[pari-sage] 03/12: Imported Upstream version 2.8-1369-g0e48e9b

Tobias Hansen thansen at moszumanska.debian.org
Sat May 23 14:30:48 UTC 2015


This is an automated email from the git hooks/post-receive script.

thansen pushed a commit to branch master
in repository pari-sage.

commit 91e28d6aede1c582ae5cd403f185433dd2d4298b
Author: Tobias Hansen <tobias.han at gmx.de>
Date:   Sun Mar 15 02:39:07 2015 +0000

    Imported Upstream version 2.8-1369-g0e48e9b
---
 AUTHORS                                            |   42 +-
 CHANGES                                            |  388 +-
 CHANGES-2.6                                        |    2 +-
 COMPAT                                             |   52 +
 Configure                                          |    5 +-
 README                                             |    4 +-
 config/Makefile.SH                                 |   35 +-
 config/extract_files                               |    2 +-
 config/genkernel                                   |    3 +-
 config/get_MANIFEST                                |    1 -
 config/get_X11                                     |   31 +-
 config/get_config_options                          |    6 +-
 config/get_dlld                                    |    2 +-
 config/get_gmp                                     |   23 +-
 config/get_kernel                                  |    2 +-
 config/get_libc                                    |   23 +-
 config/get_modld                                   |    2 +-
 config/get_perl                                    |    4 +-
 config/get_readline                                |   71 +-
 config/has_TIOCGWINSZ.c                            |    2 +-
 config/has_gettimeofday.c                          |    8 +
 config/has_mmap.c                                  |   17 +
 config/has_system.c                                |    3 +
 config/paricfg.h.SH                                |   14 +
 config/settar                                      |    7 +-
 config/version                                     |    6 +-
 doc/appa.tex                                       |   47 +-
 doc/appd.tex                                       |    8 +-
 doc/develop.tex                                    |  123 +-
 doc/gphelp.in                                      |   25 +-
 doc/parimacro.tex                                  |    7 +-
 doc/refcard.tex                                    |    9 +-
 doc/translations                                   |   15 +-
 doc/tutorial.tex                                   |   44 +-
 doc/usersFUNCS.tex                                 |  144 +-
 doc/usersch1.tex                                   |   12 +-
 doc/usersch2.tex                                   |   90 +-
 doc/usersch3.tex                                   | 3399 +++++++++-
 doc/usersch4.tex                                   |  120 +-
 doc/usersch5.tex                                   | 1480 ++++-
 doc/usersch6.tex                                   |   87 +-
 doc/usersch7.tex                                   |  212 +-
 examples/Inputrc                                   |    5 +
 examples/minigp.c                                  |   48 +-
 misc/gprc.dft                                      |   24 +-
 misc/tex2mail.in                                   |    2 +-
 src/basemath/F2x.c                                 |   31 +-
 src/basemath/F2xqE.c                               |    4 +-
 src/basemath/FF.c                                  |  113 +-
 src/basemath/Fle.c                                 |  583 ++
 src/basemath/Flx.c                                 | 1001 ++-
 src/basemath/FlxqE.c                               |  327 +-
 src/basemath/Flxq_log.c                            |   31 +-
 src/basemath/FpE.c                                 |  720 +-
 src/basemath/FpV.c                                 |  185 +-
 src/basemath/FpX.c                                 |  208 +-
 src/basemath/FpXX.c                                |  162 +-
 src/basemath/FpX_factor.c                          |  220 +-
 src/basemath/Hensel.c                              |  255 +-
 src/basemath/QX_factor.c                           |   84 +-
 src/basemath/Qfb.c                                 |   97 +-
 src/basemath/RgV.c                                 |   56 +-
 src/basemath/RgX.c                                 |  289 +-
 src/basemath/ZG.c                                  |  146 +
 src/basemath/ZV.c                                  |   81 +-
 src/basemath/ZX.c                                  |   59 +
 src/basemath/alglin1.c                             |  233 +-
 src/basemath/alglin2.c                             |  644 +-
 src/basemath/alglin3.c                             |   47 +-
 src/basemath/arith1.c                              | 1215 +++-
 src/basemath/arith2.c                              |  290 +-
 src/basemath/base1.c                               |   87 +-
 src/basemath/base2.c                               |  367 +-
 src/basemath/base3.c                               |   59 +-
 src/basemath/base4.c                               |  702 +-
 src/basemath/base5.c                               |  711 +-
 src/basemath/bb_group.c                            |  148 +-
 src/basemath/bibli1.c                              |   34 +-
 src/basemath/bibli2.c                              |  117 +-
 src/basemath/bit.c                                 |  115 +-
 src/basemath/buch1.c                               |   97 +-
 src/basemath/buch2.c                               |  422 +-
 src/basemath/buch3.c                               |  220 +-
 src/basemath/buch4.c                               |   34 +-
 src/basemath/concat.c                              |    4 +-
 src/basemath/crvwtors.c                            | 2467 +++++++
 src/basemath/ellanal.c                             |  832 +--
 src/basemath/elliptic.c                            | 2531 +++++---
 src/basemath/ellisog.c                             |  564 ++
 src/basemath/ellpadicL.c                           |  179 +
 src/basemath/elltors.c                             |  709 ++
 src/basemath/galconj.c                             |  191 +-
 src/basemath/gen1.c                                |  238 +-
 src/basemath/gen2.c                                |   88 +-
 src/basemath/gen3.c                                |  330 +-
 src/basemath/hnf_snf.c                             |  207 +-
 src/basemath/hyperell.c                            |  691 ++
 src/basemath/ifactor1.c                            |  128 +-
 src/basemath/lll.c                                 |   64 +-
 src/basemath/modsym.c                              | 2944 +++++++++
 src/basemath/nffactor.c                            |   82 +-
 src/basemath/perm.c                                |    4 +-
 src/basemath/polarit1.c                            |   67 +-
 src/basemath/polarit2.c                            |  396 +-
 src/basemath/polarit3.c                            |  448 +-
 src/basemath/polclass.c                            | 1136 ++++
 src/basemath/polmodular.c                          | 2222 +++++++
 src/basemath/prime.c                               |  154 +-
 src/basemath/qfisom.c                              |   18 +-
 src/basemath/qfsolve.c                             | 1090 ++++
 src/basemath/random.c                              |  225 +-
 src/basemath/rootpol.c                             |  822 ++-
 src/basemath/subcyclo.c                            |    4 +-
 src/basemath/subgroup.c                            |    5 +-
 src/basemath/trans1.c                              |  100 +-
 src/basemath/trans2.c                              |   64 +-
 src/basemath/trans3.c                              |  389 +-
 src/basemath/volcano.c                             |  422 ++
 src/desc/deftune                                   |   45 +
 src/desc/doc_make                                  |    1 +
 src/desc/gen_proto                                 |   40 +-
 src/desc/gen_tune                                  |  114 +
 src/desc/whatnow                                   |   81 -
 src/funclist                                       |  313 +-
 src/functions/algebras/algabsdim                   |   14 +
 src/functions/algebras/algadd                      |   14 +
 src/functions/algebras/algalgtobasis               |   16 +
 src/functions/algebras/algaut                      |   16 +
 src/functions/algebras/algb                        |   16 +
 src/functions/algebras/algbasis                    |   20 +
 src/functions/algebras/algbasistoalg               |   18 +
 src/functions/algebras/algcenter                   |   34 +
 src/functions/algebras/algcentralproj              |   27 +
 src/functions/algebras/algchar                     |   13 +
 src/functions/algebras/algcharpoly                 |   21 +
 src/functions/algebras/algdecomposition            |    9 +
 src/functions/algebras/algdegree                   |   13 +
 src/functions/algebras/algdim                      |   15 +
 src/functions/algebras/algdisc                     |   21 +
 src/functions/algebras/algdivl                     |   10 +
 src/functions/algebras/algdivr                     |    7 +
 src/functions/algebras/alghasse                    |   21 +
 src/functions/algebras/alghassef                   |   18 +
 src/functions/algebras/alghassei                   |   16 +
 src/functions/algebras/algindex                    |   28 +
 src/functions/algebras/alginit                     |  146 +
 src/functions/algebras/alginv                      |   14 +
 src/functions/algebras/alginvbasis                 |   21 +
 src/functions/algebras/algisassociative            |   20 +
 src/functions/algebras/algiscommutative            |   18 +
 src/functions/algebras/algisdivision               |   28 +
 src/functions/algebras/algisdivl                   |   20 +
 src/functions/algebras/algisinv                    |   19 +
 src/functions/algebras/algisramified               |   28 +
 src/functions/algebras/algissemisimple             |   21 +
 src/functions/algebras/algissimple                 |   28 +
 src/functions/algebras/algissplit                  |   28 +
 src/functions/algebras/algmul                      |   14 +
 src/functions/algebras/algmultable                 |   59 +
 src/functions/algebras/algneg                      |   14 +
 src/functions/algebras/algnorm                     |   18 +
 src/functions/algebras/algpoleval                  |    7 +
 src/functions/algebras/algpow                      |   14 +
 src/functions/algebras/algprimesubalg              |   22 +
 src/functions/algebras/algquotient                 |   19 +
 src/functions/algebras/algradical                  |   34 +
 src/functions/algebras/algramifiedplaces           |   18 +
 src/functions/algebras/algrandom                   |    7 +
 src/functions/algebras/algrelmultable              |   31 +
 src/functions/algebras/algsimpledec                |   15 +
 src/functions/algebras/algsplittingdata            |   45 +
 src/functions/algebras/algsplittingfield           |   29 +
 src/functions/algebras/algsplittingmatrix          |   19 +
 src/functions/algebras/algsqr                      |   14 +
 src/functions/algebras/algsub                      |   14 +
 src/functions/algebras/algsubalg                   |   17 +
 src/functions/algebras/algtableinit                |   52 +
 src/functions/algebras/algtensor                   |   13 +
 src/functions/algebras/algtrace                    |   17 +
 src/functions/algebras/algtype                     |   45 +
 src/functions/conversions/Ser                      |    2 +-
 src/functions/conversions/digits                   |    1 +
 src/functions/conversions/fromdigits               |   14 +
 src/functions/conversions/oo                       |   11 +
 src/functions/conversions/precision                |    1 +
 src/functions/conversions/random                   |    2 +-
 src/functions/conversions/sizedigit                |   18 +-
 src/functions/conversions/valuation                |   11 +-
 src/functions/conversions/varhigher                |   63 +
 src/functions/conversions/variable                 |   14 +-
 src/functions/conversions/variables                |   31 +
 src/functions/conversions/varlower                 |   82 +
 src/functions/default/breakloop                    |    2 +-
 src/functions/default/compatible                   |   40 +-
 src/functions/default/echo                         |    2 +-
 src/functions/default/graphcolormap                |    2 +-
 src/functions/default/graphcolors                  |    2 +-
 src/functions/default/help                         |    2 +-
 src/functions/default/histfile                     |    2 +-
 src/functions/default/lines                        |    2 +-
 src/functions/default/linewrap                     |    2 +-
 src/functions/default/parisize                     |   17 +-
 src/functions/default/parisizemax                  |   19 +
 src/functions/default/prompt                       |    2 +-
 src/functions/default/prompt_cont                  |    2 +-
 src/functions/default/psfile                       |    2 +-
 src/functions/default/readline                     |    2 +-
 src/functions/default/recover                      |    2 +-
 src/functions/default/strictmatch                  |    9 +-
 src/functions/default/threadsizemax                |   15 +
 src/functions/default/timer                        |    2 +-
 src/functions/elliptic_curves/ellL1                |   18 +-
 src/functions/elliptic_curves/ellap                |   10 +-
 src/functions/elliptic_curves/ellbil               |   11 +-
 src/functions/elliptic_curves/ellcard              |    2 +-
 src/functions/elliptic_curves/elleisnum            |    2 +-
 .../elliptic_curves/ellformaldifferential          |   22 +
 src/functions/elliptic_curves/ellformalexp         |   18 +
 src/functions/elliptic_curves/ellformallog         |   17 +
 src/functions/elliptic_curves/ellformalpoint       |   23 +
 src/functions/elliptic_curves/ellformalw           |   17 +
 src/functions/elliptic_curves/ellheight            |   32 +-
 src/functions/elliptic_curves/ellheightmatrix      |    2 +-
 src/functions/elliptic_curves/ellinit              |    6 +
 src/functions/elliptic_curves/ellisdivisible       |   27 +
 src/functions/elliptic_curves/ellisogeny           |   23 +
 src/functions/elliptic_curves/ellisogenyapply      |   32 +
 src/functions/elliptic_curves/ellissupersingular   |   22 +
 src/functions/elliptic_curves/elllocalred          |    9 +-
 .../elliptic_curves/ellnonsingularmultiple         |   19 +
 src/functions/elliptic_curves/ellorder             |   20 +-
 src/functions/elliptic_curves/ellpadicL            |   64 +
 src/functions/elliptic_curves/ellpadicfrobenius    |   27 +
 src/functions/elliptic_curves/ellpadicheight       |   65 +
 src/functions/elliptic_curves/ellpadicheightmatrix |   14 +
 src/functions/elliptic_curves/ellpadiclog          |   12 +
 src/functions/elliptic_curves/ellpadics2           |   28 +
 src/functions/elliptic_curves/elltors              |   34 +-
 src/functions/elliptic_curves/ellxn                |   13 +
 src/functions/elliptic_curves/genus2red            |   22 +-
 src/functions/elliptic_curves/hyperellcharpoly     |   15 +
 .../elliptic_curves/hyperellpadicfrobenius         |   17 +
 src/functions/gp2c/clone                           |    3 +
 src/functions/gp2c_internal/_cast                  |   10 +
 src/functions/gp2c_internal/_gc_needed             |    4 +
 src/functions/gp2c_internal/_tovec                 |   24 +-
 src/functions/gp2c_internal/_typedef               |    4 +
 src/functions/gp2c_internal/_wrap                  |    7 +
 src/functions/linear_algebra/matkerint             |   20 +-
 src/functions/linear_algebra/matqr                 |    4 +-
 src/functions/linear_algebra/qfparam               |   31 +
 src/functions/linear_algebra/qfsolve               |   26 +
 src/functions/linear_algebra/vecsearch             |    6 +-
 src/functions/linear_algebra/vecsum                |   11 +-
 src/functions/modular_forms/msatkinlehner          |   24 +
 src/functions/modular_forms/mscuspidal             |   39 +
 src/functions/modular_forms/mseisenstein           |   31 +
 src/functions/modular_forms/mseval                 |   41 +
 src/functions/modular_forms/msfromell              |   34 +
 src/functions/modular_forms/mshecke                |   41 +
 src/functions/modular_forms/msinit                 |   23 +
 src/functions/modular_forms/msissymbol             |   26 +
 src/functions/modular_forms/msnew                  |   18 +
 src/functions/modular_forms/mspathgens             |   50 +
 src/functions/modular_forms/mspathlog              |   35 +
 src/functions/modular_forms/msqexpansion           |   25 +
 src/functions/modular_forms/mssplit                |   29 +
 src/functions/modular_forms/msstar                 |   16 +
 src/functions/number_fields/bnrgaloisapply         |   10 +
 src/functions/number_fields/bnrgaloismatrix        |   20 +
 src/functions/number_fields/bnrinit                |    4 +-
 src/functions/number_fields/bnrisgalois            |   32 +
 src/functions/number_fields/galoissubgroups        |    2 +-
 src/functions/number_fields/idealprimedec          |   21 +-
 src/functions/number_fields/idealval               |    8 +-
 src/functions/number_fields/nfbasis                |    2 +-
 src/functions/number_fields/nfcompositum           |   66 +
 src/functions/number_fields/nfdisc                 |    4 +-
 src/functions/number_fields/nfeltval               |   40 +-
 src/functions/number_fields/nfgrunwaldwang         |   42 +
 src/functions/number_fields/nfhnf                  |   15 +-
 src/functions/number_fields/nfinit                 |    6 +-
 src/functions/number_fields/nfsnf                  |   20 +-
 src/functions/number_fields/nfsplitting            |   26 +
 src/functions/number_fields/polcompositum          |   30 +-
 src/functions/number_fields/rnfidealabstorel       |    2 +-
 src/functions/number_fields/rnfinit                |   15 +-
 src/functions/number_fields/rnfnormgroup           |    4 +-
 src/functions/number_theoretical/content           |    3 +-
 src/functions/number_theoretical/ffgen             |   12 +-
 src/functions/number_theoretical/ispower           |    2 +-
 src/functions/number_theoretical/ispowerful        |    6 +-
 src/functions/number_theoretical/ispseudoprime     |    4 +-
 .../number_theoretical/ispseudoprimepower          |   18 +
 src/functions/number_theoretical/lcm               |   12 +-
 src/functions/number_theoretical/qfbclassno        |   38 +-
 src/functions/number_theoretical/qfbredsl2         |   15 +
 src/functions/number_theoretical/quaddisc          |   12 +-
 src/functions/number_theoretical/stirling          |    2 +-
 src/functions/number_theoretical/sumdigits         |   18 +-
 src/functions/number_theoretical/zncoppersmith     |   14 +-
 src/functions/operators/powers                     |    8 +
 src/functions/polynomials/bezoutres                |    2 +-
 src/functions/polynomials/eval                     |    4 +-
 src/functions/polynomials/factorpadic              |    4 +-
 src/functions/polynomials/polclass                 |   14 +
 src/functions/polynomials/polcoeff                 |    5 +-
 src/functions/polynomials/poldegree                |   20 +-
 src/functions/polynomials/polmodular               |   29 +
 src/functions/polynomials/polrootsreal             |   36 +
 src/functions/polynomials/polsturm                 |   36 +-
 src/functions/polynomials/polzagier                |   13 +-
 src/functions/polynomials/serlaplace               |    3 +-
 src/functions/polynomials/thue                     |    2 +-
 src/functions/polynomials/thueinit                 |   52 +-
 src/functions/programming/alarm                    |    1 -
 src/functions/programming/allocatemem              |   86 +-
 src/functions/programming/extern                   |    3 +-
 src/functions/programming/externstr                |    1 -
 src/functions/programming/fold                     |   23 +
 src/functions/programming/getabstime               |    5 +-
 src/functions/programming/getheap                  |    2 +-
 src/functions/programming/gettime                  |    4 +-
 src/functions/programming/getwalltime              |   12 +
 src/functions/programming/iferr                    |    4 -
 src/functions/programming/input                    |    3 +-
 src/functions/programming/localprec                |   51 +
 src/functions/programming/parfor                   |    4 +-
 src/functions/programming/parforprime              |    6 +-
 src/functions/programming/read                     |    3 +-
 src/functions/programming/readstr                  |    1 -
 src/functions/programming/self                     |   12 +
 src/functions/programming/system                   |    5 +-
 src/functions/sums/intmellininvshort               |    5 +-
 src/functions/sums/intnum                          |   32 +-
 src/functions/sums/intnuminit                      |    4 +-
 src/functions/sums/sumalt                          |   40 +-
 src/functions/sums/sumpos                          |   14 +-
 src/gp/{highlvl.c => emacs.c}                      |   10 +-
 src/gp/gp.c                                        | 2623 +-------
 src/gp/gp.h                                        |   57 +-
 src/gp/gp_default.h                                |   20 -
 src/gp/gp_init.c                                   |  117 -
 src/gp/gp_init.h                                   |   20 +-
 src/gp/gp_rl.c                                     |  347 +-
 src/gp/highlvl.h                                   |   58 +-
 src/gp/texmacs.c                                   |  268 +
 src/gp/whatnow.c                                   |   50 +-
 src/gp/whatnow.h                                   | 1319 ++--
 src/graph/plotQt.c                                 |    6 +-
 src/graph/plotQt4.c                                |    6 +-
 src/graph/plotWin32.c                              |    2 +-
 src/graph/plotX.c                                  |    4 +-
 src/graph/plotfltk.c                               |    6 +-
 src/graph/plotport.c                               |  105 +-
 src/graph/plotps.c                                 |    6 +-
 src/headers/paricom.h                              |   20 +-
 src/headers/paridecl.h                             |  648 +-
 src/headers/parierr.h                              |    2 +-
 src/headers/parigen.h                              |   19 +-
 src/headers/pariinl.h                              |  150 +-
 src/headers/parinf.h                               |   23 +-
 src/headers/pariold.h                              |   10 +-
 src/headers/paripriv.h                             |  165 +-
 src/headers/paristio.h                             |   88 +-
 src/headers/parisys.h                              |    2 +-
 src/headers/paritune.h                             |  146 +-
 src/kernel/alpha/asm1.h                            |    2 +-
 src/kernel/gmp/mp.c                                |   44 +-
 src/kernel/gmp/tune.h                              |  144 +-
 src/kernel/none/add.c                              |   10 +-
 src/kernel/none/addll.h                            |    2 +-
 src/kernel/none/cmp.c                              |   19 +-
 src/kernel/none/divll.h                            |    2 +-
 src/kernel/none/divll_pre.h                        |  133 +
 src/kernel/none/gcd.c                              |    3 +-
 src/kernel/none/gcdext.c                           |   10 +-
 src/kernel/none/gcdll.c                            |   12 +
 src/kernel/none/invmod.c                           |   18 +-
 src/kernel/none/level1.h                           |   81 +-
 src/kernel/none/mp.c                               |  205 +-
 src/kernel/none/mp_indep.c                         |   77 +-
 src/kernel/none/ratlift.c                          |    6 +-
 src/kernel/none/tune-gen.h                         |   82 +-
 src/kernel/none/tune.h                             |  150 +-
 src/language/anal.c                                |  451 +-
 src/language/anal.h                                |    4 +-
 src/language/compat.c                              |  722 ---
 src/language/compile.c                             |  213 +-
 src/language/default.c                             |  134 +-
 src/language/default.h                             |   72 +-
 src/language/es.c                                  |  322 +-
 src/language/eval.c                                |  258 +-
 src/{gp/gp.c => language/gplib.c}                  | 1651 ++---
 src/language/hash.c                                |   92 +-
 src/language/init.c                                |  631 +-
 src/language/init.h                                | 1094 ++--
 src/language/intnum.c                              |  326 +-
 src/language/members.c                             |    1 +
 src/language/opcode.h                              |    5 +-
 src/language/parse.c                               | 1493 +++--
 src/language/parse.h                               |    7 +-
 src/language/parse.y                               |    6 +-
 src/language/parsec.h                              |   25 +-
 src/language/sumiter.c                             |  481 +-
 src/language/tree.h                                |    2 +-
 src/modules/algebras.c                             | 4482 +++++++++++++
 src/modules/aprcl.c                                |    6 +-
 src/modules/ellsea.c                               |  595 +-
 src/modules/galois.c                               |    5 +-
 src/modules/genus2red.c                            |   67 +-
 src/modules/krasner.c                              |   31 +-
 src/modules/kummer.c                               |  358 +-
 src/modules/mpqs.c                                 |   16 +-
 src/modules/part.c                                 |   68 +-
 src/modules/stark.c                                |  107 +-
 src/modules/subfield.c                             |    4 +-
 src/modules/thue.c                                 |  853 ++-
 src/mt/mpi.c                                       |   34 +-
 src/mt/pthread.c                                   |  110 +-
 src/mt/single.c                                    |    2 +-
 src/systems/mingw/mingw.c                          |   30 +
 src/systems/mingw/mingw.h                          |    1 +
 src/test/32/agm                                    |    4 +
 src/test/32/algebras                               | 3261 ++++++++++
 src/test/32/apply                                  |    4 +
 src/test/32/bnr                                    |   12 +-
 src/test/32/bnrL1                                  |   78 +-
 src/test/32/bnrisgalois                            |    9 +
 src/test/32/characteristic                         |    4 +
 src/test/32/chinese                                |    5 +-
 src/test/32/{agm => classpoly}                     |    0
 src/test/32/cmp                                    |   19 +-
 src/test/32/compat                                 | 6853 +++++++++++++-------
 src/test/32/contfrac                               |    4 +-
 src/test/32/deriv                                  |   12 +-
 src/test/32/diffop                                 |    2 +-
 src/test/32/digits                                 |    8 +-
 src/test/32/dirmul                                 |   26 +-
 src/test/32/div                                    |   16 +-
 src/test/32/ell                                    |  296 +-
 src/test/32/ellanal                                |   22 +-
 src/test/32/ellff                                  |    5 +-
 src/test/32/elliptic                               |   15 +-
 src/test/32/ellisogeny                             |    7 +
 src/test/32/ellnf                                  |   16 +
 src/test/32/ellpadic                               |   80 +
 src/test/32/ellsea                                 |   10 +-
 src/test/32/elltors                                |   85 +
 src/test/32/ellweilpairing                         |    3 +-
 src/test/32/equal                                  |   49 +
 src/test/32/err                                    |   19 +-
 src/test/32/eval                                   |    3 +
 src/test/32/extract                                |   32 +-
 src/test/32/factormod                              |    5 +-
 src/test/32/ff                                     |  163 +-
 src/test/32/fflog                                  |   26 +
 src/test/32/for                                    |   17 -
 src/test/32/forvec                                 |   96 +
 src/test/32/galoisinit                             |   16 +-
 src/test/32/gamma                                  |    8 +-
 src/test/32/genus2red                              |   40 +-
 src/test/32/help                                   |   33 +-
 src/test/32/history                                |   17 +-
 src/test/32/hyperell                               |  101 +
 src/test/32/ideal                                  |    5 +
 src/test/32/idealramgroups                         |    4 +-
 src/test/32/incgam                                 |   12 +-
 src/test/32/intnum                                 |   65 +-
 src/test/32/io                                     |    3 +-
 src/test/32/ispower                                |   12 +-
 src/test/32/isprime                                |    3 +-
 src/test/32/iterator                               |   37 +
 src/test/32/kernel                                 |   38 +-
 src/test/32/krasner                                |   31 +-
 src/test/32/lambert                                |    5 +-
 src/test/32/lex                                    |   12 +-
 src/test/32/lindep                                 |    4 +-
 src/test/32/linear                                 |   54 +-
 src/test/32/list                                   |    6 +
 src/test/32/mat                                    |   93 +-
 src/test/32/matsnf                                 |  430 +-
 src/test/32/member                                 |  120 +-
 src/test/32/modfun                                 |    4 +-
 src/test/32/{agm => modpoly}                       |    0
 src/test/32/modsym                                 |  187 +
 src/test/32/modular                                |   28 +-
 src/test/32/nf                                     |   94 +-
 src/test/32/nfields                                |  184 +-
 src/test/32/nfsplitting                            |   48 +
 src/test/32/objets                                 |    3 +-
 src/test/32/op                                     |    6 +
 src/test/32/padic                                  |   30 +-
 src/test/32/ploth                                  |  155 +-
 src/test/32/pol                                    |    9 +-
 src/test/32/{agm => polclass}                      |    0
 src/test/32/polmod                                 |    4 +-
 src/test/32/{agm => polmodular}                    |    0
 src/test/32/polred                                 |   10 +-
 src/test/32/polylog                                |    6 +-
 src/test/32/polyser                                |    9 +-
 src/test/32/pow                                    |    8 +-
 src/test/32/prec                                   |    3 +-
 src/test/32/primes                                 |    7 +-
 src/test/32/printf                                 |    5 +-
 src/test/32/program                                |    8 +-
 src/test/32/qfb                                    |   11 +-
 src/test/32/qfbclassno                             |   16 +
 src/test/32/qfsolve                                |  142 +
 src/test/32/quadray                                |   16 +
 src/test/32/random                                 |   28 +-
 src/test/32/real                                   |   27 +-
 src/test/32/resultant                              |    5 +-
 src/test/32/rnf                                    |   47 +
 src/test/32/rnfkummer                              |  253 +-
 src/test/32/rootsreal                              |   64 +
 src/test/32/round4                                 |    3 +-
 src/test/32/select                                 |    4 +-
 src/test/32/self                                   |    2 +
 src/test/32/ser                                    |   44 +
 src/test/32/size                                   |    3 +-
 src/test/32/str                                    |    5 +-
 src/test/32/subgroup                               |   29 +-
 src/test/32/sumdiv                                 |    3 +
 src/test/32/sumiter                                |    4 +-
 src/test/32/thue                                   |   48 +-
 src/test/32/trans2                                 |    4 +-
 src/test/32/valuation                              |   12 +-
 src/test/32/vararg                                 |   27 +
 src/test/32/variable                               |   16 +-
 src/test/32/whatnow                                |    4 +-
 src/test/32/zetak                                  |   10 +-
 src/test/32/zn                                     |    7 +-
 src/test/64/bnr                                    |   44 -
 src/test/64/bnrL1                                  |   33 -
 src/test/64/compat                                 | 2593 --------
 src/test/64/ell                                    |  405 --
 src/test/64/ellanal                                |   14 -
 src/test/64/ff                                     |  283 -
 src/test/64/incgam                                 |   73 -
 src/test/64/isprime                                |   25 -
 src/test/64/kernel                                 |   23 -
 src/test/64/member                                 |  319 -
 src/test/64/nf                                     |  361 --
 src/test/64/nfields                                |  751 ---
 src/test/64/random                                 |   30 -
 src/test/64/real                                   |    3 -
 src/test/64/rnfkummer                              |  175 -
 src/test/in/agm                                    |    1 +
 src/test/in/algebras                               | 2090 ++++++
 src/test/in/apply                                  |    5 +
 src/test/in/bnrL1                                  |   12 +-
 src/test/in/bnrisgalois                            |    4 +
 src/test/in/characteristic                         |    2 +
 src/test/in/chinese                                |    1 +
 src/test/in/cmp                                    |   18 +-
 src/test/in/compat                                 | 1012 ++-
 src/test/in/deriv                                  |    4 +
 src/test/in/digits                                 |    7 +-
 src/test/in/dirmul                                 |   17 +
 src/test/in/div                                    |    5 +
 src/test/in/ell                                    |   81 +-
 src/test/in/ellanal                                |   12 +-
 src/test/in/ellff                                  |   11 +-
 src/test/in/elliptic                               |    9 +-
 src/test/in/ellisogeny                             |  286 +
 src/test/in/ellissupersingular                     |   41 +
 src/test/in/ellnf                                  |   32 +
 src/test/in/ellpadic                               |   81 +
 src/test/in/ellsea                                 |   11 +
 src/test/in/elltors                                |  123 +
 src/test/in/ellweilpairing                         |    1 +
 src/test/in/equal                                  |   30 +
 src/test/in/err                                    |    5 +-
 src/test/in/eval                                   |    2 +
 src/test/in/extract                                |   10 +
 src/test/in/factormod                              |    2 +
 src/test/in/ff                                     |   36 +-
 src/test/in/fflog                                  |   37 +
 src/test/in/for                                    |    6 -
 src/test/in/forvec                                 |   25 +
 src/test/in/gamma                                  |    1 +
 src/test/in/genus2red                              |  126 +-
 src/test/in/help                                   |    6 +
 src/test/in/hyperell                               |   45 +
 src/test/in/ideal                                  |    9 +
 src/test/in/incgam                                 |    2 +-
 src/test/in/intnum                                 |   32 +-
 src/test/in/ispower                                |   10 +
 src/test/in/isprime                                |    2 +
 src/test/in/iterator                               |   24 +
 src/test/in/krasner                                |   20 +-
 src/test/in/lambert                                |   23 +
 src/test/in/lex                                    |   12 +
 src/test/in/list                                   |    8 +
 src/test/in/mat                                    |   37 +
 src/test/in/matsnf                                 |   13 +-
 src/test/in/member                                 |    2 +-
 src/test/in/modfun                                 |    1 +
 src/test/in/modsym                                 |   96 +
 src/test/in/modular                                |   23 +
 src/test/in/nf                                     |   23 +-
 src/test/in/nffactor                               |    2 +-
 src/test/in/nfields                                |    9 +-
 src/test/in/nfsplitting                            |   10 +
 src/test/in/objets                                 |    3 +-
 src/test/in/op                                     |    6 +
 src/test/in/padic                                  |    2 +-
 src/test/in/parallel                               |    2 +
 src/test/in/ploth                                  |   52 +-
 src/test/in/pol                                    |    8 +
 src/test/in/polclass                               |   66 +
 src/test/in/polmodular                             |  150 +
 src/test/in/polred                                 |    4 +
 src/test/in/polyser                                |    3 +-
 src/test/in/pow                                    |    3 +
 src/test/in/prec                                   |    1 +
 src/test/in/primes                                 |    4 +
 src/test/in/printf                                 |    1 +
 src/test/in/qfb                                    |   11 +-
 src/test/in/qfbclassno                             |   16 +
 src/test/in/qfsolve                                |   35 +
 src/test/in/quadray                                |   17 +
 src/test/in/random                                 |    1 +
 src/test/in/real                                   |   39 +-
 src/test/in/resultant                              |    6 +
 src/test/in/rnf                                    |   15 +
 src/test/in/rnfkummer                              |   10 +-
 src/test/in/rootsreal                              |   45 +
 src/test/in/round                                  |    4 +-
 src/test/in/round4                                 |    8 +-
 src/test/in/select                                 |    3 +
 src/test/in/self                                   |    1 +
 src/test/in/ser                                    |   31 +
 src/test/in/size                                   |    1 +
 src/test/in/subgroup                               |    6 +
 src/test/in/sumdiv                                 |    3 +
 src/test/in/thue                                   |   42 +
 src/test/in/valuation                              |   10 +-
 src/test/in/vararg                                 |   21 +
 src/test/in/variable                               |   19 +
 src/test/in/zn                                     |    5 +
 src/test/kerntest.c                                |   19 +-
 src/test/tune.c                                    |   55 +-
 src/whatnow                                        |  653 --
 645 files changed, 61347 insertions(+), 27065 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index 5a21ab2..ef45962 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -21,41 +21,45 @@ Major contributors (large modules written or rewritten from scratch):
 
   Bill ALLOMBERT: GP2C, the GP parser, extension of the GP language
     (my, closures), GMP kernel, modular kernel, ffinit, galois* routines,
-    subcyclo, black-box groups, the elldata and galdata package,
-    multithread model, PARI description system, FLTK support, Bug tracking
-    system, administration of pari.math.u-bordeaux.fr, the
+    subcyclo, black-box groups, elliptic curves, the elldata and galdata
+    package, multithread model, PARI description system, FLTK support,
+    Bug tracking system, administration of pari.math.u-bordeaux.fr, the
     http://pari.math.u-bordeaux.fr website
   Christian BATUT: 68k multiprecision kernel, Linear algebra, lattices
   Karim BELABAS: current project leader, native multiprecision kernel, modular
     kernel, polynomial arithmetic, polynomial factorization (finite fields,
     number fields), LLL, primality and compositeness tests, number fields,
-    polgalois and the galdata package, transcendental functions, install(),
-    extension of the GP language (next/break/return, local, op=, default()),
-    gphelp, Configure, readline, man pages, documentation layout, reference card
-    and user's manuals, the FAQ, the http://pari.math.u-bordeaux.fr website
-    the PARI resource pages.
-  Dominique BERNARDI: the original gp interpreter, ECM, elliptic curves
+    polgalois and the galdata package, elliptic curves, qfsolve, transcendental
+    functions, install(), extension of the GP language (next/break/return,
+    local, op=, default()), gphelp, Configure, readline, man pages,
+    documentation layout, reference card and user's manuals, the FAQ, the
+    http://pari.math.u-bordeaux.fr website.
+  Dominique BERNARDI: the original gp interpreter, ECM, original
+    elliptic curves implementation
   Henri COHEN: original designer and project leader, native multiprecision
     kernel, arithmetic functions, LLL, transcendental functions, number fields,
-    elliptic curves
+    original elliptic curves implementation
   Francisco DIAZ Y DIAZ: number fields (class groups, units)
   Yves EICHENLAUB: original polgalois implementation
   Xavier GOURDON: polroots, initial Karatsuba/Toom Cook/fft implementations
   Louis GRANBOULAN: breakup of monolithic PARI into modules, first GMP
     kernel, first Configure
-  Loic GRENIE: bnfinit() rewrite, openMP / MPI implementations
+  Loic GRENIE: bnfinit() rewrite, openMP / MPI implementations,
+    polrootsreal/polsturm
   Bruno HAIBLE: micro assembly implementations, DOS/Windows support
-  Guillaume HANROT: thue, zncoppersmith
-  Pascal LETARD: basic number field (round2, initial round4)
-  Jean-Francois MESTRE: elliptic curves
+  Guillaume HANROT: thue, zncoppersmith, initial polrootsreal implementation
+  Pascal LETARD: basic number fields (round2, initial round4)
+  Jean-Francois MESTRE: original elliptic curves implementation
   Gerhard NIKLASCH: binary powering, integer extended gcd and rational
     reconstruction, primality and compositeness test, integer factorization,
     documentation layout, AIX and Solaris support, first PARI web site.
   Michel OLIVIER: 68k multiprecision kernel, number fields, original polgalois
     and nfsubfields implementation
+  Aurel PAGE: central simple algebra package (?8)
   Thomas PAPANIKOlAOU: MPQS integration, Pari-Lidia project
-  Xavier ROBLOT: MPQS integration, Stark, original nffactor
-  Denis SIMON: Norm equations, S-units, Hilbert symbols
+  Xavier ROBLOT: MPQS integration, Stark, original nffactor, padicfields
+  Denis SIMON: Norm equations, S-units, Hilbert symbols, original qfsolve
+    implementation
   Emmanuel TOLLIS: primedec, zetak
   Ilya ZAKHAREVITCH: prime sieves, gphelp, tex2mail, major cleanup of the
     graphics and GP parser code, gnuplot support, readline support,
@@ -68,8 +72,9 @@ kindly remind us if you have been forgotten!
 AF = Aurimas Fiseras
 AM = Alex V. Myltsev
 AMe= Anton Mellit
-AW = Aleksander Wittlin
+AP = Aurel Page
 AS = Andy Stubbs
+AW = Aleksander Wittlin
 BA = Bill Allombert
 BD = Bill Daly
 BG = Brian Gladman
@@ -90,6 +95,7 @@ GN = Gerhard Niklasch
 GT = Glenn Thobe
 GTo= Gonzalo Tornaria
 HC = Henri Cohen
+HIL= Hamish Ivey-Law
 HR = Harvey Rose
 IK = Iwao Kimura
 IM = Ivan Middleton
@@ -128,6 +134,8 @@ SG = Scott Garee
 TH = Teluhiko Hilano
 TP = Thomas Papanikolaou
 VB = Vasili Burdo
+VBr= Volker Braun
 VL = Vincent Lefevre
 XR = Xavier Roblot
 YU = Yoshiaki Uchikawa
+WH = William Hart
diff --git a/CHANGES b/CHANGES
index 086ccdb..eed5cef 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,58 +1,346 @@
 # $Id$
 Bug numbers refer to the BTS at http://pari.math.u-bordeaux.fr/Bugs/
 
-Done for version 2.7.2 (released 19/09/2014):
-[last column crossreferences current development release 2.8.0]
+Done for version 2.8.0 (released ??/??/2015):
 
   Fixed
-    1- gaffsg(0, t_PADIC): wrong valuation                                [F21]
-    2- (t_INTMOD with word-sized modulus)^(huge negative power) [#1584]   [F24]
-    3- (gp -p N) or (primelimit=N in gprc_ for N >= 436273290 resulted in an
+    1- make install fails on OS/X: ln -s libpari.dylib libpari.dylib fails
+    2- Q_pvalrem(t_FRAC) => wrong result
+    3- [] == 0 but []~ != 0  (now []~ == 0 as well) [#1560]
+BA  4- test-kernel did not work when using --mt=pthread
+BA  5- ellheegner was using too much memory in some case
+    6- ellap can overflow on 32-bit machine [#1558]
+       ellap(ellinit([582304190,64196421]),2147438927) -> overflow
+       ellap(ellinit([-1137195,489565862]),2038074751) -> wrong result
+    7- nfhilbert(K,x,y, P above 2) could give wrong results [#1561]
+    8- rnfkummer sometimes failed to return an answer: error or oo loop.
+       Relied on exhaustive enumeration of an Fp-vector space, some of
+       whose elements would trigger an error. Replace by Fp-linear algebra
+       that directly picks the correct line (O(d^3) algo instead of O(p^d),
+       and no failures). Only compute the defining poly for the right element.
+XR  9- padicfields(huge p, d) was very slow [even though ramification is tame]
+   10- gcd(1/2, 1+I*1.) -> SEGV [#1563], 2.5.5 returned the wrong answer 1/2
+   11- mathnf(t_VEC) could corrupt input (change sign)
+   12- [libpari] RgM_transmul did not work
+   13- [libpari] Fq_issquare didn't support T=NULL
+   14- [libpari] nfpow_u didn't handle non-integral rational numbers
+   15- eint1(0) -> stack overflow [#1568]
+   16- liftint(List([0])) -> gerepile bug
+   17- factorint(n,flag): flag was ignored when n fit into a long
+   18- factor(n,lim): lim was ignored when n fit into a long
+   19- nfrootsQ(t_POL with leading coeff -1) could miss some solutions, e.g.
+       nfroots(,-y^2-24476*y+119814917) -> [] instead of [-28657,4181]
+   20- precprime(1) -> invalid t_INT [#1576]
+   21- gaffsg(0, t_PADIC): wrong valuation
+   22- thue(f^e*g, ...), e even, (f,g)=1 missed solutions such that f<0
+   23- faster znlog when p-1 has only smallish prime factors.
+   24- (t_INTMOD with word-sized modulus)^(huge negative power) wrong [#1584]
+   25- (gp -p N) or (primelimit=N in gprc_ for N >= 436273290 resulted in an
        incorrect primetable. N.B. Such commands are now useless: needed primes
-       are produced dynamically anyway.                                   [F25]
-    4- monomial(exact zero, d, v) returned an invalid t_POL / t_RFRAC     [F26]
-    5- contfracpnqn(v, n) returned partial quotients p[-1]/q[-1] ...
-       p[n-1]/q[n-1], instead of the documented p[0]/q[0] ... p[n]/q[n]   [F27]
-    6- factor((3+4*I)/25) -> factor 2+I had 0 exponent [#1586]            [F29]
-BA  7- iferr() could crash if some component of the t_ERROR were clones.  [F31]
-    8- nffactor() could overflow the stack when default accuracy too low  [F32]
-BA  9- obsolete use of E=[a1,a2,a3,a4,a6] in ellmul crashed  [#1589]      [F33]
-   10- incorrect rounding in mulrr/divrr for one-word precision reals     [F34]
-BA 11- multiif did not handle correctly return() in conditions [#1590]    [F35]
-   12- [0..5] -> [0,0,0,0,0] on some architectures                        [F36]
-   13- is_gener_Fp could return wrong results                             [F37]
-   14- Fq_sqrtn(t_INT,..,&zeta) could return a wrong root of 1            [F38]
-   15- bnfinit: SEGV due to precision issues [#1592]                      [F39]
-   16- zm_zc_mul only worked for square zm matrices                       [F40]
-   17- genus2red(0,27*x^5+97*x^4+118*x^3+60*x^2+13*x+1,3) -> bug [#1596]  [F41]
-   18- [gphelp] oo loop when $COLUMNS too small [#1594]                   [F42]
-   19- genus2red(x,-x^6-3*x^4-10*x^2-1,3) -> impossible inverse [#1597]   [F43]
-   20- factoru(1) returned a t_MAT instead of the expected "matsmall"     [F44]
-   21- FpM_charpoly wrong in small characteristic [#1602]                 [F45]
-   22- when compatible = 3; series() used a random precision              [F50]
-   23- genus2red(0,6*x^6+5*x^4+x^2+1,7) -> impossible inverse [#1597]     [F51]
-   24- isprime() could crash on large input [#1604]                       [F52]
-   25- genus2red(x^3+1,1) -> type error [#1597]                           [F53]
-   26- gphelp did not handle === correctly [#1603]                        [F54]
-   27- FpXY_evaly() wrong when evaluating at 0                            [F56]
-   28- [mingw] gp could crash at start up [#1607]                         [F57]
+       are produced dynamically anyway.
+   26- monomial(exact zero, d, v) returned an invalid t_POL / t_RFRAC
+   27- contfracpnqn(v, n) returned partial quotients p[-1]/q[-1] ...
+       p[n-1]/q[n-1], instead of the documented p[0]/q[0] ... p[n]/q[n] [#1580]
+   28- isprime(N, 0) was often slower than either of isprime(N, 1 or 2)
+   29- factor((3+4*I)/25) -> factor 2+I had 0 exponent [#1586]
+   30- made qfbclassno more reliable (fixes all counter examples in [#1411])
+BA 31- iferr() could crash if some component of the t_ERROR were clones.
+   32- nffactor() could overflow the stack when default accuracy too low: e.g.
+       nffactor(y^2-22, x^2+926246528884912528275985458927067632*y-4344481316563541186659879867597013188)
+   33- some elliptic curve functions accepted (elladd, ellmul) a Weierstrass
+       5-uple [a1,a2,a3,a4,a6] instead of an ell structure. No longer.
+       Now only ellinit and ellchangecurve allow this syntax.
+   34- incorrect rounding in mulrr/divrr for one-word precision reals.
+BA 35- multiif did not handle correctly return() in conditions [#1590]
+   36- [0..5] -> [0,0,0,0,0] on some architectures
+   37- is_gener_Fp could return wrong results
+   38- Fq_sqrtn(t_INT,..,&zeta) could return a wrong root of 1
+   39- bnfinit: SEGV due to precision issues [#1592]
+   40- zm_zc_mul only worked for square zm matrices
+   41- genus2red(0,27*x^5+97*x^4+118*x^3+60*x^2+13*x+1,3) -> bug msg [#1596]
+   42- [gphelp] oo loop when $COLUMNS too small [#1594]
+   43- genus2red(x,-x^6-3*x^4-10*x^2-1,3) -> impossible inverse [#1597]
+   44- factoru(1) returned a t_MAT instead of the expected "matsmall" [#1598]
+   45- FpM_charpoly wrong in small characteristic [#1602]
+   46- Ser(Mod(0,2)) => incorrect object [#1587]
+   47- Ser(Mod(1,2)*x^2,,4) => incorrect precision [#1587]
+   48- Ser(x,v,prec < 0) => crash [#1587]
+   49- The t_SER Mod(0,2) + O(x^n) was not handled properly [precision and
+       valuation would change unexpectedly] [#1587]
+   50- when compatible = 3; series() used a random precision
+   51- genus2red(0,6*x^6+5*x^4+x^2+1,7) -> impossible inverse [#1597]
+   52- isprime(2030967737887612953751815611955778057721609672149695775998900201419048774375002716065557720510887824952942799737911826638068045234238082640629966597954851668852106621828704531597859470496362810381251800973022824003330423370127762722630493369197869948901862977534730314352222720177713223750671181797)
+       -> SEGV [#1604]
+   53- genus2red(x^3+1,1) -> type error [#1597]
+   54- gphelp did not handle === correctly [#1603]
+XR 55- bnrL1(bnrinit(bnfinit(x^2-168),[6,[1,1]],1)) -> bug in ArtinNumber[#1601]
+   56- FpXY_evaly() wrong when evaluating at 0
+BA 57- [win32] gp could crash at start up [#1607]
+   58- nfisincl(t_POL, t_POL) could lead to wrong negative results
+   59- polresultant(1+x*z^2,1+y*z^4,z) -> GC error [#1614]
+BA 60- ellcard over non-prime fields of large char could return wrong results
+   61- [libpari] FpX_roots could produce GC errors [#1618]
+   62- weber(1+I) was missing its imaginary part
+   63- (1+I)*(1+1/2*I) => wrong result (type errors) [#1619]
+   64- contfracpnqn([a]) => [1,a;0,1] instead of [a,1;1,0]
+   65- primes([2^50, 2^50+200000]) => stack overflow
+   66- issquare((x+1/2)^2,&z); z => 1.0*x+0.5 instead of x+1/2
+   67- possibly wrong result in nfsnf
+   68- possibly missing roots in nfroots (when using Trager)
+   69- quadray(bnf, ideal) did not work
+   70- thue(-14*x^3 + 10*x^2 + 63*x - 5,1) -> "short continued fraction" [#1629]
+   71- thue(29*x^3+130*x^2-35*x-48,1) -> "round error" bug
+   72- T=thueinit(10*x^3+6*x^2-41*x+8,1); thue(T,8) => SEGV [#1630]
+   73- ellrootno(e,p = 2 or 3) when e not minimal at p => random result
+   74- catastrophic cancellation in ellheight (at oo) [#1637]
+   75- bnfnewprec could return a corrupt bnf structure:
+        K=bnfinit(x^3-15667*x^2-88630960*x-1836105977032,1);
+        bnfisprincipal(K,[29,14,15;0,1,0;0,0,1],3) -> oo loop
+   76- agm(1,2+O(5)) -> SEGV [#1645]
+BA 77- [cygwin64] ellap(ellinit([0,0,1,-1,0]),10007) broken
+   78- primes([-5,5]) -> [5] (spurious absolute values)
+   79- matqr([;]) -> crash
+   80- Fp_rem_mBarrett could return a non-normalized result
+       p=436^56-35;Mod(271,p)^((p-1)/2) -> p+1
+   81- plotcopy would corrupt "string" objects (ROt_ST)
+BA 82- [GP] default arguments to GP functions could cause corruption [#1658]
+VBr83- [darwin] remove obsolete linker options that cause crashes [#1623]
+   84- divisors([2,1]) -> SEGV                                    [#1664]
+   85- acos([Pol(1)]) -> GC bug [#1663]
+   86- matsolve(a,b) and a^(-1) gave wrong results [or SEGV] when t_MAT a
+       was not square and a,b "modular" (F2m,Flm,FpM,FqM,F2xqM,FlxqM)
+       same for x^(-1) [#1666]
+   87- primes([1,Pol(2)]) -> SEGV [#1668]
+   88- znlog(0,Mod(1,4),1) -> 0 (instead of [])
+   89- polzagier / sumalt(,1) / sumpos(,1) were slow and used too much memory
+   90- sumpos was wasting time when pre-computing \sum 2^e a(k*2^e) [ only
+       needed for k odd, but was also done for k = 0 mod 4 ] + improve accuracy
+   91- intnum(x=[0,-1/2],[oo,-3/2],1/(sqrt(x)+x^(3/2))) -> junk t_COMPLEX
+       (more generally: one endpoint has an algebraic singularity and the
+       other is +-oo, non-oscillatory
+   92- intnum(x = [-oo,-3/2], [oo,-5/2], f(x)) --> loss of accuracy due to
+       confusion between endpoint behaviours a/b in intnuminit data
+       E.g. f(x)=(x<0,1/(1+(-x)^(3/2)), 1/(1+x^(5/2)));
 
-Done for version 2.7.1 (released 16/05/2014):
-[last column crossreferences current development release 2.8.0]
+  Added
+    1- add optional argument to sumdigits to specify the base
+    2- [libpari] bits_to_int,bits_to_u,binary_zv,binary_2k,binary_2k_zv
+BA  3- [GP] support for variadic GP functions (f(v[..])=expr)
+    4- nfeltval(K, x, pr, &y) now takes an optional 4th argument, containing
+       the part of x coprime to pr.
+BA  5- [libpari] New functions family RgXn: new functions RgXnV_red_shallow,
+       RgXn_powers, RgX_RgXnV_eval, RgX_RgXn_eval, RgXn_reverse, RgXn_inv,
+       RgXn_exp
+BA  6- [libpari] New functions Flv_inv
+BA  7- [libpari] New functions Flx_Flv_eval, Flv_FlvV_polint
+WH  8- [libpari] New low-level functions get_Fl_inv, remll_pre
+BA  9- [libpari] New low-level functions Fl_sqr_pre, Fl_mul_pre, remlll_pre,
+       Fl_powu_pre, Fl_sqrt_pre, divll_pre, random_Fle_pre
+   10- [TeX documentation] new primitive \url (verbatim arg)
+   11- [libpari] New functions Fq_log, gener_Fq_local
+BA 12- GP functions bnrisgalois, bnrgaloismatrix, bnrgaloisapply
+LGr13- GP function polrootsreal
+   14- GP constant "oo" (for +/- infinity)
+   15- [libpari] New functions mkoo, mkmoo, inf_get_sign
+   16- [libpari] New functions ellbasechar, ec_f_evalx, ec_dfdx_evalQ,
+   ec_dfdy_evalQ, ec_2divpol_evalx, ec_half_deriv_2divpol_evalx, ec_h_evalx,
+   ec_dmFdy_evalQ, ec_bmodel
+HIL17- GP functions ellisogeny, ellisogenyapply
+   18- [libpari] New function RgX_coeff
+BA 19- [libpari] New functions Fl_halve, Fp_halve, Flx_halve, Fq_halve
+BA 20- [libpari] New functions vecsmallpermute, vec_append
+   21- GP functions qfsolve, qfparam [ adapted from Denis Simon's qfsolve.gp ]
+   22- [libpari] New function ZM_transmul
+   23- allow elliptic curves over number fields: ellinit([a1,...,a5], nf)
+   24- [libpari] ZX_sturm, ZX_sturmpart, RgX_sturmpart
+   25- [libpari] RgXQV_RgXQ_mul
+   26- thue / thueinit now also support (powers of) imaginary quadratic equations
+BA 27- [libpari] ZpX_ZpXQ_liftroot, ZpX_ZpXQ_liftroot_ea
+   28- [libpari] fuse_Z_factor
+   29- ellformalw, ellformalpoint, ellformaldifferential,
+       ellformallog, ellformalexp, ellnonsingularmultiple, ellpadicheight,
+       ellpadicheightmatrix, ellpadics2, ellpadiclog
+BA 30- [libpari] functions FpX_powu, FpX_digits, FpX_fromdigits,
+                 FpXQX_powu, FpXQX_digits, FpXQX_fromdigits, FqX_powu
+BA 31- GP functions ellpadicfrobenius, hyperellpadicfrobenius, hyperellcharpoly
+   32- [libpari] function RgX_normalize
+BA 33- much faster matfrobenius/minpoly(t_MAT)
+BA 34- prototype codes U and u for ulong
+   35- allow testing for BITS_IN_LONG in gprc
+   36- GP functions msinit, ellpadicL
+BA 37- [mingw] support for the alarm GP function
+BA 38- [libpari] functions Fl_sqrtl, Fl_sqrtl_pre
+   39- [libpari] function ZV_allpnqn
+   40- [libpari] function Qevproj_init, Qevproj_apply, Qevproj_apply_vecei
+   41- [libpari] functions G_ZGC_mul, G_ZG_mul, ZGC_G_mul, ZGC_Z_mul, ZG_G_mul,
+       ZG_Z_mul, ZG_add, ZG_mul, ZG_neg, ZG_normalize, ZG_sub
+   42- [libpari] function kroui
+BA 43- GP function powers and libpari function gpowers
+   44- flag LLL_COMPATIBLE for LLL routines [ use 64-bit compatible accuracies
+       only ]
+BA 45- [libpari] functions FpX_Frobenius, FpX_matFrobenius, Flx_Frobenius,
+       Flx_matFrobenius, ZpX_Frobenius
+   46- [libpari] function ser_isexactzero
+BA 47- [libpari] functions ZV_chinese, Z_ZV_mod, Z_nv_mod, nmV_chinese
+BA 48- GP function fromdigits
+BA 49- [libpari] functions Zp_sqrt, ZpXQ_sqrt
+   50- GP functions mscuspidal, mseisenstein, msnew, mssplit, msqexpansion,
+       mshecke, ellmsinit, msatkinlehner, msstar, mseval, mspathgens, mspathlog,
+       msissymbol
+BA 51- GP declaration localprec()
+HIL52- [libpari] functions Fl_powers_pre, Fl_ellj_pre, Fl_elldisc_pre,
+                           Fl_elltwist
+BA 53- [libpari] functions Fl_powers, Fp_powers, Fl_ellj, Fl_elldisc,
+                           Fl_ellj_to_a4a6, Flxq_ellj_to_a4a6
+BA 54- [libpari] functions FpXQX_div_by_X_x, FqX_div_by_X_x
+HIL55- [libpari] function Flx_oneroot_split, zxX_to_FlxX, RgXY_degreex
+BA 56- [libpari] functions Flv_inv_pre, Flv_inv_inplace, Flv_inv_pre_inplace
+HIL57- GP function ellissupersingular
+HIL58- [libpari] functions Fp_elljissupersingular, FpXQ_elljissupersingular
+BA 59- [libpari] functions umodsu, zx_to_Flx, corediscs
+   60- GP function qfbredsl2
+   61- [libpari] functions ell_is_integral, ellintegralmodel, ellQ_get_CM,
+   ellorder_Q, ellap_CM_fast, point_to_a4a6, point_to_a4a6, Fl_elltrace_CM,
+   Fle_changepoint, Fle_changepointinv, Fle_log
+   62- allow elltors and ellorder for E/K number field
+   63- GP function ellxn, ellisdivisible
+HIL64- [libpari] function family Flj_*
+   65- [libpari] idealprimedec_limit_f, idealprimedec_limit_norm
+   66- [libpari] modpr_get_p, modpr_get_T, modpr_get_pr
+   67- GP function nfsplitting
+HIL68- [libpari] functions Flv_dotproduct_pre, Flx_eval_pre,
+       Flx_eval_powers_pre, FlxY_eval_powers_pre, FlxY_evalx_powers_pre
+HIL69- GP functions polclass, polmodular
+BA 70- ellcard over fields of medium characteristic (SEA, Kedlaya, Satoh)
+   71- GP functions varhigher() / varlower() / variables()
+BA 72- GP function self() (for defining recursive anonymous functions)
+BA 73- GP function fold()
+   74- [libpari] hash_create_ulong, hash_create_str, hash_select,
+       hash_remove_select, hash_keys, hash_values
+   75- allow serlaplace(t_POL)
+   76- GP function ispseudoprimepower
+   77- [libpari] functions FpM_add, Flm_add, FpM_Fp_mul
+   78- [libpari] function nfembed, nfissquarefree
+   79- new binary flag to polcompositum: assume fields are linearly disjoint
+   80- GP function nfcompositum
+AP 81- [GP] central simple algebra package, GP functions
+    aladd              algetaut           alinit             alrandom
+    alalgtobasis       algetb             alinv              alsimpledec
+    albasistoalg       algetcenter        alisassociative    alsplittingmatrix
+    alcenter           algetchar          almul              alsqr
+    alcentralproj      algetdegree        almultable         alsub
+    alcharpoly         algetdim           alneg              alsubalg
+    aldecomposition    algethassef        alnorm             altableinit
+    aldisc             algethassei        alpoleval          altensor
+    aldivl             algetinvord        alpow              altrace
+    aldivr             algetmultable      alprimesubalg      altype
+    algetord           alquotient         algetabsdim        algetsplitting
+    alradical
+   82- [libpari] functions rnf_get_alpha, rnf_get_idealdisc, rnf_get_k
+   83- [libpari] functions ZC_is_ei, RgC_is_ei, ZM_Z_div, ZMV_to_FlmV, checkal
+   84- [libpari] functions cbrtr, cbrtr_abs
+   85- nfinit(rnf) now returns an nf structure associated to rnf.polabs
+   86- idealprimedec now allows an optional 3rd argument, to limit f(P/p)
+   87- [libpari] cb_pari_err_handle callback
+   88- [libpari] function nf_get_ramified_primes
+   89- Configure --with-runtime-perl option
+PB 90- Faster matrix multiplication over finite fields
+   91- allow content(t_VECSMALL)
+   92 [libpari] ZX_div_by_X_1
 
-  Fixed
-    1- make install fails on OS/X: ln -s libpari.dylib libpari.dylib fails [F1]
-    2- Q_pvalrem(t_FRAC) => wrong result                                   [F2]
-    3- [] == 0 but []~ != 0  (now []~ == 0 as well) [#1560]                [F3]
-BA  4- test-kernel did not work when using --mt=pthread                    [F4]
-BA  5- ellheegner was using too much memory in some case                   [F5]
-BA  6- ellap can overflow on 32-bit machine [#1558] (minimal fix)          [F6]
-    7- nfhilbert(K,x,y, P above 2) could give wrong results [#1561]        [F7]
-    8- gcd(1/2, 1+I*1.) -> SEGV [#1563]                                   [F10]
-    9- mathnf(t_VEC) could corrupt input (change sign)                    [F11]
-   10- [libpari] RgM_transmul did not work                                [F12]
-   11- [libpari] Fq_issquare didn't support T=NULL                        [F13]
-   12- [libpari] nfpow_u didn't handle non-integral rational numbers      [F14]
-   13- eint1(0) -> stack overflow [#1568]                                 [F15]
-   14- nfroots(, t_POL with leading coeff -1) could miss solutions        [F19]
-   15- precprime(1) -> invalid t_INT [#1576]                              [F20]
+  Changed
+    1- make log(+/-I) return (+/-)Pi/2*I with gen_0 real part [#1556]
+BA  2- [libpari] rename RgX_mullow -> RgXn_mul, RgX_sqrlow -> RgXn_sqr,
+    RgX_modXn_eval -> RgXn_eval, RgX_modXn_shallow-> RgXn_red_shallow
+    3- change rnfnormgroup to return [;] instead of raising an error whenever
+    it detects a problem (modulus not a multiple of the conductor, non-abelian
+    extension...): this is a BIB with undefined result, but returning a
+    sentinel is more useful *if* we notice it.
+    4- [gp] uniformize errors from the % history operator (SYNTAX->MISC) [#1553]
+    5- t_STR used to compare as larger than any real number via < or >
+       operators. Such a comparison now raises an exception.
+    6- valuation(0,p), nfeltval(nf,0,pr), idealval(nf,0) now all return +oo
+       poldegree(0) now returns -oo
+BA  7- rootpadicfast renamed ZpX_roots
+    8- nfinit: switch from sturm() to ZX_sturm() [Uspensky], and from polroots
+       to polrootsreal (totally real fields). polsturm() now uses Uspensky in
+       most cases.
+    9- polsturm interface change
+         - polsturm(T, a, b) is still supported but deprecated, use
+           polsturm(T, [a,b])
+         - polsturm(T, a, b) used to return the number of roots in ]a,b],
+           we now use the closed interval [a,b]: more intuitive given the new
+           syntax, and compatible with polrootsreal()
+BA 10- [libpari] mkintn: handles arguments as 32bit unsigned int
+   11- nfdisc, nfbasis: no longer support the old (T,flag,fa) arguments.
+       Use the generic [T,listP] syntax (see 2.6.0-C105)
+   12- factorpadic: no longer support the deprecated (no-op) 'flag' argument
+   13- thue() sort solutions lexicographically
+   14- thueinit tnf format: always include a bnf (also when r1=0), to allow
+       checking for norm equation solutions first: e.g. thue(x^4+1,7*10^80)
+       becomes instantaneous instead of overflowing
+BA 15- Flx_pow renamed to Flx_powu
+   16- optional flag to ellheight is gone (useless)
+   17- ellbil(E,P,Q) is now deprecated, use ellheight(E,P,Q)
+   18- [libpari] rename ghell->ellheight, mathell->ellheightmatrix
+BA 19- Rg_to_RgV renamed to Rg_to_RgC, RgX_to_RgV renamed to RgX_to_RgC
+   20- ellL1(e, r): make r optional (default value = 0)
+BA 21- powruvec is replaced by powersr
+   22- [libpari] merge_factor no longer keeps entries with exponent 0
+Pmo23- More robust and much faster ellL1 and ellanalyticrank. The condition
+       ord(L_E,s=1) <= r in ellL1(E,r) is no longer necessary.
+   24- renamed ZV_gcdext -> ZV_extgcd for consistency with other gcdext methods
+BA 25- setrand now return a (huge) integer instead of a vecsmall
+   26- unify 32/64 bit random generators. Probabilistic algorithm should now
+       behave identically on all architecture, provided they do not involve
+       the floating point kernel
+   28- unify 32/64 bit tests
+   29- move extern(), externstr(), readstr() and system() to the generic
+       part of GP language (was gp-specific). This allows to use them
+       in parallel mode and under gp2c [#1593]
+   30- made cmprr, cmpri, equalrr consistent with == semantic. We now have,
+       e.g., 0e1==1.0 and (0e1 < 1) = 0 (since 1-0e1 evaluates to 0e1)
+   31- [libpari] comment out function names obsoleted during the 2.3.* cycle
+       (2007). See PARI_OLD_NAMES.
+   32- default 'strictmatch' has been obsoleted. It is now a no-op.
+   33- default 'compatible' has been obsoleted. It is now a no-op.
+   34- zeta(odd integer): use Borwein's "sumalt" algorithm (10 times faster
+       than previous at \p1000)
+   35- elltors flags are now deprecated (and ignored, removed corresponding
+       code)
+   36- add optional flag to nfhnf / nfsnf: return transformation matrices
+   37- nfroots/nffactor: factor polynomials in Q[X] over Q first
+BA 38- much faster polresultant over Z
+   39- GP and libpari polynomial variables of arbitrary priority can now be
+       created: 'x' is no longer guaranteed to have maximal priority,
+       nor MAXVARN to have minimal priority.
+   40- GP: polynomial variable 'y' is now always defined on startup,
+       with priority lower than 'x'
+   41- Allow ffgen([p,f]) in addition to ffgen(p^f) and ffgen(T*Mod(1,p))
+   42- thue() needed to compute to huge accuracies when regulator was large
+       E.g. t=thueinit(15*x^3+8*x^2-95*x+24,1); thue(t,8)
+   43- rnf structures may now contain a full absolute nf struct ('nfabs')
+   44- matkerint: replace underlying LLL algorithm by mathnf
+       Simple bench: M=matrix(50,55,i,j,random(10^5)); \\ 200 times faster
+   45- allow t_VECSMALL vector exponents in gen_factorback
+   47- [libpari] rename 'define' PI -> M_PI and use proper constant
+   48- no longer print 0 t_POLMOD as "0", bug e.g. Mod(0,x). Uniformize code
+       and behaviour with t_INTMOD.
+   49- warn when coercing quotient rings when 'debug' non-zero
+      ? \g1
+      ? Mod(1,2)+Mod(1,3)
+        *** _+_: Warning: coercing quotient rings; moduli 2 and 3 -> 1.
+   50- content([]) -> 0 [ was 1 ]
+   51- [] / 0 => div. by 0. Now returns [] (as [] \ 0 already did)
+LGr52- use GRH-guaranteed bounds in bnfinit for residue estimate
+   53- Configure: avoid inserting unnecessary -L arguments in link line
+   54- genus2red: change syntax. Allow either genus2red(P) or genus2red([P,Q])
+       instead of mandatory Q (was: genus2red(Q,P) with Q almost always 0).
+       Allow uniformization with hyperellcharpoly
+   55- old functions from gp-1.39.15 no longer loaded into an "entree" table,
+       no longer complete specially "whatnow" arguments; remove compat.c and
+       most of gp_init.c
+
+Removed
+   1- deprecated functions nfbasis0, nfdisc0, factorpadic0
+   2- deprecated function manage_var
diff --git a/CHANGES-2.6 b/CHANGES-2.6
index c277219..9f1e69f 100644
--- a/CHANGES-2.6
+++ b/CHANGES-2.6
@@ -208,7 +208,7 @@ JD 14- polcyclo(n, x) now works for all roots of 1
    33- rnf.pol (absolute defining polynomial / Q) is now called rnf.polabs,
        rnf.pol is now the relative polynomial, defining the relative extension
        over the base.
-BA 34- FpXYQQ_pow: change order of moduli to be consstent with FpXQXQ_pow.
+BA 34- FpXYQQ_pow: change order of moduli to be consistent with FpXQXQ_pow.
 BA 35- FlxYqQ_pow: renamed to FlxYqq_pow, and moduli order changed.
    36- idealstar(K,id), allow to input 'id' as a factorization into prime
        ideals, as produced by idealfactor
diff --git a/COMPAT b/COMPAT
index a32a8f0..30ee16b 100644
--- a/COMPAT
+++ b/COMPAT
@@ -1,4 +1,56 @@
 This file lists the incompatible changes between Version 2.x and older versions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.8 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+  - t_STR used to compare as larger than any real number via < or >
+    operators. Such a comparison now raises an exception.
+  - valuation(0,p), nfeltval(nf,0,pr), idealval(nf,0) now all return +oo
+    under GP [ used to return LONG_MAX ]
+  - poldegree(0) now returns -oo [ used to return -LONG_MAX ]
+  - polsturm interface change
+     * polsturm(T, a, b) is still supported but deprecated, use
+       polsturm(T, [a,b])
+
+     * polsturm(T, a, b) used to return the number of roots in ]a,b],
+       we now use the closed interval [a,b]: more intuitive given the new
+       syntax, and compatible with polrootsreal()
+  - nfdisc, nfbasis: no longer support the old (T,flag,fa) arguments.
+    Use the generic [T,listP] syntax (see 2.6.0-C105)
+  - factorpadic: no longer support the deprecated (no-op) 'flag' argument
+  - optional flag to ellheight is gone (useless)
+  - ellbil(E,P,Q) is now deprecated, use ellheight(E,P,Q)
+  - default 'strictmatch' has been obsoleted. It is now a no-op.
+  - default 'compatible' has been obsoleted. It is now a no-op.
+  - GP and libpari polynomial variables of arbitrary priority can now be
+    created: 'x' is no longer guaranteed to have maximal priority,
+    nor MAXVARN to have minimal priority.
+  - GP: polynomial variables no longer spring into existence unless a true
+    t_POL/t_SER in the variable is needed. E.g. y = 0 does not create the
+    "variable" y, thereby messing up variable ordering.
+  - genus2red: change syntax. Allow either genus2red(P) or genus2red([P,Q])
+    instead of mandatory Q (was: genus2red(Q,P) with Q almost always 0).
+    Allow uniformization with hyperellcharpoly
+
+* Specific to the PARI library:
+===============================
+  - renamed RgX_mullow -> RgXn_mul, RgX_sqrlow -> RgXn_sqr,
+    RgX_modXn_eval -> RgXn_eval, RgX_modXn_shallow -> RgXn_shallow
+  - top and bot are replaced by pari_mainstack->top and pari_mainstack->bot.
+  - allocatemem() is replaced by paristack_resize.
+  - rootpadicfast was renamed to ZpX_roots
+  - mkintn() now handles arguments as 32bit unsigned int on both 64/32 bits.
+  - sturmpart(x, a, b) is deprecated, use RgX_sturmpart(x, ab) or (better)
+    ZX_sturmpart(x, ab)
+  - removed deprecated functions nfbasis0, nfdisc0, factorpadic0
+  - Flx_pow renamed to Flx_powu
+  - [libpari] rename ghell->ellheight, mathell->ellheightmatrix
+  - Rg_to_RgV renamed to Rg_to_RgC, RgX_to_RgV renamed to RgX_to_RgC
+  - powruvec was replaced by powersr
+  - renamed ZV_gcdext -> ZV_extgcd for consistency with other 'gcdext' methods
+  - comment out libpari function names obsoleted during the 2.3.* cycle
+    See PARI_OLD_NAMES.
+  - ellsea is replaced by Fp_ellcard_SEA
+  - rename PI -> M_PI
+
 %%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.6 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   - eval() no longer evaluates its arguments in "permissive" mode: eval("1a")
     now produces a syntax error.
diff --git a/Configure b/Configure
index ecedc55..7a66846 100755
--- a/Configure
+++ b/Configure
@@ -159,6 +159,7 @@ for variable in\
   ln_s make_sh\
   sizeof_long doubleformat\
   thread_engine enable_tls\
+  runtime_perl\
   $_tools_list\
   $_test_list\
   $_install_list\
@@ -186,8 +187,8 @@ if test -n "$tune"; then
   echo "Building and tuning PARI (this may take a while)"
   echo
   (cd $objdir; rm -f parilvl1.h pariinl.h;\
-  $MAKE tune; tune -t > tune.h.new && mv tune.h.new tune.h && cat tune.h;\
-  rm -f parilvl1.h pariinl.h; $MAKE gp)
+  $MAKE tune && tune -t > tune.h.new && mv tune.h.new tune.h && cat tune.h\
+    && rm -f parilvl1.h pariinl.h && $MAKE gp)
 else
   echo $n "Shall we try to build pari $version.$patch ($status) now (y/n)? $c"
   dflt=n; rep='y n'; . $config_dir/myread
diff --git a/README b/README
index 886427e..df76438 100644
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
-This is PARI/GP, version 2.7.x (*).
+This is PARI/GP, version 2.8.x (*).
 
 PARI/GP Number Theory-oriented Computer Algebra System
-        Copyright (C) 2000-2014 The PARI Group, Bordeaux.
+        Copyright (C) 2000-2015 The PARI Group, Bordeaux.
 
 ==========================================================================
 
diff --git a/config/Makefile.SH b/config/Makefile.SH
index d2193d0..237d62b 100644
--- a/config/Makefile.SH
+++ b/config/Makefile.SH
@@ -319,20 +319,20 @@ mpinl\$(_O): .headers parilvl0.h parilvl1.h $knone/mpinl.c
 
 test-kernel:: kerntest
 	@./kerntest > gp.out;\
-	diff -c gp.out $src/test/$numbits/kernel > kern.dif;\
+	diff -c gp.out $src/test/32/kernel > kern.dif;\
 	if test -s kern.dif; then echo "KERNEL BUG"; else echo OK; fi
 
-tune.o: $src/test/tune.c
-	\$(CC) \$(GMPFLAGS) \$(CPPFLAGS) \$(CFLAGS) -o \$@ \$< -c
+tune\$(_O): .headers $src/test/tune.c
+	\$(CC) \$(GMPFLAGS) \$(CPPFLAGS) \$(CFLAGS) -o \$@ $src/test/tune.c -c
 
 tune: mpinl.h tune-sta
 	-\$(RM) tune ../tune
 	-\$(LN) tune-sta tune
 	-\$(LN) $ln_objdir/tune ../tune
 
-tune-dyn: tune.o \$(LIBPARI_DYN)
+tune-dyn: tune\$(_O) \$(LIBPARI_DYN)
 	\$(LD) -L. \$(LDFLAGS) \$(RUNPTH) -o \$@ \$< \$(GMPOBJS) \$(LDDYN) \$(STA_LIBS)
-tune-sta: tune.o \$(LIBPARI_STA)
+tune-sta: tune\$(_O) \$(LIBPARI_STA)
 	\$(LD) \$(LDFLAGS) \$(RUNPTH) -o \$@ \$< \$(GMPOBJS) ./\$(LIBPARI_STA) \$(STA_LIBS)
 
 gp-sta: $add_funclist \$(OBJS) \$(OBJSGP)
@@ -349,7 +349,7 @@ cleanobj:
 cleandesc:
 	-\$(RM) $desc/\$(DESC) *\$(TMPSUF)
 cleantune:
-	-\$(RM) tune tune-sta tune.o
+	-\$(RM) tune tune-sta tune\$(_O)
 
 cleanall: cleanobj cleantune cleantest cleandesc
 
@@ -625,7 +625,7 @@ HUGELINE="
 $src/funclist::
 	@-$cfg/genfunclist $desc"
 suffix='$$$$-$(TMPSUF)'
-list="funclist whatnow init default gp_default gp_init highlvl"
+list="funclist init default gp_init highlvl"
 for name in $list; do
   case $name in
   funclist)
@@ -633,11 +633,6 @@ for name in $list; do
     depend="$src/funclist $desc/merge_822 $desc/PARI/822.pm"
     script="merge_822 ../funclist"
   ;;
-  whatnow)
-    target=$src/gp/whatnow.h
-    depend="$desc/whatnow $src/whatnow"
-    script=whatnow
-  ;;
   init)
     target=$src/language/init.h
     depend="$desc/\$(DESC) \$(DESC_HELP_GEN)"
@@ -648,11 +643,6 @@ for name in $list; do
     depend="$desc/\$(DESC) \$(DESC_HELP_GEN)"
     script="gen_proto default \$(DESC)"
   ;;
-  gp_default)
-    target=$src/gp/gp_default.h
-    depend="$desc/\$(DESC) \$(DESC_HELP_GEN)"
-    script="gen_proto gp_default \$(DESC)"
-  ;;
   gp_init)
     target=$src/gp/gp_init.h
     depend="$desc/\$(DESC) \$(DESC_HELP_GEN)"
@@ -715,16 +705,12 @@ for dir in basemath modules language gp graph systems mt; do
   case "$f" in
   gp)
     cflags="$cflags -I$src/language -DDL_DFLT_NAME=\$(DL_DFLT_NAME)"
-    depend="$src/gp/gp.h"
+    depend="$src/gp/gp.h $src/gp/highlvl.h $src/gp/gp_init.h"
     ;;
-  gp_rl)
+  gp_rl|texmacs)
     cflags="$cflags -I$src/language \$(RLINCLUDE)"
     depend="$src/gp/gp.h"
     ;;
-  gp_init)
-    cflags="$cflags -I$src/graph"
-    depend="$RECT_H $src/gp/gp_init.h $src/gp/gp_default.h"
-    ;;
   default)
     cflags="$cflags \$(DLCFLAGS)"
     ;;
@@ -736,9 +722,6 @@ for dir in basemath modules language gp graph systems mt; do
     cflags="$cflags -I$src/graph"
     depend="$RECT_H"
     ;;
-  highlvl)
-    depend="$RECT_H $src/gp/highlvl.h"
-    ;;
   plotQt)
     cflags="$cflags \$(PLOTCFLAGS)"
     depend="$RECT_H"
diff --git a/config/extract_files b/config/extract_files
index e8eae1a..894c9be 100755
--- a/config/extract_files
+++ b/config/extract_files
@@ -9,7 +9,7 @@ for dir in "$doc_dir" "$misc_dir"; do
     echo "...in $dir"
     flist=`ls $dir/*.in`
     for file in $flist; do
-      sed -e "s%@perl@%$perl%g"\
+      sed -e "s%@runtime_perl@%$runtime_perl%g"\
           -e "s%@datadir@%$datadir%g"\
           -e "s%@bindir@%$bindir%g"\
           -e "s%@includedir@%$includedir%g"\
diff --git a/config/genkernel b/config/genkernel
index 2a924b8..1472435 100755
--- a/config/genkernel
+++ b/config/genkernel
@@ -1,6 +1,7 @@
 #! /bin/sh
 K=../src/kernel
 knone=$K/none
+EXTRA="divll_pre"
 for file in "$@"; do
   echo "#ifndef ASMINLINE"
   for i in `grep '^ASM' $file`; do
@@ -11,7 +12,7 @@ for file in "$@"; do
   done
   echo "#endif"
   cat $file
-  for i in `grep '^NOASM' $file`; do
+  for i in `grep '^NOASM' $file` $EXTRA; do
     case $i in
       NOASM);;
       *) cat $knone/$i.h;;
diff --git a/config/get_MANIFEST b/config/get_MANIFEST
index 68774c6..b378e76 100755
--- a/config/get_MANIFEST
+++ b/config/get_MANIFEST
@@ -5,7 +5,6 @@ echo src/language/default.h
 echo src/language/init.h
 echo src/language/parse.c
 echo src/language/parse.h
-echo src/gp/gp_default.h
 echo src/gp/gp_init.h
 echo src/gp/highlvl.h
 echo src/gp/whatnow.h
diff --git a/config/get_X11 b/config/get_X11
index 6f5a174..90b386c 100644
--- a/config/get_X11
+++ b/config/get_X11
@@ -38,21 +38,24 @@ if test -f $Xincroot/X11/Xos.h; then
   X11_INC="-I$Xincroot"
 fi
 # X11 -- Lib
-pth=$x11pth
-lib=X11; . ./locatelib
-if test -n "$X11"; then
-  X11_LIBS="-L$X11 -lX11 $extralib"
-else
-  exe=$osname-$arch-X11$$
-  cmd="$CC $CFLAGS $extraflag $X11_INC -o $exe has_X11.c -lX11 $extralib"
-  . log_cmd
-  if test -r $exe; then
-    X11_LIBS="-lX11 $extralib"
-  else
-    echo "### X11 not found"
-    X11_LIBS=
-    X11_INC=
+
+exe=$osname-$arch-X11$$
+cmd0="$CC $CFLAGS $extraflag $X11_INC -o $exe has_X11.c"
+try() { X11_LIBS=$1; cmd="$cmd0 $1"; . log_cmd; }
+
+try "-lX11 $extralib"
+if test ! -r $exe; then
+  pth=$x11pth
+  lib=X11; . ./locatelib
+  if test -n "$X11"; then
+    try "-L$X11 -lX11 $extralib"
   fi
 fi
+
+if test ! -r $exe; then
+  echo "### X11 not found"
+  X11_LIBS=
+  X11_INC=
+fi
 rm -f $exe $exe$exe_suff;
 echo ..."X11 libraries: $X11_LIBS"
diff --git a/config/get_config_options b/config/get_config_options
index 82b39dd..4b52b43 100644
--- a/config/get_config_options
+++ b/config/get_config_options
@@ -63,7 +63,8 @@ while test $# -gt 0; do
   -graphic|--graphic) shift; which_graphic_lib=$1;;
   --graphic=*|--graphi=*|--graph=*|--grap=*|--gra=*|--gr=*|--g=*)
 	       which_graphic_lib=`echo "$1" | sed -e 's/[-a-z]*=//'`;;
-
+  --with-runtime-perl=*)
+      runtime_perl=`echo "$1" | sed -e 's/[-a-z]*=//'` ;;
   --without-readline|--with-readline=no) without_readline=yes ;;
   --with-readline) with_readline=yes ;;
   --with-readline=*)
@@ -166,6 +167,9 @@ Optional libraries:
   --with-qt[=DIR]        use the Qt graphical library [prefix for Qt dir.]
   --with-fltk[=DIR]      use the FLTK graphical library [prefix for FLTK dir.]
 
+Miscellaneous
+  --with-runtime-perl[=path-to-perl-binary] for gphelp / tex2mail
+
 Environment variables affecting the build:
   CC                     C compiler
   CFLAGS                 additional flags to the C compiler
diff --git a/config/get_dlld b/config/get_dlld
index 2272aac..4b41be0 100644
--- a/config/get_dlld
+++ b/config/get_dlld
@@ -74,7 +74,7 @@ if test -n "$DLLD"; then
   else # DLLD != GNU ld
     case "$osname" in
       aix)     DLLDFLAGS='-r' ;;
-      darwin)  DLLDFLAGS="-flat_namespace -undefined suppress -compatibility_version $compat_ver -current_version $num_ver" ;;
+      darwin)  DLLDFLAGS="-compatibility_version $compat_ver -current_version $num_ver" ;;
       freebsd) DLLDFLAGS='-Bshareable -x' ;;
       hpux)    DLLDFLAGS='-b' ;;
       irix)    DLLDFLAGS='-shared -elf -no_unresolved -all' ;;
diff --git a/config/get_gmp b/config/get_gmp
index f2a11c0..41ebb38 100644
--- a/config/get_gmp
+++ b/config/get_gmp
@@ -4,8 +4,6 @@ if test -n "$with_gmp"; then
   with_gmp_lib="$with_gmp_lib $with_gmp/lib"
   with_gmp_include="$with_gmp_include $with_gmp/include"
 fi
-pth="$with_gmp_lib $libpth"
-lib=gmp; . ./locatelib
 
 pth="$with_gmp_include $basic_include_path"
 x=`./locate 'gmp.h' '' $pth`
@@ -18,15 +16,24 @@ case $x in
      gmp=;;
 esac
 
+try() { GMPLIBS=$1; cmd="$cmd0 $1"; . log_cmd; }
+
 exe=$osname-$arch-gmpv$$
-if test -n "$gmp"; then
-  GMPLIBS="-L$gmp -lgmp"
-else
-  GMPLIBS="-lgmp"
+cmd0="$CC $CFLAGS $extraflag $GMPINCLUDE -o $exe gmp_version.c"
+
+if test -n "$with_gmp_lib"; then
+  try "-L$with_gmp_lib -lgmp"
+fi
+if test ! -r $exe; then
+  try "-lgmp"
+fi
+if test ! -r $exe; then
+  lib=gmp; . ./locatelib
+  if test -n "$gmp"; then
+    try "-L$gmp -lgmp"
+  fi
 fi
 
-cmd="$CC $CFLAGS $extraflag $GMPINCLUDE -o $exe gmp_version.c $GMPLIBS"
-. log_cmd
 if test -r $exe; then
   gmp_version=`env LD_LIBRARY_PATH="$LD_LIBRARY_PATH$dir_sep$gmp" $RUNTEST $exe`;
 fi
diff --git a/config/get_kernel b/config/get_kernel
index 7717f35..b2ef34f 100644
--- a/config/get_kernel
+++ b/config/get_kernel
@@ -29,7 +29,7 @@ case "$arch" in
            8) asmarch=mips64;           prettya='MIPS64';;
            esac;;
   alpha)         asmarch=$arch;         prettya=Alpha ;;
-  ppc|ppc64)  case "$sizeof_long" in
+  ppc|ppc64|ppc64le)  case "$sizeof_long" in
         4) asmarch=ppc;;
         8) asmarch=ppc64;;
         esac;                           prettya='PowerPC' ;;
diff --git a/config/get_libc b/config/get_libc
index 513a983..4b09e3e 100644
--- a/config/get_libc
+++ b/config/get_libc
@@ -8,11 +8,15 @@ list=log2; . ./look
 extra_flags=
 list=strftime; . ./look
 if test "$timing_fun" = "clock_gettime"; then
-  extra_flags=-lrt
   list=clock_gettime; . ./look
-  extra_flags=
-  if test "$has_clock_gettime" = yes; then
-    RT_LIBS=-lrt
+  if test "$has_clock_gettime" = no; then
+    echo "Try again, with -lrt this time..."
+    extra_flags=-lrt
+    list=clock_gettime; . ./look
+    extra_flags=
+    if test "$has_clock_gettime" = yes; then
+      RT_LIBS=-lrt
+    fi
   fi
 else
   if test -n "$timing_fun"; then
@@ -24,16 +28,27 @@ else
     esac;
   fi; . ./look
 fi
+if test "$has_clock_gettime" = yes -o "$has_ftime" = yes; then
+  :
+else
+  list='gettimeofday ftime'; . ./look
+  if test "$has_ftime" = yes; then
+    has_ftimeforwalltime=yes
+    unset has_ftime
+  fi
+fi
 list=sigaction; . ./look
 list=TIOCGWINSZ; . ./look
 list=getrlimit; . ./look
 list='stat opendir'; . ./look
 list=vsnprintf; . ./look
+list=mmap; . ./look
 list=waitpid; . ./look
 list=setsid; . ./look
 list=getenv; . ./look
 list=isatty; . ./look
 list=alarm; . ./look
+list=system; . ./look
 
 # For install(). Do we need libdl.so?
 # on irix and osf1 -ldl not needed
diff --git a/config/get_modld b/config/get_modld
index 3a77363..26173aa 100644
--- a/config/get_modld
+++ b/config/get_modld
@@ -12,7 +12,7 @@ LIBS=$__LIBS
 
 case $osname in
 darwin) MODLD=$CC;
-        MODLDFLAGS="-bundle -flat_namespace -undefined suppress \
+        MODLDFLAGS="-bundle -undefined dynamic_lookup \
 \$(CFLAGS) \$(DLCFLAGS)";;
 *)      MODLD="$DLLD";
         MODLDFLAGS=`echo "$DLLDFLAGS" | \
diff --git a/config/get_perl b/config/get_perl
index 99613f9..7025ae8 100644
--- a/config/get_perl
+++ b/config/get_perl
@@ -12,4 +12,6 @@ if test -n "$perl"; then
   fi
   if test "$res" = OK; then add_funclist=../src/funclist; fi
 fi
-
+if test -z "$runtime_perl"; then
+  runtime_perl=$perl
+fi
diff --git a/config/get_readline b/config/get_readline
index a7ba691..47217d7 100644
--- a/config/get_readline
+++ b/config/get_readline
@@ -6,8 +6,6 @@ if test -n "$with_readline"; then
   with_readline_lib="$with_readline_lib $with_readline/lib"
   with_readline_include="$with_readline_include $with_readline/include"
 fi
-pth="$with_readline_lib $libpth"
-lib=readline; . ./locatelib
 
 # Readline -- Headers
 pth="$with_readline_include $basic_include_path"
@@ -25,37 +23,54 @@ case $x in
 esac
 
 exe=$osname-$arch-rlv$$
-if test -n "$readline"; then
-  RLLIBS="-L$readline -lreadline"
+cmd0="$CC $CFLAGS $extraflag $RLINCLUDE -o $exe rl_version.c"
+try() { RLLIBS=$1; cmd="$cmd0 $1"; . log_cmd; }
+
+if test -n "$with_readline_lib"; then
+  rl="-L$with_readline_lib -lreadline"
 else
-  RLLIBS="-lreadline"
+  rl="-lreadline"
 fi
-rllibs="$RLLIBS";
-cmd="$CC $CFLAGS $extraflag $RLINCLUDE -o $exe rl_version.c $RLLIBS"
-. log_cmd
-if test ! -r $exe; then # need ncurses ?
-  echo ..."Linking failed. Trying with libncurses"
-  pth="$with_ncurses_lib $libpth"
-  lib=ncurses; . ./locatelib
-  if test -n "$ncurses"; then
-    RLLIBS="$rllibs -L$ncurses -lncurses"
-  else
-    RLLIBS="$rllibs -lncurses"
+
+# try linking without locatelib (without -L except --with-xxx-lib)
+for tlib in "" tinfo ncurses termcap; do
+  t=$rl
+  if test -n "$tlib"; then # need a termcap compatible library?
+    eval with="\$with_${tlib}_lib"
+    if test -n "$with"; then
+      t="$t -L$with -l$tlib"
+    else
+      t="$t -l$tlib"
+    fi
   fi
-  cmd="$CC $CFLAGS $extraflag $RLINCLUDE -o $exe rl_version.c $RLLIBS"
-  . log_cmd
-fi
-if test ! -r $exe; then # need termcap ?
-  echo ..."Linking failed. Trying with libtermcap"
-  pth="$with_ncurses_lib $libpth"
-  lib=termcap; . ./locatelib
-  if test -n "$termcap"; then
-    RLLIBS="$rllibs -L$termcap -ltermcap"
+  try "$t"
+  if test -r $exe; then break; fi
+done
+
+# failed; retry with -Lxxx using locatelib
+if test ! -r $exe; then
+  pth="$with_readline_lib $libpth"
+  lib=readline; . ./locatelib
+  if test -n "$readline"; then
+    rl="-L$readline -lreadline"
   else
-    RLLIBS="$rllibs -ltermcap"
+    rl="-lreadline" # not found, sequel will almost certainly fail
   fi
-  cmd="$CC $CFLAGS $extraflag $RLINCLUDE -o $exe rl_version.c $RLLIBS"
-  . log_cmd
+  for tlib in "" tinfo ncurses termcap; do
+    t=$rl
+    if test -n "$tlib"; then # termcap compatible library, using locatelib
+      eval pth="\$with_${tlib}_lib $libpth"
+      lib=$tlib; . ./locatelib
+      eval p="\$$tlib"
+      if test -n "$p"; then
+        t="$t -L$p -l$tlib"
+      else
+        t="$t -l$p"
+      fi
+    fi
+    try "$t"
+    if test -r $exe; then break; fi
+  done
 fi
 
 readline_version=
diff --git a/config/has_TIOCGWINSZ.c b/config/has_TIOCGWINSZ.c
index afa3e10..799ade2 100644
--- a/config/has_TIOCGWINSZ.c
+++ b/config/has_TIOCGWINSZ.c
@@ -8,5 +8,5 @@ int main()
 {
   struct winsize s;
   int status = ioctl(0, TIOCGWINSZ, &s);
-  return s.ws_col;
+  (void)status; return s.ws_col;
 }
diff --git a/config/has_gettimeofday.c b/config/has_gettimeofday.c
new file mode 100644
index 0000000..5e8fa5e
--- /dev/null
+++ b/config/has_gettimeofday.c
@@ -0,0 +1,8 @@
+#include <stddef.h>
+#include <sys/time.h>
+int main(void)
+{
+  static struct timeval tv0;
+  if(!gettimeofday(&tv0, NULL)) return 1;
+  return 0;
+}
diff --git a/config/has_mmap.c b/config/has_mmap.c
new file mode 100644
index 0000000..87d93cf
--- /dev/null
+++ b/config/has_mmap.c
@@ -0,0 +1,17 @@
+#include <unistd.h>
+#include <sys/mman.h>
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+#ifndef MAP_NORESERVE
+#define MAP_NORESERVE 0
+#endif
+int main(void)
+{
+  size_t size = sysconf(_SC_PAGE_SIZE)*1000;
+  void *b = mmap(NULL, size, PROT_READ|PROT_WRITE,
+                             MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE,-1,0);
+  madvise(b, size, MADV_DONTNEED);
+  munmap(b, size);
+  return 0;
+}
diff --git a/config/has_system.c b/config/has_system.c
new file mode 100644
index 0000000..35bf5fa
--- /dev/null
+++ b/config/has_system.c
@@ -0,0 +1,3 @@
+#include <stdlib.h>
+int (*f)(const char*) = system;
+int main(){ return f != system; }
diff --git a/config/paricfg.h.SH b/config/paricfg.h.SH
index 9389814..8344771 100644
--- a/config/paricfg.h.SH
+++ b/config/paricfg.h.SH
@@ -108,6 +108,9 @@ esac
 case "$has_alarm" in
 yes) echo '#define HAS_ALARM' >> $file;;
 esac
+case "$has_system" in
+yes) echo '#define HAS_SYSTEM' >> $file;;
+esac
 
 
 case "$has_clock_gettime" in
@@ -123,6 +126,13 @@ yes) echo '#define USE_CLOCK_GETTIME 1' >> $file;;
      esac;;
 esac
 
+case "$has_gettimeofday" in
+yes) echo '#define USE_GETTIMEOFDAY 1' >> $file;;
+  *) case "$has_ftimeforwalltime" in
+     yes) echo '#define USE_FTIMEFORWALLTIME 1' >> $file;;
+     esac;;
+esac
+
 case $has_sigaction in
 yes) echo '#define HAS_SIGACTION' >> $file;;
 esac
@@ -170,6 +180,10 @@ case $has_stat in
 yes) echo '#define HAS_STAT' >> $file;;
 esac
 
+case $has_mmap in
+yes) echo '#define HAS_MMAP' >> $file;;
+esac
+
 case $enable_tls in
 yes) echo '#define ENABLE_TLS' >> $file;;
 esac
diff --git a/config/settar b/config/settar
index f0724e1..07342fa 100755
--- a/config/settar
+++ b/config/settar
@@ -6,7 +6,12 @@ STATUS=$3; # status we're being coerced into
 case "$STATUS" in
   alpha|beta) dir="$dir.$STATUS";;
   snapshot) STATUS="development git-"`git log -1 --pretty=format:%h`;
-            dir=`git describe`;;
+            dir=`git describe`
+            case $dir in
+            pari-*);;
+            *) dir=pari-$dir;;
+            esac
+            ;;
 esac
 if test -d $dir; then
   echo "Remove $dir before building a new release"; exit 1
diff --git a/config/version b/config/version
index fba211d..e6a148a 100644
--- a/config/version
+++ b/config/version
@@ -2,16 +2,16 @@
 VersionMajor='2'
 
 # minor version number
-VersionMinor='7'
+VersionMinor='8'
 
 # Patch level
-patch='2'
+patch='0'
 
 # Version code
 version_code=`expr $VersionMajor \\* 65536 + $VersionMinor \\* 256 + $patch`
 
 # Status: alpha, beta, released, development. Rewritten by config/settar !
-stat='released'
+stat='development git-0e48e9b'
 
 # soname of stable libpari.so is libpari.so.$soname_num
 status="$stat"
diff --git a/doc/appa.tex b/doc/appa.tex
index 59a69c0..2eca0fe 100644
--- a/doc/appa.tex
+++ b/doc/appa.tex
@@ -13,10 +13,9 @@ Compiling PARI requires an \kbd{ANSI C} or a \kbd{C++} compiler. If you do
 not have one, we suggest that you obtain the \kbd{gcc/g++} compiler. As for
 all GNU software mentioned afterwards, you can find the most convenient site
 to fetch \kbd{gcc} at the address
-
-\kbd{http://www.gnu.org/order/ftp.html}
-
-\noindent (On Mac OS X, this is also provided in the \kbd{Xcode} tool
+$$\url{http://www.gnu.org/order/ftp.html}$$
+%
+(On Mac OS X, this is also provided in the \kbd{Xcode} tool
 suite; or the lightweight ``Command-line tools for \kbd{Xcode}''.) You can
 certainly compile PARI with a different compiler, but the PARI kernel takes
 advantage of optimizations provided by \kbd{gcc}. This results in at least
@@ -26,8 +25,10 @@ advantage of optimizations provided by \kbd{gcc}. This results in at least
 in conjunction with \kbd{gp}, but not mandatory. In any case, get them before
 proceeding if you want the functionalities they provide. All of them are free.
 The download page on our website
-\kbd{http://pari.math.u-bordeaux.fr/download.html} contains pointers on how
-to get these.
+$$
+\url{http://pari.math.u-bordeaux.fr/download.html}
+$$
+contains pointers on how to get these.
 
   \item GNU \kbd{MP} library. This provides an alternative multiprecision
 kernel, which is faster than PARI's native one, but unfortunately binary
@@ -128,6 +129,16 @@ one, \kbd{ftime}, gives timings in terms of absolute (wall-clock) time.
 Moreover, the \kbd{clock\_gettime} function is more precise, but much slower
 (at the time of this writing), than \kbd{getrusage} or \kbd{times}.
 
+\kbd{--with-runtime-perl=}\var{perl}: absolute path to the runtime \kbd{perl}
+binary to be used by the \kbd{gphelp} and \kbd{tex2mail} scripts. Defaults
+to the path found by \kbd{Configure} on the build host (usually
+\kbd{/usr/bin/perl}). For cross-compiling builds, when the target and build
+hosts have mismatched configurations; suggested values are
+
+\kbd{/usr/bin/env perl}: the first \kbd{perl} executable found in user's
+\kbd{PATH},
+
+\kbd{/usr/bin/perl}: \kbd{perl}'s standard location.
 
 The remaining options are specific to parallel programming. We provide an
 \emph{Introduction to parallel GP programming} in the file
@@ -344,9 +355,9 @@ their package dependency handling).
 built without readline support. Since \kbd{readline} is not trivial to
 install in this environment, a step by step solution can be found in the PARI
 FAQ, see
-\bprog
-  http://pari.math.u-bordeaux.fr/
- at eprog
+$$
+\url{http://pari.math.u-bordeaux.fr/}.
+$$
 
 \subsec{Testing}
 
@@ -550,16 +561,14 @@ Mersenne numbers and a simple general class group and fundamental unit
 algorithm. See the file \kbd{examples/EXPLAIN} for some explanations.
 
 \subsec{The PARI Community} PARI's home page at the address
-\bprog
-  http://pari.math.u-bordeaux.fr/
- at eprog\noindent
+$$\url{http://pari.math.u-bordeaux.fr/}$$
+%
 maintains an archive of mailing lists dedicated to PARI, documentation
 (including Frequently Asked Questions), a download area and our Bug Tracking
 System (BTS). Bug reports should be submitted online to the BTS, which may be
 accessed from the navigation bar on the home page or directly at
-\bprog
-  http://pari.math.u-bordeaux.fr/Bugs/
- at eprog\noindent
+$$\url{http://pari.math.u-bordeaux.fr/Bugs/}$$
+%
 Further information can be found at that address but, to report a
 configuration problem, make sure to include the relevant \kbd{*.dif} files in
 the \kbd{O$xxx$} directory and the file \kbd{pari.cfg}.
@@ -567,9 +576,9 @@ the \kbd{O$xxx$} directory and the file \kbd{pari.cfg}.
 
 There are a number of mailing lists devoted to PARI/GP, and most feedback
 should be directed there. Instructions and archives can be consulted at
-\bprog
-  http://pari.math.u-bordeaux1.fr/lists-index.html
- at eprog\noindent The most important are:
+$$ \url{http://pari.math.u-bordeaux1.fr/lists-index.html} $$
+%
+The most important are:
 
 \item \kbd{pari-announce} (\emph{read-only}): to announce major version
 changes. You cannot write to this one, but you should probably subscribe.
@@ -603,7 +612,7 @@ following form (BibTeX format):
 @@manual{PARI2,
     organization = "{The PARI~Group}",
     title        = "{PARI/GP version @vers}",
-    year         = 2014,
+    year         = 2015,
     address      = "Bordeaux",
     note         = "available from \url{http://pari.math.u-bordeaux.fr/}"
 }
diff --git a/doc/appd.tex b/doc/appd.tex
index f594373..e1e2fb2 100644
--- a/doc/appd.tex
+++ b/doc/appd.tex
@@ -41,10 +41,14 @@ void *child_thread(void *arg)
   pari_thread_free(&pth); /* ... and clean up */
 @eprog
 
-\fun{void}{pari_thread_alloc}{struct pari_thread *pth, size_t s, GEN arg}
-Allocate a PARI stack of size \kbd{s} and associate it, together with the
+\fun{void}{pari_thread_valloc}{struct pari_thread *pth, size_t s, size_t v, GEN arg}
+Allocate a PARI stack of size \kbd{s} which can grow to at most \kbd{v} (as
+with \kbd{parisize} and \kbd{parisizemax}) and associate it, together with the
 argument \kbd{arg}, with the PARI thread data \kbd{pth}.
 
+\fun{void}{pari_thread_alloc}{struct pari_thread *pth, size_t s, GEN arg}
+As above but the stack cannot grow beyond \kbd{s}.
+
 \fun{void}{pari_thread_free}{struct pari_thread *pth}
 Free the PARI stack associated with the PARI thread data \kbd{pth}. This
 is called after the child thread terminates, i.e.~after
diff --git a/doc/develop.tex b/doc/develop.tex
index 03e7151..610abb7 100644
--- a/doc/develop.tex
+++ b/doc/develop.tex
@@ -290,6 +290,22 @@ Return \kbd{cgetg(1, t\_VEC)} if there are no solutions. This requires
 $O(\sqrt{N})$ group operations and uses an auxiliary table containing
 $O(\sqrt{N})$ group elements.
 
+The above is useful for a one-shot computation. If many discrete logs
+are desired:
+\fun{GEN}{gen_Shanks_init}{GEN g, long n, void *E, const struct bb_group *grp}
+return an auxiliary data structure $T$ required to compute a discrete log in
+base $g$. Compute and store all powers $g^i$,  $i < n$.
+
+\fun{GEN}{gen_Shanks}{GEN T, GEN x, ulong N, void *E, const struct bb_group *grp}
+Let $T$ be computed by \tet{gen_Shanks_init}$(g,n,\dots)$.
+Return $k < n N$ such that  $g^k = x$ or \kbd{NULL} if no such index exist.
+It uses $O(N)$ operation in the group and fast table lookups  (in time
+$O(\log n)$). The interface is such that the function may be used when the
+order of the base $g$ is unknown, and hence compute it given only an upper
+bound $B$ for it: e.g. choose $n,N$ such that $nN \geq B$ and compute the
+discrete log $l$ of $g^{-1}$ in base $g$, then use \tet{gen_order}
+with multiple $N = l+1$.
+
 \fun{GEN}{gen_Pollard_log}{GEN x, GEN g, GEN N, void *E, const struct bb_group
 *grp} \hbadness 10000\break
 Generic Pollard rho algorithm. Assuming that $g$ has order $N$, compute an
@@ -367,6 +383,8 @@ $Q$ is of order $m$. (Note: $Q$ needs not be of order $d_2$).
 
 \subsec{Functions returning black box groups}
 
+\fun{const struct bb_group *}{get_Flxq_star}{void **E, GEN T, ulong p}
+
 \fun{const struct bb_group *}{get_FpXQ_star}{void **E, GEN T, GEN p}
 returns a pointer to the black box group $(\F_p[x]/(T))^*$.
 
@@ -504,6 +522,44 @@ parameter $l$ for the evaluation of $n/m$ polynomials of degree $d$.
 Fractional values can be used if the evaluations are done with different
 accuracies, and thus have different weights.
 
+\section{Black box ring}
+
+A black box ring is defined by a \tet{bb_ring} struct, describing methods
+available to handle ring elements:
+\bprog
+struct bb_ring
+{
+  GEN (*add)(void *E, GEN x, GEN y);
+  GEN (*mul)(void *E, GEN x, GEN y);
+  GEN (*sqr)(void *E, GEN x);
+};
+ at eprog
+
+\kbd{add(E,x,y)} returns the sum $x+y$.
+
+\kbd{mul(E,x,y)} returns the product $x\*y$.
+
+\kbd{sqr(E,x)} returns the square $x^2$.
+
+\fun{GEN}{gen_fromdigits}{GEN v, GEN B, void *E, struct bb_ring *r}
+where $B$ is a ring element and $v=[c_0,\ldots,c_{n-1}]$ a vector of ring elements,
+return $\sum_{i=0}^n c_i\*B^i$ using binary splitting.
+
+\fun{GEN}{gen_digits}{GEN x, GEN B, long n, void *E, struct bb_ring *r,
+                          GEN (*div)(void *E, GEN x, GEN y, GEN *r)}
+
+(Require the ring to be Euclidean)
+
+\kbd{div(E,x,y,\&r)} performs the Euclidean division of $x$ by $y$ in the ring
+$R$, returning the quotient $q$ and setting $r$ to the residue so that
+$x=q\*y+r$ holds. The residue must belong to a fixed set of representatives of
+$R/(y)$.
+
+The argument $x$ being a ring element, \kbd{gen\_digits} returns a vector of
+ring elements $[c_0,\ldots,c_{n-1}]$ such that $x = \sum_{i=0}^n c_i\*B^i$.
+Furthermore for all $i\ne n-1$, the elements $c_i$ belonging to the fixed set
+of representatives of $R/(B)$.
+
 \section{Black box free $\Z_p$-modules}
 
 (Very experimental)
@@ -548,6 +604,31 @@ subproduct of computing the function. The vector $v$ allows \kbd{eval} to
 provide these to \kbd{invd}. The implementation of \kbd{invd} will generally
 involves the use of the function \kbd{gen\_ZpX\_Dixon}.
 
+\section{$\F_{l^2}$ field for small primes $l$}
+Let $l>2$ be a prime \kbd{ulong}.  A \kbd{Fl2} is an element of the finite
+field $\F_{l^2}$ represented (currently) by a \kbd{Flx} of degree at most $1$
+modulo a polynomial of the form $x^2-D$ for some non square $0\leq D<p$.
+Below \kbd{pi} denotes the pseudo inverse of \kbd{p}, see \kbd{Fl\_mul\_pre}
+
+\fun{int}{Fl2_equal1}{GEN x} return $1$ if $x=1$, $0$ else.
+
+\fun{GEN}{Fl2_mul_pre}{GEN x, GEN y, ulong D, ulong p, ulong pi} return $x\*y$
+
+\fun{GEN}{Fl2_sqr_pre}{GEN x, ulong D, ulong p, ulong pi} return $x^2$
+
+\fun{GEN}{Fl2_inv_pre}{GEN x, ulong D, ulong p, ulong pi} return $x^{-1}$
+
+\fun{GEN}{Fl2_pow_pre}{GEN x, GEN n, ulong D, ulong p, ulong pi} return $x^n$
+
+\fun{GEN}{Fl2_sqrtn_pre}{GEN a, GEN n, ulong D, ulong p, ulong pi, GEN *zeta}
+as \kbd{Flxq\_sqrtn}
+
+\fun{GEN}{Fl2_norm_pre}{GEN x, GEN n, ulong D, ulong p, ulong pi} return the
+norm of $x$.
+
+\fun{GEN}{Flx_Fl2_eval_pre}{GEN P, GEN x, ulong D, ulong p, ulong pi}
+return $P(x)$.
+
 \section{Public functions useless outside of GP context}
 
 These functions implement GP functionality for which the C language or
@@ -658,19 +739,33 @@ used to implement \kbd{[x<-b,c(x)]}.
 \fun{GEN}{vecselapply}{void *Epred, long (*pred)(void* E, GEN x), void *Efun, GEN (*fun)(void* E, GEN x), GEN A}
 used to implement \kbd{[a(x)|x<-b,c(x)]}.
 
-\subsec{Function related to the GP parser}
+\subsec{Local precision}
+
+Theses functions allow to change \kbd{realprecision} locally when
+calling the GP interpretor.
+
+\fun{void}{push_localprec}{long p} set the local precision to $p$.
+
+\fun{void}{pop_localprec}{void} reset the local precision to the previous
+value.
 
-The GP parser can generate an opcode saving the current lexical context
-(pairs made of a lexical variable name and its value) in a \kbd{GEN}, called
-\kbd{pack} in the sequel. These can be used from debuggers (e.g. gp's break
-loop) to track values of lexical variable. Indeed, lexical variables have
-disappeared from the compiled code, only their values in a given scope exist
-(on some value stack). Provided the parser generated the proper opcode, there
-remains a trace of lexical variable names and everything can still be
-unravelled.
+\fun{long}{get_localprec}{void} returns the current local precision.
+
+\subsec{Functions related to the GP evaluator}
+
+The prototype code \kbd{C} instructs the GP compiler to save the current
+lexical context (pairs made of a lexical variable name and its value)
+in a \kbd{GEN}, called \kbd{pack} in the sequel. This \kbd{pack} can be used
+to evaluate expressions in the corresponding lexical context, providing it is
+current.
 
 \fun{GEN}{localvars_read_str}{const char *s, GEN pack} evaluate the string $s$
-in the lexical context given by \kbd{pack}.  Used by \tet{geval_gp} in GP.
+in the lexical context given by \kbd{pack}.  Used by \tet{geval_gp} in GP
+to implement the behaviour below:
+\bprog
+? my(z=3);eval("z=z^2");z
+%1 = 9
+ at eprog
 
 \fun{long}{localvars_find}{GEN pack, entree *ep} does \kbd{pack} contain
 a pair whose variable corresponds to \kbd{ep}? If so, where is the
@@ -773,23 +868,23 @@ it is actually valid. This is used by GP2C -C.
 
 PARI provides an abstraction for doing parallel computations.
 
-\fun{void}{mt_queue_start}{struct pari\_mt *pt, GEN worker} Let \kbd{worker}
+\fun{void}{mt_queue_start}{struct pari_mt *pt, GEN worker} Let \kbd{worker}
 be a \typ{CLOSURE} object of arity $1$.  Initialize the structure \kbd{pt}
 to evaluate \kbd{worker} in parallel.
 
-\fun{void}{mt_queue_submit}{struct pari\_mt *pt, long taskid, GEN task} Submit
+\fun{void}{mt_queue_submit}{struct pari_mt *pt, long taskid, GEN task} Submit
 \kbd{task} to be evaluated by \kbd{worker}, or \kbd{NULL} if no further task
 is left to be submitted. The value \kbd{taskid} is user-specified and allows
 to later match up results and submitted tasks.
 
-\fun{GEN}{mt_queue_get}{struct pari\_mt *pt, long *taskid, long *pending}
+\fun{GEN}{mt_queue_get}{struct pari_mt *pt, long *taskid, long *pending}
 Return the result of the evaluation by \kbd{worker} of one of the previously
 submitted tasks. Set \kbd{pending} to the number of remaining pending tasks.
 Set \kbd{taskid} to the value associate to this task by
 \kbd{mt\_queue\_submit}.  Returns \kbd{NULL} if more tasks need to be
 submitted.
 
-\fun{void}{mt_queue_end}{struct pari\_mt *pt} End the parallel execution.
+\fun{void}{mt_queue_end}{struct pari_mt *pt} End the parallel execution.
 
 Calls to \tet{mt_queue_submit} and \tet{mt_queue_get} must alternate: each
 call to \tet{mt_queue_submit} must be followed by a call to
diff --git a/doc/gphelp.in b/doc/gphelp.in
index 79d3d11..00ff6bd 100755
--- a/doc/gphelp.in
+++ b/doc/gphelp.in
@@ -1,7 +1,4 @@
-#!@perl@
-#
-# $Id$
-#
+#!@runtime_perl@
 # Copyright (C) 2000  The PARI group.
 #
 # This file is part of the PARI/GP package.
@@ -75,7 +72,7 @@ cleanexit();
 # Procedures
 #
 sub cleanexit {
-  print "\e[0m" unless $to_pod;
+  print "\e[0m" unless $to_pod or $raw;
   exit 0;
 }
 
@@ -287,7 +284,7 @@ sub treat {
   }
 
   s/(\W)/\\$1/g;
-  s/_/\\\\_/g;
+  s/_/\\\\_/g if (!/^se\\:/);
       ($pipe && open(DOC,"$pipe $docfile |"))
   || (!$pipe && open(DOC,"$docfile")) || die "Cannot open $docfile: $!";
   return &apropos($_) if ($apropos);
@@ -298,7 +295,7 @@ sub treat {
 
   my ($first);
   my ($pat) = $help;
-  if ($pat =~ /[a-zA-Z]$/) { $pat .= '\b'; } else { $pat .= '}'; }
+  if ($pat =~ /[a-zA-Z0-9]$/) { $pat .= '\b'; } else { $pat .= '}'; }
   while (<DOC>)
   {
     if (/\\(subsubsec[a-z]*|subsec[a-z]*|section|chapter|label){$pat/)
@@ -388,6 +385,7 @@ sub apropos_check {
   s/\\pow/^/;
   s/\\%/%/;
   s/\\bs/\\/;
+  s/\\_/_/g;
   s/\\\#/\#/g;
   s,\+\$/\$-,+/-,;
   s/\$\(.*//; # remove argument lists
@@ -716,11 +714,17 @@ sub inittr {
 	);
 }
 
-sub indent_equally { my $in = shift; $in =~ s/^[ \t]*/    /mg; $in}
+sub indent_equally { my $in = shift; $in =~ s/^[ \t]*/    /mg; $in }
+sub quote { my $in = shift; $in =~ s/~/\\~/g; $in }
 
 sub basic_subst {
   local($_) = shift;
 
+  s/\\teb\{([^\}]*)\}/"\\sidx{$1}$tr{startbold}" . quote($1) . "$tr{endbold}"/eg;
+  s/\\tet\{([^\}]*)\}/"\\sidx{$1}$tr{startcode}" . quote($1) . "$tr{endcode}"/eg;
+  s/\\url\{([^\}]*)\}/"\\sidx{$1}$tr{startcode}" . quote($1) . "$tr{endcode}"/eg;
+  s/\\tev\{([^\}]*)\}/"\\sidx{$1}$tr{startit}" . quote($1) . "$tr{endit}"/eg;
+
   s/(\S)[ \t]*\n[ \t]+/$1\n/gm;
   s/([^\\])\\\{/$1$tr{obr}/g;
   s/([^\\])\\\}/$1$tr{cbr}/g;
@@ -853,7 +857,7 @@ sub basic_subst {
   s/\\langle(?![a-zA-Z])\s*/$tr{startcode}$tr{lt}$tr{endcode}/g;
   s/\\rightarrow(?![a-zA-Z])\s*/$tr{startcode}--$tr{gt}$tr{endcode}/g;
   s/\\longleftrightarrow(?![a-zA-Z])\s*/$tr{startcode}$tr{lt}-----$tr{gt}$tr{endcode}/g;
-  s/\\mapsto(?![a-zA-Z])\s*/$tr{startcode}|---$tr{gt}$tr{endcode}/g;
+  s/\\mapsto(?![a-zA-Z])\s*/$tr{startcode}:---$tr{gt}$tr{endcode}/g;
   s/ *\\geq?(?![a-zA-Z]) *([^ ])/ $tr{startcode}$tr{gt}=$tr{endcode} $1/g;
   s/ *\\leq?(?![a-zA-Z]) *([^ ])/ $tr{startcode}$tr{lt}=$tr{endcode} $1/g;
   s/ *\\gg?(?![a-zA-Z]) *([^ ])/ $tr{startcode}$tr{gt}$tr{gt}$tr{endcode} $1/g;
@@ -876,9 +880,6 @@ sub basic_subst {
   s/\\item/$tr{startbold}*$tr{endbold}/g;
   s/^ *\\misctitle\{([^\}]*)\}/\@3$tr{startbold}$1.$tr{endbold}/g;
   s/\\subsec\{([^\}]*)\}/\@3$tr{startbold}$1.$tr{endbold}/g unless $to_pod;
-  s/\\teb\{([^\}]*)\}/\\sidx{$1}$tr{startbold}$1$tr{endbold}/g;
-  s/\\tet\{([^\}]*)\}/\\sidx{$1}$tr{startcode}$1$tr{endcode}/g;
-  s/\\tev\{([^\}]*)\}/\\sidx{$1}$tr{startit}$1$tr{endit}/g;
   s/\\\$/$tr{ldollar}/g;
   s/\\kbd\s*\{\s*</\\kbd{$tr{lt}/g if $to_pod;
   s/\\kbd\s*\{\s*>/\\kbd{$tr{gt}/g if $to_pod;
diff --git a/doc/parimacro.tex b/doc/parimacro.tex
index d5a5817..21077e5 100644
--- a/doc/parimacro.tex
+++ b/doc/parimacro.tex
@@ -214,6 +214,9 @@
 \def\@kbdidx#1{{\tt\@idx{#1}}}
 \def\tet{\gdef\f at nt{tt}\let\do=\@kbdidx\doverb}
 
+\def\@url#1{\hbox{\tt#1}}
+\def\url{\let\do=\@url\doverb}
+
 % to index + set up as var (variable)
 \def\@kbdvar#1{{\it\@idx{#1}\/}}
 \def\tev{\gdef\f at nt{it}\let\do=\@kbdvar\doverb}
@@ -344,7 +347,7 @@
 \def\copyrightpage{
 \begintitle
 \vskip 14cm
-\noindent Copyright \copyright\ 2000--2014 The PARI Group
+\noindent Copyright \copyright\ 2000--2015 The PARI Group
 \medskip\par
 \noindent Permission is granted to make and distribute verbatim copies of
 this manual provided the copyright notice and this permission notice are
@@ -355,7 +358,7 @@ translations, of this manual under the conditions for verbatim copying,
 provided also that the entire resulting derived work is distributed under the
 terms of a permission notice identical to this one.
 \bigskip\par
-\noindent PARI/GP is Copyright \copyright\ 2000--2014 The PARI Group
+\noindent PARI/GP is Copyright \copyright\ 2000--2015 The PARI Group
 \medskip\par
 \noindent PARI/GP 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
diff --git a/doc/refcard.tex b/doc/refcard.tex
index 27a7163..58efb19 100644
--- a/doc/refcard.tex
+++ b/doc/refcard.tex
@@ -16,10 +16,10 @@
 %% which I modified from his GNU emacs reference card
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \def\TITLE{Pari/GP reference card}
-\def\versionnumber{2.27}% Version of this reference card
-\def\PARIversion{2.6.1}% Version of PARI described on this reference card
-\def\year{2013}
-\def\month{September}
+\def\versionnumber{2.28}% Version of this reference card
+\def\PARIversion{2.8.0}% Version of PARI described on this reference card
+\def\year{2015}
+\def\month{April}
 
 \special{papersize=29.7cm,21cm}
 
@@ -315,6 +315,7 @@ To exit \kbd{gp}, type \kbd{quit}, \kbd{\\q}, or \kbd{<C-D>} at prompt.\hfill
 \li{\typ{MAT}. Matrices}{[$x,y$;$z,t$;$u,v$]}
 \li{\typ{LIST}. Lists}{List$($[$x,y,z$]$)$}
 \li{\typ{STR}. Strings}{"abc"}
+\li{\typ{INFINITY}. $\pm\infty$}{+oo, -oo}
 
 \section{Reserved Variable Names}
 \li{$\pi=3.14\dots$, $\gamma=0.57\dots$, $C=0.91\dots$}{Pi{\rm, }Euler{\rm, }Catalan}
diff --git a/doc/translations b/doc/translations
index a564e5b..f18f5e1 100644
--- a/doc/translations
+++ b/doc/translations
@@ -137,13 +137,14 @@ Emacs           @Using GP under GNU Emacs at 2
 3               @Transcendental functions
 4               @Arithmetic functions
 5               @Functions related to elliptic curves
-6               @Functions related to general number fields
-7               @Polynomials and power series
-8               @Vectors, matrices, linear algebra and sets
-9               @Sums, products, integrals and similar functions
-10              @Plotting functions
-11              @Programming in GP: control statements
-13              @GP operators at 2
+6               @Functions related to modular forms and modular symbols
+7               @Functions related to general number fields
+8               @Polynomials and power series
+9               @Vectors, matrices, linear algebra and sets
+10              @Sums, products, integrals and similar functions
+11              @Plotting functions
+12              @Programming in GP: control statements
+14              @GP operators at 2
 ell             @Functions related to elliptic curves
 nf              @Number field structures
 bnf             @Number field structures
diff --git a/doc/tutorial.tex b/doc/tutorial.tex
index 4593a53..5e9c2ce 100644
--- a/doc/tutorial.tex
+++ b/doc/tutorial.tex
@@ -168,19 +168,8 @@ and come back later)
 1) If you are a PARI old timer, say the last version of PARI you used was
 released around 1996, you have certainly noticed already that many many
 things changed between the older 1.39.xx versions and this one.
-Conspicuously, most function names have been changed.
-
-Of course, this is going to break all your nice old scripts. Well, you can
-either change the compatibility level (typing \kbd{default(compatible, 3)}
-will send you back to the stone-age behavior of good ol' version 1.39.15),
-or rewrite the scripts. We really advise you to do the latter if they are not
-too long, since they can now be written much more cleanly than before,
-especially with lexical scoping (\kbd{my}) and the new control statements
-(\kbd{break}, \kbd{next}, \kbd{return}). Besides it'll be as good a way as any
-to get used to the new names.
-
-To know how a specific function was changed, just type \kbd{whatnow({\rm
-function})}.
+Conspicuously, most function names have been changed. To know how a specific
+function was changed, type \kbd{whatnow({\rm function})}.
 
 2) It seems that the text implicitly says that as soon as an imprecise number
 is entered, the result will be imprecise. Is this always true? There is a
@@ -439,7 +428,7 @@ of course transpose. You don't see much difference in the output, except for
 the tilde at the end. However, now type \b{b}: lo and behold, the column
 vector appears as a proper vertical thingy now. The \b{b} command is used
 mainly for this purpose. The length of a vector is given by, well
-\kbd{length} of course. The shorthand ``cardinal'' notation \kbd{\#v} for
+\kbd{length} of course. The shorthand ``cardinality'' notation \kbd{\#v} for
 \kbd{length(v)} is also available, for instance \kbd{v[\#v]} is the last
 element of \kbd{v}.
 
@@ -524,9 +513,10 @@ the final expression to get zero entries, as in \kbd{matrix(10,20)}.
 equal to the square root of $-1$. Hence it is forbidden to use it as a
 variable. Try typing \kbd{vector(10,I, I\pow 2)}, the error message that you
 get clearly indicates that \kbd{gp} does not consider \kbd{I} as a variable.
-There are other reserved variable names: \kbd{Pi}, \kbd{Euler} and
-\kbd{Catalan}. All function names are forbidden as well. On the other hand
-there is nothing special about \kbd{i}, \kbd{pi}, \kbd{euler} or \kbd{catalan}.
+There are other reserved variable names: \kbd{Pi}, \kbd{Euler},
+\kbd{Catalan} and \kbd{oo}. All function names are forbidden as well. On the
+other hand there is nothing special about \kbd{i}, \kbd{pi}, \kbd{euler} or
+\kbd{catalan}.
 
 When creating vectors or matrices, it is often useful to use Boolean
 operators and the \kbd{if()} statement. Indeed, an \kbd{if} expression has a
@@ -3236,18 +3226,20 @@ won't forget to look them up in the manual, will you?)
 Output is done via variants of the familiar \kbd{print} (to screen),
 \kbd{write} (to a file). Input via \kbd{read} (from file), \kbd{input}
 (querying user), or \kbd{extern} (from an external auxiliary program).
-Perhaps the most useful simple command we haven't seen yet is
-\kbd{allocatemem} which increase the size of \kbd{gp}'s ``scratch space''. If
-you regularly see \kbd{PARI stack overflows!} messages, think about this
-one.
 
 To customize \kbd{gp}, e.g.~increase the default stack space or load your
 private script libraries on startup, look up \kbd{The preferences file}
-section in the User's manual. For clarity, it is advisable  to declare local
-variables in user functions (and in fact, with the smallest possible scope),
-as we have done so far with the keyword \kbd{my}. One is usually better off
-avoiding global variables altogether, but you are the sole master on board at
-this point.
+section in the User's manual. We strongly advise to set \kbd{parisizemax} to
+a large non-zero value, about what you believe your machine can stand: this
+both limits the amount of memory PARI will use for its computation (thereby
+keeping your machine usable), and let PARI increases its stack size (up to
+this limit) to accomodate large computations. If you regularly see \kbd{PARI
+stack overflows} messages, think about this one!
+
+For clarity, it is advisable  to declare local variables in user functions
+(and in fact, with the smallest possible scope), as we have done so far with
+the keyword \kbd{my}. As usual, one is usually better off avoiding global
+variables altogether.
 
 \emph{Break loops} are more powerful than we saw: look up \kbd{dbg\_down} /
 \kbd{dbg\_up} (to get a chance to inspect local variables in various scopes)
diff --git a/doc/usersFUNCS.tex b/doc/usersFUNCS.tex
index f3dc1c2..125686f 100644
--- a/doc/usersFUNCS.tex
+++ b/doc/usersFUNCS.tex
@@ -343,9 +343,9 @@ The extra operator \kbd{===} tests whether two objects are identical and is
 much stricter than \kbd{==} : objects of different type or length are never
 identical.
 
-For the purpose of comparison, \typ{STR} objects are strictly larger than any
-other non-string type; two \typ{STR} objects are compared using the standard
-lexicographic order.
+For the purpose of comparison, \typ{STR} objects are compared using
+the standard lexicographic order, and comparing them to objects
+of a different type raises an exception.
 
 GP accepts \kbd{<>} as a synonym for \kbd{!=}. On the other hand, \kbd{=} is
 definitely \emph{not} a synonym for \kbd{==}: it is the assignment statement.
@@ -720,14 +720,50 @@ memory and require at least 2MB stack to avoid stack overflows.
 \item \tet{gen} returns the generators of $E(\Q)$, if known (from John
   Cremona's database)
 
+\subsubsec{Curves over number fields}
+
+\item \tet{nf} returns the number field over which $E$ is defined.
+
+
 %SECTION: elliptic_curves
 
+\section{Functions related to modular forms and modular symbols}
+
+Let $\Delta := \text{Div}^0(\P^1(\Q))$ be the abelian group of divisors of
+degree $0$ on the rational projective line. The standard $\text{GL}(2,\Q)$
+action on $\P^1(\Q)$ via homographies naturally extends to $\Delta$. Given
+
+\item $G$ a finite index subgroup of $\text{SL}(2,\Z)$,
+
+\item a field $F$ and a finite dimensional representation $V/F$ of
+  $\text{GL}(2,\Q)$,
+
+\noindent we consider the space of \emph{modular symbols} $M :=
+\text{Hom}_G(\Delta, V)$. This finite dimensional $F$-vector
+space is a $G$-module, canonically isomorphic to $H^1_c(X(G), V)$,
+and allows to compute modular forms for $G$.
+
+Currently, we only support the groups $\Gamma_0(N)$ ($N > 1$ an integer)
+and the representations $V_k = \Q[X,Y]_{k-2}$ ($k \geq 2$ an integer) over
+$\Q$. We represent a space of modular symbols by an \var{ms} structure,
+created by the function \tet{msinit}. It encodes basic data associated to the
+space: chosen $\Z[G]$-generators $(g_i)$ for $\Delta$ (and relations among
+those) and an $F$-basis of $M$. A modular symbol $s$ is thus given either in
+terms of this fixed basis, or as a collection of values $s(g_i)$
+satisfying certain relations.
+
+A subspace of $M$ (e.g. the cuspidal or Eisenstein subspaces, the new or
+old modular symbols, etc.) is given by a structure allowing quick projection
+and restriction of linear operators; its first component is a matrix whose
+columns  form  an $F$-basis  of the subspace.
+
+%SECTION: modular_forms
+
 \section{Functions related to general number fields}
 
-In this section can be found functions which are used almost exclusively for
-working in general number fields. Other less specific functions can be found
-in the next section on polynomials. Functions related to quadratic number
-fields are found in section \secref{se:arithmetic} (Arithmetic functions).
+In this section, we describe functions related to general number fields.
+Functions related to quadratic number fields are found in
+section \secref{se:arithmetic} (Arithmetic functions).
 
 \subsec{Number field structures}
 
@@ -1122,6 +1158,97 @@ recomputing the integral basis and analogous quantities.
 
 %SECTION: number_fields
 
+\section{Functions related to associative and central simple algebras}
+
+This section collects functions related to associative algebras and central
+simple algebras over number fields. Let $A$ be a finite-dimensional unitary
+associative algebra over a field $K$. We say that $A$ is \emph{central} if
+the center of $A$ is $K$, and that $A$ is \emph{simple} if it has no
+nontrivial two-sided ideals.
+
+\par We provide functions to manipulate associative algebras of finite
+dimension over~$\Q$ or~$\F_p$. We represent them by the left multiplication
+table on a basis over the prime subfield. The function \kbd{algtableinit}
+creates the object representing an associative algebra. We also provide
+functions to manipulate central simple algebras over number fields. We
+represent them either by the left multiplication table on a basis over the
+center, or by a cyclic algebra (see below). The function~\kbd{alginit} creates
+the object representing a central simple algebra.
+
+\par The set of elements of an algebra~$A$ that annihilate every simple left
+$A$-module is a two-sided ideal, called the \emph{Jacobson radical} of~$A$.
+An algebra is \emph{semisimple} if its Jacobson radical is trivial. A
+semisimple algebra is isomorphic to a direct sum of simple algebras. The
+dimension of a central simple algebra~$A$ over $K$ is always a square $d^2$,
+and the integer $d$ is called the \emph{degree} of the algebra~$A$ over~$K$.
+A central simple algebra~$A$ over a field~$K$ is always isomorphic to~$M_d(D)$
+for some integer~$d$ and some central division algebra~$D$ of degree~$e$ : the
+integer~$e$ is called the \emph{index} of~$A$.
+
+\par Let $L/K$ be a cyclic extension of degree $d$, let $\sigma$ be a
+generator of $\text{Gal}(L/K)$ and let $b\in K^*$. Then the \emph{cyclic
+algebra} $(L/K,\sigma,b)$ is the algebra $\bigoplus_{i=0}^{d-1}x^iL$ with
+$x^d=b$ and $\ell x=x\sigma(\ell)$ for all~$\ell\in L$. The algebra
+$(L/K,\sigma,b)$ is a central simple $K$-algebra of degree~$d$, and it is an
+$L$-vector space. Left multiplication is $L$-linear and induces a $K$-algebra
+homomorphism $(L/K,\sigma,b)\to M_d(L)$.
+
+\par Let $K$ be a nonarchimedean local field with uniformizer $\pi$, and let
+$L/K$ be the unique unramified extension of degree $d$. Then every central
+simple algebra $A$ of degree $d$ over $K$ is isomorphic to
+$(L/K,\text{Frob},\pi^h)$ for some integer $h$. The element $h/d\in
+(1/d)\Z/\Z\subset\Q/\Z$ is called the \emph{Hasse invariant} of $A$.
+
+\par Let~$A$ be an algebra of finite dimension over~$\Q$. An \emph{order}
+in~$A$ is a finitely generated $\Z$-submodule~${\cal O}$ such that~$\Q{\cal
+O} = A$, that is also a subring with unit. We define natural orders in
+central simple algebras defined by a cyclic algebra or by a multiplication
+table over the center. Let~$A = (L/K,\sigma,b) = \bigoplus_{i=0}^{d-1}x^iL$
+be a cyclic algebra over a number field~$K$ of degree~$n$ with ring of
+integers~$\Z_K$. Let~$\Z_L$ be the ring of integers of~$L$, and assume
+that~$b$ is integral. Then the submodule~${\cal O} =
+\bigoplus_{i=0}^{d-1}x^i\Z_L$ is an order in~$A$, called the \emph{natural
+order}. Let~$\omega_0,\dots,\omega_{nd-1}$ be a~$\Z$-basis of~$\Z_L$. The
+\emph{natural basis} of~${\cal O}$ is~$b_0,\dots,b_{nd^2-1}$ where~$b_i =
+x^{i/(nd)}\omega_{(i \mod nd)}$. Now let~$A$ be a central simple algebra of
+degree~$d$ over a number field~$K$ of degree~$n$ with ring of
+integers~$\Z_K$. Let~$e_0,\dots,e_{d^2-1}$ be a basis of~$A$ over~$K$ and
+assume that the left multiplication table of~$A$ on~$(e_i)$ is integral. Then
+the submodule~${\cal O} = \bigoplus_{i=0}^{d^2-1}\Z_K e_i$ is an order
+in~$A$, called the \emph{natural order}. Let~$\omega_0,\dots,\omega_{n-1}$ be
+a~$\Z$-basis of~$\Z_K$. The \emph{natural basis} of~${\cal O}$
+is~$b_0,\dots,b_{nd^2-1}$ where~$b_i = \omega_{(i \mod n)}e_{i/n}$.
+
+\par As with number fields, we represent elements of central simple algebras
+in two ways, called the \emph{algebraic representation} and the \emph{basis
+representation}, and you can convert betweeen the two with the functions
+\kbd{algalgtobasis} and \kbd{algbasistoalg}. In every central simple algebra
+object, we store a~$\Z$-basis of an order~${\cal O}_0$, and the basis
+representation is simply a \typ{COL} with coefficients in~$\Q$ expressing the
+element in that basis. If no maximal order was computed, then~${\cal O}_0$ is
+the natural order. If a maximal order was computed, then~${\cal O}_0$ is a
+maximal order containing the natural order. For a cyclic algebra~$A =
+(L/K,\sigma,b)$, the algebraic representation is a \typ{COL} with coefficients
+in~$L$ representing the element in the decomposition~$A =
+\bigoplus_{i=0}^{d-1}x^iL$. For a central simple algebra defined by a
+multiplication table over its center~$K$ on a basis~$(e_i)$, the algebraic
+representation is a \typ{COL} with coefficients in~$K$ representing the element
+on the basis~$(e_i)$.
+
+\misctitle{Warning} The coefficients in the decomposition~$A =
+\bigoplus_{i=0}^{d-1}x^iL$ are not the same as those in the decomposition~$A
+= \bigoplus_{i=0}^{d-1}Lx^i$! The $i$-th coefficients are related by
+conjugating by~$x^i$, which on~$L$ amounts to acting by~$\sigma^i$.
+
+\misctitle{Warning} For a central simple algebra over $\Q$ defined by a
+multiplication table, we cannot distinguish between the basis and the algebraic
+representations from the size of the vectors. The behaviour is then to always
+interpret the column vector as a basis representation if the coefficients are
+\typ{INT} or \typ{FRAC}, and as an algebraic representation if the coefficients
+are \typ{POL} or \typ{POLMOD}.
+
+%SECTION: algebras
+
 \section{Polynomials and power series}
 
 We group here all functions which are specific to polynomials or power
@@ -1346,7 +1473,8 @@ identically with both.
 %SECTION: programming/parallel
 
 \section{GP defaults}
-\label{se:gp_defaults} This section documents the GP defaults
+\label{se:gp_defaults} This section documents the GP defaults, be sure to
+check out \tet{parisize} and \tet{parisizemax} !
 
 %SECTION: default
 
diff --git a/doc/usersch1.tex b/doc/usersch1.tex
index 12a057d..a03f2f9 100644
--- a/doc/usersch1.tex
+++ b/doc/usersch1.tex
@@ -60,17 +60,17 @@ can refer to the complete function description in Chapter 3.
 
 \subsectitle{How to get the latest version} Everything can be found on
 PARI's home page:
-\bprog
-  http://pari.math.u-bordeaux.fr/
- at eprog\noindent From that point you may access all sources, some binaries,
+$$\url{http://pari.math.u-bordeaux.fr/}.$$
+%
+From that point you may access all sources, some binaries,
 version information, the complete mailing list archives, frequently asked
 questions and various tips. All threaded and fully searchable.
 
 \subsectitle{How to report bugs} Bugs are submitted online to our Bug
 Tracking System, available from PARI's home page, or directly from the URL
-\bprog
-  http://pari.math.u-bordeaux.fr/Bugs/
- at eprog\noindent Further instructions can be found on that page.
+$$\url{http://pari.math.u-bordeaux.fr/Bugs/}.$$
+%
+Further instructions can be found on that page.
 
 \section{Multiprecision kernels / Portability}
 
diff --git a/doc/usersch2.tex b/doc/usersch2.tex
index 0389ad5..73bec0a 100644
--- a/doc/usersch2.tex
+++ b/doc/usersch2.tex
@@ -18,6 +18,11 @@ use of the \kbd{gp} programmable calculator.
 special Emacs shell, described in \secref{se:emacs}. Specific features of
 this Emacs shell are indicated by an EMACS sign in the left margin.
 
+We briefly mention at this point GNU
+TeXmacs\footnote{*}{\url{http://www.texmacs.org/}}, a free wysiwyg editing
+platform that allows to embed an entire gp session in a document, and
+provides a nice alternative to PariEmacs.
+
 \subsec{Startup}
 
 To start the calculator, the general command line syntax is:
@@ -153,9 +158,9 @@ object:
 ? x
 %2 = x          \\@com a polynomial of degree 1 in the unknown \kbd{x}
 ? print("Hello")
-Hello           \\@com \kbd{void} return value
+Hello           \\@com \kbd{void} return value, 'Hello' printed as side effect
 ? f(x) = x^2
-%3 = (x)->x^2   \\@com a user function
+%4 = (x)->x^2   \\@com a user function
 @eprog
 \noindent In the third example, \kbd{Hello} is printed as a side effect, but
 is not the return value. The \kbd{print} command is a \emph{procedure},
@@ -942,6 +947,12 @@ non trivial information from the error context:
   Mod(6, 12)
 @eprog\noindent We can also rethrow the exception: \kbd{error(E)}.
 
+\subsec{Infinity (\typ{INFINITY})}%
+\kbdsidx{t_INFINITY}
+
+There are only two objects of this type \kbd{+oo} and \kbd{-oo}, representing
+$\pm\infty$.
+
 \section{GP operators}\label{se:operators}
 
 \noindent Loosely speaking, an \idx{operator} is a function, usually
@@ -1146,8 +1157,8 @@ If the expression cannot be parsed in a way where the left hand side is an
 lvalue, raise an error.
 \bprog
 ? x + 1 = 1
-  ***   unused characters: x+1=1
-  ***                         ^--
+  ***   syntax error, unexpected '=', expecting $end or ';': x+1=1
+  ***                                                           ^--
 @eprog
 \leavevmode
 \kbd{\var{op}=}, where \var{op} is any binary operator
@@ -1186,7 +1197,7 @@ M[i,i+j] = M[i,i+j] * 2    -->    M[i,i+j] *= 2
 ? i = 0; while(i<a, i=i+1)
 time = 365 ms.
 ? i = 0; while(i<a, i++)
-time = 352ms.
+time = 352 ms.
 @eprog
 \noindent For the same reason, the shift operators should be preferred to
 multiplication:
@@ -1211,7 +1222,7 @@ associated to values in a given scope.
 followed by any number of keyword characters: \kbd{\_} or alphanumeric
 characters ([\kbd{A-Za-z0-9}]). The built-in function names are reserved and
 cannot be used; see the list with \b{c}, including the constants \kbd{Pi},
-\kbd{Euler}, \kbd{Catalan} and $\kbd{I}=\sqrt{-1}$.
+\kbd{Euler}, \kbd{Catalan}, $\kbd{I}=\sqrt{-1}$ and $\kbd{oo} = \infty$.
 
 GP names are case sensitive. For instance, the symbol \kbd{i} is perfectly
 safe to use, and will not be mistaken for $\kbd{I} = \sqrt{-1}$; analogously,
@@ -1286,7 +1297,9 @@ The answer is that variables are ordered implicitly by the interpreter:
 when a new identifier (e.g~$x$, or $y$ as above) is input, the corresponding
 variable is registered as having a strictly lower priority than any variable in
 use at this point\footnote{*}{This is not strictly true:
-the variable $x$ is predefined and always has the highest possible priority.}%
+the variables $x$ and $y$ are predefined, and satisfy $x > y$.
+Variables of higher priority than $x$ can be created
+using \tet{varhigher}.}%
 . To see the ordering used by \kbd{gp} at any given time, type
 \kbd{variable()}.\kbdsidx{variable}
 
@@ -1627,6 +1640,25 @@ variable name for different parameters of your function:
   ***                                ^----
 @eprog
 
+\misctitle{Functions taking an unlimited number of arguments}
+
+A function taking an unlimited number of arguments is called \emph{variadic}.
+To create such a function, use the syntax
+
+  \kbd{(\var{list of formal variables}, \var{var}[..]) -> \var{seq}}
+
+\noindent The parameter \var{var} is replaced by a vector containing all the
+remaining arguments.
+
+\bprog
+? f(c[..]) = sum(i=1,#c,c[i]);
+? f(1,2,3)
+%1 = 6
+? sep(s,v[..]) = for(i=1,#v-1,print1(v[i],s)); if (#v, print(v[#v]));
+? sep(":", 1, 2, 3)
+1:2:3
+ at eprog
+
 \misctitle{Finishing touch}
 You can add a specific help message for your function using \kbd{addhelp},
 but the online help system already handles it. By default \kbd{?\var{name}}
@@ -2189,10 +2221,14 @@ bytecode; then the latter is evaluated, calling appropriate functions from
 the PARI library. Accordingly, there are two kind of errors: syntax errors
 produced by the compiler, and runtime errors produced by the PARI library
 either by the evaluator itself, or in a mathematical function.
-Both kinds are fatal to your computation: \kbd{gp} will report the error,
-perform some cleanup (restore variables modified while evaluating the
-erroneous command, close open files, reclaim unused memory, etc.), and output
-its usual prompt.
+Both kinds are fatal to your computation: \kbd{gp} will report the error
+and perform some cleanup (restore variables modified while evaluating the
+erroneous command, close open files, reclaim unused memory, etc.).
+
+At this point, the default is to return to the usual prompt, but if the
+\kbd{recover} option (\secref{se:def,recover}) is off then \kbd{gp} exits
+immediately.  This can be useful for batch-mode operation to make untrapped
+errors fatal.
 
 When reporting a \emph{syntax error}, \kbd{gp} gives meaningful
 context by copying (part of) the expression it was trying to compile,
@@ -2556,10 +2592,10 @@ We are aware of three PARI-related Free Software packages to embed PARI in
 other languages. We \emph{neither endorse nor support} any of them, but you
 may want to give them a try if you are familiar with the languages they are
 based on. The first is William Stein's Python-based SAGE\footnote{*}{see
-\kbd{http://sagemath.org/}} system. The second is the \tet{Math::Pari} Perl
+\url{http://sagemath.org/}} system. The second is the \tet{Math::Pari} Perl
 module (see any CPAN mirror), written by Ilya Zakharevich.
 Finally, Michael Stoll has integrated PARI into \tet{CLISP}\footnote{***}{see
-\kbd{http://clisp.cons.org/}}, which is a Common Lisp implementation by Bruno
+\url{http://clisp.cons.org/}}, which is a Common Lisp implementation by Bruno
 Haible, Marcus Daniels and others; this interface has been updated for pari-2
 by Sam Steingold.
 
@@ -2586,18 +2622,17 @@ is described in \secref{se:default}. The basic syntax is
 use, most of these can be abbreviated using \kbd{gp} metacommands
 (mostly, starting with \b), which we shall describe in the next section.
 
-Here we will only describe the available defaults and how they are used. Just
-be aware that typing \kbd{default} by itself will list all of them, as well
-as their current values (see \b{d}). Just after the default name, we give
-between parentheses the initial value when \kbd{gp} starts, assuming you did
-not tamper with factory settings using command-line switches or a~\tet{gprc}.
+Available defaults are described in the reference guide,
+\secref{se:gp_defaults}, the most important one being \tet{parisizemax}.
+Just be aware that typing \kbd{default} by itself will list all of them, as
+well as their current values (see \b{d}).
 
 \misctitle{Note} The suffixes \kbd{k}, \kbd{M} or \kbd{G} can be appended to
 a \var{value} which is a numeric argument, with the effect of multiplying it
 by $10^3$, $10^6$ and $10^9$ respectively. Case is not taken into account
 there, so for instance \kbd{30k} and \kbd{30K} both stand for $30000$. This
-is mostly useful to modify or set the default \kbd{parisize} which typically
-involve a lot of trailing zeroes.
+is mostly useful to modify or set the defaults \kbd{parisize} and
+\kbd{parisizemax} which typically involve a lot of trailing zeroes.
 
 \misctitle{(somewhat technical) Note} As we saw in \secref{se:strings},
 the second argument to \kbd{default} is subject to string context
@@ -2635,9 +2670,6 @@ many shells~--- \kbd{\til} by itself stands for your home directory, and
 \kbd{\til{}user} is expanded to \kbd{user}'s home directory. This is applied
 to all file names\sidx{filename}. \label{se:envir}
 
-Available defaults are described in the reference guide,
-\secref{se:gp_defaults}.
-
 \section{Simple metacommands}\label{se:meta}
 
 \noindent
@@ -2892,6 +2924,10 @@ last two components can be omitted (i.e.~$1$ is understood as version $1.0.0$).
 This is \kbd{true} if \kbd{gp}'s version number satisfies the required
 inequality.
 
+\kbd{BITS\_IN\_LONG} \kbd{==} \var{number}: \var{number} is $32$ (resp.~$64$).
+This is \kbd{true} if \kbd{gp} was built for a 32-bit (resp.~64-bit)
+architecture.
+
 \subsubsec{Commands:}
 After preprocessing, the remaining lines are executed as
 sequence of expressions (as usual, separated by \kbd{;} if necessary). Only
@@ -3073,11 +3109,9 @@ conditions).
 
   For instance, shortly after a \kbd{\til}, we expect a user name, then a
 path to some file. Directly after \kbd{default(} has been typed, we would
-expect one of the \kbd{default} keywords. After \kbd{whatnow(} , we expect
-the name of an old function, which may well have disappeared from this
-version. After a '.', we expect a member keyword. And generally of course, we
-expect any GP symbol which may be found in the hashing lists: functions (both
-yours and GP's), and variables.
+expect one of the \kbd{default} keywords. After a '.', we expect a member
+keyword. And generally of course, we expect any GP symbol which may be found
+in the hashing lists: functions (both yours and GP's), and variables.
 
   If, at any time, only one completion is meaningful, \kbd{gp} will provide it
 together with
diff --git a/doc/usersch3.tex b/doc/usersch3.tex
index d1b391c..ef8ef2b 100644
--- a/doc/usersch3.tex
+++ b/doc/usersch3.tex
@@ -418,6 +418,11 @@ Creates the minimum of $x$ and $y$ when they can be compared.
 
 The library syntax is \fun{GEN}{gmin}{GEN x, GEN y}.
 
+\subsec{powers$(x,n)$}\kbdsidx{powers}\label{se:powers}
+Return the vector $[1,x,\dots,x^n]$.
+
+The library syntax is \fun{GEN}{gpowers}{GEN x, long n}.
+
 \subsec{shift$(x,n)$}\kbdsidx{shift}\label{se:shift}
 Shifts $x$ componentwise left by $n$ bits if $n\ge0$ and right by $|n|$
 bits if $n<0$. May be abbreviated as $x$ \kbd{<<} $n$ or $x$ \kbd{>>} $(-n)$.
@@ -497,9 +502,9 @@ The extra operator \kbd{===} tests whether two objects are identical and is
 much stricter than \kbd{==} : objects of different type or length are never
 identical.
 
-For the purpose of comparison, \typ{STR} objects are strictly larger than any
-other non-string type; two \typ{STR} objects are compared using the standard
-lexicographic order.
+For the purpose of comparison, \typ{STR} objects are compared using
+the standard lexicographic order, and comparing them to objects
+of a different type raises an exception.
 
 GP accepts \kbd{<>} as a synonym for \kbd{!=}. On the other hand, \kbd{=} is
 definitely \emph{not} a synonym for \kbd{==}: it is the assignment statement.
@@ -729,7 +734,7 @@ Also available are
 \subsec{Ser$(s,\{v='x\},\{d=\var{seriesprecision}\})$}\kbdsidx{Ser}\label{se:Ser}
 Transforms the object $s$ into a power series with main variable $v$
 ($x$ by default) and precision (number of significant terms) equal to
-$d$ (= the default \kbd{seriesprecision} by default). If $s$ is a
+$d \geq 0$ ($d = \kbd{seriesprecision}$ by default). If $s$ is a
 scalar, this gives a constant power series in $v$ with precision \kbd{d}.
 If $s$ is a polynomial, the polynomial is truncated to $d$ terms if needed
 \bprog
@@ -1109,6 +1114,7 @@ The library syntax is \fun{GEN}{denom}{GEN x}.
 
 \subsec{digits$(x,\{b={10}\})$}\kbdsidx{digits}\label{se:digits}
 Outputs the vector of the digits of $|x|$ in base $b$, where $x$ and $b$ are integers.
+See \kbd{fromdigits} for the reverse operation.
 
 The library syntax is \fun{GEN}{digits}{GEN x, GEN b = NULL}.
 
@@ -1126,6 +1132,18 @@ $x-\text{floor}(x)$. If $x$ is real, the result is in $[0,1[$.
 
 The library syntax is \fun{GEN}{gfrac}{GEN x}.
 
+\subsec{fromdigits$(x,\{b={10}\})$}\kbdsidx{fromdigits}\label{se:fromdigits}
+Gives the integer formed by the elements of $x$ seen as the digits of a
+number in base $b$.  This is the reverse of \kbd{digits}:
+\bprog
+? digits(1234,5)
+%1 = [1,4,4,1,4]
+? fromdigits([1,4,4,1,4],5)
+%2 = 1234
+ at eprog
+
+The library syntax is \fun{GEN}{fromdigits}{GEN x, GEN b = NULL}.
+
 \subsec{hammingweight$(x)$}\kbdsidx{hammingweight}\label{se:hammingweight}
 If $x$ is a \typ{INT}, return the binary Hamming weight of $|x|$. Otherwise
 $x$ must be of type \typ{POL}, \typ{VEC}, \typ{COL}, \typ{VECSMALL}, or
@@ -1310,6 +1328,15 @@ ordering, starting at $0$.
 
 The library syntax is \fun{GEN}{numtoperm}{long n, GEN k}.
 
+\subsec{oo$(\var{oo})$}\kbdsidx{oo}\label{se:oo}
+Returns an object meaning $+\infty$, for use in functions such as
+\kbd{intnum}. It can be negated (\kbd{-oo} represents $-\infty$), and
+compared to real numbers (\typ{INT}, \typ{FRAC}, \typ{REAL}), with the
+expected meaning: $+\infty$ is greater than any real number and $-\infty$ is
+smaller.
+
+The library syntax is \fun{GEN}{mkoo}{}.
+
 \subsec{padicprec$(x,p)$}\kbdsidx{padicprec}\label{se:padicprec}
 Absolute $p$-adic precision of the object $x$. This is the minimum
 precision of the components of $x$. The result is \tet{LONG_MAX}
@@ -1444,7 +1471,7 @@ version 2.4 included, the internal generator produced pseudo-random numbers
 by means of linear congruences, which were not well distributed in arithmetic
 progressions. We now
 use Brent's XORGEN algorithm, based on Feedback Shift Registers, see
-\kbd{http://wwwmaths.anu.edu.au/\til{}brent/random.html}. The generator has period
+\url{http://wwwmaths.anu.edu.au/~brent/random.html}. The generator has period
 $2^{4096}-1$, passes the Crush battery of statistical tests of L'Ecuyer and
 Simard, but is not suitable for cryptographic purposes: one can reconstruct
 the state vector from a small sample of consecutive values, thus predicting
@@ -1520,9 +1547,17 @@ Also available is \fun{long}{gsizeword}{GEN x} returning a
 number of \emph{words}.
 
 \subsec{sizedigit$(x)$}\kbdsidx{sizedigit}\label{se:sizedigit}
-Outputs a quick bound for the number of decimal
-digits of (the components of) $x$, off by at most $1$. If you want the
-exact value, you can use \kbd{\#Str(x)}, which is slower.
+Outputs a quick upper bound for the number of decimal digits of (the
+components of) $x$, off by at most $1$. More precisely, for a positive
+integer $x$, it computes (approximately) the ceiling of
+$$\kbd{floor}(1 + \log_2 x) \log_{10}2,$$
+
+This function is DEPRECATED, essentially meaningless, and provided for
+backwards compatibility only. Don't use it!
+
+To count the number of decimal digits of a positive integer $x$, use
+\kbd{\#digits(x)}. To estimate (recursively) the size of $x$, use
+\kbd{normlp(x)}.
 
 The library syntax is \fun{long}{sizedigit}{GEN x}.
 
@@ -1559,12 +1594,75 @@ function, and also a power series if $x$ is a monomial. Finally, the
 valuation of a vector, complex or quadratic number is the minimum of the
 component valuations.
 
-If $x=0$, the result is \tet{LONG_MAX} ($2^{31}-1$ for 32-bit machines or
-$2^{63}-1$ for 64-bit machines) if $x$ is an exact object. If $x$ is a
+If $x=0$, the result is \kbd{+oo} if $x$ is an exact object. If $x$ is a
 $p$-adic numbers or power series, the result is the exponent of the zero.
 Any other type combinations gives an error.
 
-The library syntax is \fun{long}{gvaluation}{GEN x, GEN p}.
+The library syntax is \fun{GEN}{gpvaluation}{GEN x, GEN p}.
+Also available is
+\fun{long}{gvaluation}{GEN x, GEN p}, which returns \tet{LONG_MAX} if $x = 0$
+and the valuation as a \kbd{long} integer.
+
+\subsec{varhigher$(\var{name},\{v\})$}\kbdsidx{varhigher}\label{se:varhigher}
+Return a variable \emph{name} whose priority is higher
+than the priority of $v$ (of all existing variables if $v$ is omitted).
+This is a counterpart to \tet{varlower}.
+\bprog
+? Pol([x,x], t)
+ ***   at top-level: Pol([x,x],t)
+ ***                 ^------------
+ *** Pol: incorrect priority in gtopoly: variable x <= t
+? t = varhigher("t", x);
+? Pol([x,x], t)
+%3 = x*t + x
+ at eprog\noindent This routine is useful since new GP variables directly
+created by the interpreter always have lower priority than existing
+GP variables. When some basic objects already exist in a variable
+that is incompatible with some function requirement, you can now
+create a new variable with a suitable priority instead of changing variables
+in existing objects:
+\bprog
+? K = nfinit(x^2+1);
+? rnfequation(K,y^2-2)
+ ***   at top-level: rnfequation(K,y^2-2)
+ ***                 ^--------------------
+ *** rnfequation: incorrect priority in rnfequation: variable y >= x
+? y = varhigher("y", x);
+? rnfequation(K, y^2-2)
+%3 = y^4 - 2*y^2 + 9
+ at eprog\noindent
+\misctitle{Caution 1}
+The \emph{name} is an arbitrary character string, only used for display
+purposes and need not be related to the GP variable holding the result, nor
+to be a valid variable name. In particular the \emph{name} can
+not be used to retrieve the variable, it is not even present in the parser's
+hash tables.
+\bprog
+? x = varhigher("#");
+? x^2
+%2 = #^2
+ at eprog
+\misctitle{Caution 2} There are a limited number of variables and if no
+existing variable with the given display name has the requested
+priority, the call to \kbd{varhigher} uses up one such slot. Do not create
+new variables in this way unless it's absolutely necessary,
+reuse existing names instead and choose sensible priority requirements:
+if you only need a variable with higher priority than $x$, state so
+rather than creating a new variable with highest priority.
+\bprog
+\\ quickly use up all variables
+? n = 0; while(1,varhigher("tmp"); n++)
+ ***   at top-level: n=0;while(1,varhigher("tmp");n++)
+ ***                             ^-------------------
+ *** varhigher: no more variables available.
+ ***   Break loop: type 'break' to go back to GP prompt
+break> n
+65510
+\\ infinite loop: here we reuse the same 'tmp'
+? n = 0; while(1,varhigher("tmp", x); n++)
+ at eprog
+
+The library syntax is \fun{GEN}{varhigher}{const char *name, long v = -1}, where \kbd{v} is a variable number.
 
 \subsec{variable$(\{x\})$}\kbdsidx{variable}\label{se:variable}
 Gives the main variable of the object $x$ (the variable with the highest
@@ -1585,8 +1683,18 @@ $x$ has no variable associated to it.
 @eprog\noindent can be used to test whether a variable is attached to $x$.
 
 If $x$ is omitted, returns the list of user variables known to the
-interpreter, by order of decreasing priority. (Highest priority is $x$,
-which always come first.)
+interpreter, by order of decreasing priority. (Highest priority is initially
+$x$, which come first until \tet{varhigher} is used.) If \kbd{varhigher}
+or \kbd{varlower} are used, it is quite possible to end up with different
+variables (with different priorities) printed in the same way: they
+will then appear multiple times in the output:
+\bprog
+? varhigher("y");
+? varlower("y");
+? variable()
+%4 = [y, x, y]
+ at eprog\noindent Using \kbd{v = variable()} then \kbd{v[1]}, \kbd{v[2]},
+etc.~allows to recover and use existing variables.
 
 The library syntax is \fun{GEN}{gpolvar}{GEN x = NULL}.
 However, in library mode, this function should not be used for $x$
@@ -1596,6 +1704,113 @@ $x$ a $p$-adic (type \typ{PADIC}), $p$ is $gel(x,2)$; otherwise, use
 it exists, \kbd{NO\_VARIABLE} otherwise, which satisfies the property
 $\kbd{varncmp}(\kbd{NO\_VARIABLE}, v) > 0$ for all valid variable number
 $v$, i.e. it has lower priority than any variable.
+
+\subsec{variables$(\{x\})$}\kbdsidx{variables}\label{se:variables}
+Returns the list of all variables occuring in object $x$ (all user
+variables known to the interpreter if $x$ is omitted), sorted by
+decreasing priority.
+\bprog
+? variables([x^2 + y*z + O(t), a+x])
+%1 = [x, y, z, t, a]
+ at eprog\noindent The construction
+\bprog
+   if (!variables(x),...)
+ at eprog\noindent can be used to test whether a variable is attached to $x$.
+
+If \kbd{varhigher} or \kbd{varlower} are used, it is quite possible to end up
+with different variables (with different priorities) printed in the same
+way: they will then appear multiple times in the output:
+\bprog
+? y1 = varhigher("y");
+? y2 = varlower("y");
+? variables(y*y1*y2)
+%4 = [y, y, y]
+ at eprog
+
+The library syntax is \fun{GEN}{variables_vec}{GEN x = NULL}.
+
+Also available is \fun{GEN}{variables_vecsmall}{GEN x} which returns
+the (sorted) variable numbers instead of the associated monomials of degree 1.
+
+\subsec{varlower$(\var{name},\{v\})$}\kbdsidx{varlower}\label{se:varlower}
+Return a variable \emph{name} whose priority is lower
+than the priority of $v$ (of all existing variables if $v$ is omitted).
+This is a counterpart to \tet{varhigher}.
+
+New GP variables directly created by the interpreter always
+have lower priority than existing GP variables, but it is not easy
+to check whether an identifier is currently unused, so that the
+corresponding variable has the expected priority when it's created!
+Thus, depending on the session history, the same command may fail or succeed:
+\bprog
+? t; z;  \\ now t > z
+? rnfequation(t^2+1,z^2-t)
+ ***   at top-level: rnfequation(t^2+1,z^
+ ***                 ^--------------------
+ *** rnfequation: incorrect priority in rnfequation: variable t >= t
+ at eprog\noindent Restart and retry:
+\bprog
+? z; t;  \\ now z > t
+? rnfequation(t^2+1,z^2-t)
+%2 = z^4 + 1
+ at eprog\noindent It is quite annoying for package authors, when trying to
+define a base ring, to notice that the package may fail for some users
+depending on their session history. The safe way to do this is as follows:
+\bprog
+? z; t;  \\ In new session: now z > t
+...
+? t = varlower("t", 'z);
+? rnfequation(t^2+1,z^2-2)
+%2 = z^4 - 2*z^2 + 9
+? variable()
+%3 = [x, y, z, t]
+ at eprog
+\bprog
+? t; z;  \\ In new session: now t > z
+...
+? t = varlower("t", 'z); \\ create a new variable, still printed "t"
+? rnfequation(t^2+1,z^2-2)
+%2 = z^4 - 2*z^2 + 9
+? variable()
+%3 = [x, y, t, z, t]
+ at eprog\noindent Now both constructions succeed. Note that in the
+first case, \kbd{varlower} is essentially a no-op, the existing variable $t$
+has correct priority. While in the second case, two different variables are
+displayed as \kbd{t}, one with higher priority than $z$ (created in the first
+ line) and another one with lower priority (created by \kbd{varlower}).
+
+\misctitle{Caution 1}
+The \emph{name} is an arbitrary character string, only used for display
+purposes and need not be related to the GP variable holding the result, nor
+to be a valid variable name. In particular the \emph{name} can
+not be used to retrieve the variable, it is not even present in the parser's
+hash tables.
+\bprog
+? x = varlower("#");
+? x^2
+%2 = #^2
+ at eprog
+\misctitle{Caution 2} There are a limited number of variables and if no
+existing variable with the given display name has the requested
+priority, the call to \kbd{varlower} uses up one such slot. Do not create
+new variables in this way unless it's absolutely necessary,
+reuse existing names instead and choose sensible priority requirements:
+if you only need a variable with higher priority than $x$, state so
+rather than creating a new variable with highest priority.
+\bprog
+\\ quickly use up all variables
+? n = 0; while(1,varlower("x"); n++)
+ ***   at top-level: n=0;while(1,varlower("x");n++)
+ ***                             ^-------------------
+ *** varlower: no more variables available.
+ ***   Break loop: type 'break' to go back to GP prompt
+break> n
+65510
+\\ infinite loop: here we reuse the same 'tmp'
+? n = 0; while(1,varlower("tmp", x); n++)
+ at eprog
+
+The library syntax is \fun{GEN}{varlower}{const char *name, long v = -1}, where \kbd{v} is a variable number.
 %SECTION: conversions
 
 \section{Transcendental functions}\label{se:trans}
@@ -3089,8 +3304,16 @@ to display $g$, else the variable $x$ is used.
  ***   at top-level: ffgen(6)
  ***                 ^--------
  *** ffgen: not a prime number in ffgen: 6.
- at eprog\noindent Alternative syntax: instead of a prime power $q$, one may
-input directly the polynomial $P$ (monic, irreducible, with \typ{INTMOD}
+ at eprog\noindent Alternative syntax: instead of a prime power $q=p^f$, one may
+input the pair $[p,f]$:
+\bprog
+? g = ffgen([2,4], 't);
+? g.p
+%2 = 2
+? g.mod
+%3 = t^4 + t^3 + t^2 + t + 1
+ at eprog\noindent Finally, one may input
+directly the polynomial $P$ (monic, irreducible, with \typ{INTMOD}
 coefficients), and the function returns the generator $g = X \pmod{P(X)}$,
 inferring $p$ from the coefficients of $P$. If \kbd{v} is given, the
 variable name is used to display $g$, else the variable of the polynomial
@@ -3349,7 +3572,7 @@ $n$ to a $k$-th root of $x$.
 \noindent For a \typ{FFELT} \kbd{x}, instead of omitting \kbd{k} (which is
 not allowed for this type), it may be natural to set
 \bprog
-k = (x.p ^ poldegree(x.pol) - 1) / fforder(x)
+k = (x.p ^ x.f - 1) / fforder(x)
 @eprog
 
 The library syntax is \fun{long}{ispower}{GEN x, GEN k = NULL, GEN *n = NULL}.
@@ -3358,8 +3581,8 @@ Also available is
 
 \subsec{ispowerful$(x)$}\kbdsidx{ispowerful}\label{se:ispowerful}
 True (1) if $x$ is a powerful integer, false (0) if not;
-an integer is powerful if and only if its valuation at all primes is
-greater than 1.
+an integer is powerful if and only if its valuation at all primes dividing
+$x$ is greater than 1.
 \bprog
 ? ispowerful(50)
 %1 = 0
@@ -3441,13 +3664,27 @@ such that $P^2 - 4$ is not a square mod $x$).
 There are no known composite numbers passing this test, although it is
 expected that infinitely many such numbers exist. In particular, all
 composites $\leq 2^{64}$ are correctly detected (checked using
-\kbd{http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html}).
+\url{http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html}).
 
 If $\fl > 0$, checks whether $x$ is a strong Miller-Rabin pseudo prime  for
 $\fl$ randomly chosen bases (with end-matching to catch square roots of $-1$).
 
 The library syntax is \fun{GEN}{gispseudoprime}{GEN x, long flag}.
 
+\subsec{ispseudoprimepower$(x,\{\&n\})$}\kbdsidx{ispseudoprimepower}\label{se:ispseudoprimepower}
+If $x = p^k$ is a pseudo-prime power ($p$ pseudo-prime as per
+\tet{ispseudoprime}, $k > 0$), return $k$, else
+return 0. If a second argument $\&n$ is given and $x$ is indeed
+the $k$-th power of a prime $p$, sets $n$ to $p$.
+
+More precisely, $k$ is always the largest integer such that $x = n^k$ for
+some integer $n$ and, when $n \leq  2^{64}$ the function returns $k > 0$ if and
+only if $n$ is indeed prime. When $n > 2^{64}$ is larger than the threshold,
+the function may return $1$ even though $n$ is composite: it only passed
+an \kbd{ispseudoprime(n)} test.
+
+The library syntax is \fun{long}{ispseudoprimepower}{GEN x, GEN *n = NULL}.
+
 \subsec{issquare$(x,\{\&n\})$}\kbdsidx{issquare}\label{se:issquare}
 True (1) if $x$ is a square, false (0)
 if not. What ``being a square'' means depends on the type of $x$: all
@@ -3524,8 +3761,9 @@ The library syntax is \fun{long}{kronecker}{GEN x, GEN y}.
 
 \subsec{lcm$(x,\{y\})$}\kbdsidx{lcm}\label{se:lcm}
 Least common multiple of $x$ and $y$, i.e.~such
-that $\lcm(x,y)*\gcd(x,y) = \text{abs}(x*y)$. If $y$ is omitted and $x$
+that $\lcm(x,y)*\gcd(x,y) = x*y$, up to units. If $y$ is omitted and $x$
 is a vector, returns the $\text{lcm}$ of all components of $x$.
+For integer arguments, return the non-negative \text{lcm}.
 
 When $x$ and $y$ are both given and one of them is a vector/matrix type,
 the LCM is again taken recursively on each component, but in a different way.
@@ -3544,11 +3782,11 @@ the \kbd{v[i]} is a vector/matrix). The computation uses a divide-conquer tree
 and should be much more efficient, especially when using the GMP
 multiprecision kernel (and more subquadratic algorithms become available):
 \bprog
-? v = vector(10^4, i, random);
+? v = vector(10^5, i, random);
 ? lcm(v);
-time = 323 ms.
+time = 546 ms.
 ? l = v[1]; for (i = 1, #v, l = lcm(l, v[i]))
-time = 833 ms.
+time = 4,561 ms.
 @eprog
 
 The library syntax is \fun{GEN}{glcm0}{GEN x, GEN y = NULL}.
@@ -3746,23 +3984,27 @@ allowed, in which case the primes in $[a,b]$ are returned
 The library syntax is \fun{GEN}{primes0}{GEN n}.
 
 \subsec{qfbclassno$(D,\{\fl=0\})$}\kbdsidx{qfbclassno}\label{se:qfbclassno}
-Ordinary class number of the quadratic
-order of discriminant $D$. In the present version \vers, a $O(D^{1/2})$
-algorithm is used for $D > 0$ (using Euler product and the functional
-equation) so $D$ should not be too large, say $D < 10^8$, for the time to be
-reasonable. On the other hand, for $D < 0$ one can reasonably compute
-\kbd{qfbclassno($D$)} for $|D|<10^{25}$, since the routine uses
-\idx{Shanks}'s method which is in $O(|D|^{1/4})$. For larger values of $|D|$,
-see \kbd{quadclassunit}.
-
-If $\fl=1$, compute the class number using \idx{Euler product}s and the
-functional equation. However, it is in $O(|D|^{1/2})$.
-
-\misctitle{Important warning} For $D < 0$, this function may give incorrect
-results when the class group has many cyclic factors,
-because implementing \idx{Shanks}'s method in full generality slows it down
-immensely. It is therefore strongly recommended to double-check results using
-either the version with $\fl = 1$ or the function \kbd{quadclassunit}.
+Ordinary class number of the quadratic order of discriminant $D$, for
+``small'' values of $D$.
+
+\item if  $D > 0$ or $\fl = 1$, use a $O(|D|^{1/2})$
+algorithm (compute $L(1,\chi_D)$ with the approximate functional equation).
+This is slower than \tet{quadclassunit} as soon as $|D| \approx 10^2$ or
+so and is not meant to be used for large $D$.
+
+\item if $D < 0$ and $\fl = 0$ (or omitted), use a $O(|D|^{1/4})$
+algorithm (Shanks's baby-step/giant-step method). It should
+be faster than \tet{quadclassunit} for small values of $D$, say
+$|D| < 10^{18}$.
+
+\misctitle{Important warning} In the latter case, this function only
+implements part of \idx{Shanks}'s method (which allows to speed it up
+considerably). It gives unconditionnally correct results for $|D| < 2\cdot
+10^{10}$, but may give incorrect results for larger values if the class
+group has many cyclic factors. We thus recommend to double-check results
+using the function \kbd{quadclassunit}, which is about 2 to 3 times slower in
+the above range, assuming GRH. We currently have no counter-examples but
+they should exist: we'd appreciate a bug report if you find one.
 
 \misctitle{Warning} Contrary to what its name implies, this routine does not
 compute the number of classes of binary primitive forms of discriminant $D$,
@@ -3890,6 +4132,16 @@ Also available are
 
 \fun{GEN}{rhorealnod}{GEN x, GEN isd} (= \kbd{qfbred(x,3,,isd)}).
 
+\subsec{qfbredsl2$(x,\{\var{data}\})$}\kbdsidx{qfbredsl2}\label{se:qfbredsl2}
+Reduction of the (real or imaginary) binary quadratic form $x$, return
+$[y,g]$ where $y$ is reduced and $g$ in $\text{SL}(2,\Z)$ is such that
+ $g \cdot x = y$; \var{data}, if
+present, must be equal to $[D, \kbd{sqrtint}(D)]$, where $D > 0$ is the
+discriminant of $x$. In case $x$ is \typ{QFR}, the distance component is
+unaffected.
+
+The library syntax is \fun{GEN}{qfbredsl2}{GEN x, GEN data = NULL}.
+
 \subsec{qfbsolve$(Q,p)$}\kbdsidx{qfbsolve}\label{se:qfbsolve}
 Solve the equation $Q(x,y)=p$ over the integers,
 where $Q$ is a binary quadratic form and $p$ a prime number.
@@ -4091,7 +4343,7 @@ vecstirling(n) = Vec( factorback(vector(n-1,i,1-i*'x)) )
 /* list of S(n,k), k = 1..n */
 vecstirling2(n) =
 { my(Q = x^(n-1), t);
-  vector(n, i, t = divrem(Q, x-i); Q=t[1]; t[2]);
+  vector(n, i, t = divrem(Q, x-i); Q=t[1]; simplify(t[2]));
 }
 @eprog
 
@@ -4108,15 +4360,20 @@ Returns the \idx{Dedekind sum} associated to the integers $h$ and $k$,
 
 The library syntax is \fun{GEN}{sumdedekind}{GEN h, GEN k}.
 
-\subsec{sumdigits$(n)$}\kbdsidx{sumdigits}\label{se:sumdigits}
-Sum of (decimal) digits in the integer $n$.
+\subsec{sumdigits$(n,\{B={10}\})$}\kbdsidx{sumdigits}\label{se:sumdigits}
+Sum of digits in the integer $n$, when written in base $B > 1$.
 \bprog
 ? sumdigits(123456789)
 %1 = 45
- at eprog\noindent Other bases that 10 are not supported. Note that the sum of
-bits in $n$ is returned by \tet{hammingweight}.
+? sumdigits(123456789, 2)
+%1 = 16
+ at eprog\noindent Note that the sum of bits in $n$ is also returned by
+\tet{hammingweight}. This function is much faster than
+\kbd{vecsum(digits(n,B))} when $B$ is $10$ or a power of $2$, and only
+slightly faster in other cases.
 
-The library syntax is \fun{GEN}{sumdigits}{GEN n}.
+The library syntax is \fun{GEN}{sumdigits0}{GEN n, GEN B = NULL}.
+Also available is \fun{GEN}{sumdigits}{GEN n}, for $B = 10$.
 
 \subsec{zncoppersmith$(P, N, X, \{B=N\})$}\kbdsidx{zncoppersmith}\label{se:zncoppersmith}
 $N$ being an integer and $P\in \Z[X]$, finds all integers $x$ with
@@ -4447,18 +4704,21 @@ memory and require at least 2MB stack to avoid stack overflows.
 \item \tet{gen} returns the generators of $E(\Q)$, if known (from John
   Cremona's database)
 
+\subsubsec{Curves over number fields}
+
+\item \tet{nf} returns the number field over which $E$ is defined.
+
 
-\subsec{ellL1$(e, r)$}\kbdsidx{ellL1}\label{se:ellL1}
+
+\subsec{ellL1$(e, \{r = 0\})$}\kbdsidx{ellL1}\label{se:ellL1}
 Returns the value at $s=1$ of the derivative of order $r$ of the
-$L$-function of the elliptic curve $e$ assuming that $r$ is at most the order
-of vanishing of the $L$-function at $s=1$. (The result is wrong if $r$ is
-strictly larger than the order of vanishing at 1.)
+$L$-function of the elliptic curve $e$.
 \bprog
 ? e = ellinit("11a1"); \\ order of vanishing is 0
-? ellL1(e, 0)
+? ellL1(e)
 %2 = 0.2538418608559106843377589233
 ? e = ellinit("389a1");  \\ order of vanishing is 2
-? ellL1(e, 0)
+? ellL1(e)
 %4 = -5.384067311837218089235032414 E-29
 ? ellL1(e, 1)
 %5 = 0
@@ -4472,17 +4732,17 @@ Swinnerton-Dyer conjecture:
 \bprog
 ? \p18
   realprecision = 18 significant digits
-? ellanalyticrank(ellinit([0, 0, 1, -7, 6]))
-time = 32 ms.
+? e = ellinit("5077a1"); ellanalyticrank(e)
+time = 8 ms.
 %1 = [3, 10.3910994007158041]
 ? \p200
   realprecision = 202 significant digits (200 digits displayed)
 ? ellL1(e, 3)
-time = 23,113 ms.
+time = 104 ms.
 %3 = 10.3910994007158041387518505103609170697263563756570092797 at com$[\dots]$
 @eprog
 
-The library syntax is \fun{GEN}{ellL1}{GEN e, long r, long prec}.
+The library syntax is \fun{GEN}{ellL1}{GEN e, long r , long prec}.
 
 \subsec{elladd$(E,\var{z1},\var{z2})$}\kbdsidx{elladd}\label{se:elladd}
 Sum of the points $z1$ and $z2$ on the
@@ -4599,21 +4859,16 @@ will be more efficient.
 quadratic order we use a fast explicit formula (involving essentially Kronecker
 symbols and Cornacchia's algorithm), in $O(\log q)^2$.
 Otherwise, we use Shanks-Mestre's baby-step/giant-step method, which runs in
-time $q(p^{1/4})$ using $O(q^{1/4})$ storage, hence becomes unreasonable when
-$q$ has about 30~digits. If the \tet{seadata} package is installed, the
-\tet{SEA} algorithm becomes available, heuristically in $\tilde{O}(\log
-q)^4$, and primes of the order of 200~digits become feasible. In very small
-characteristic (2,3,5,7 or $13$), we use Harley's algorithm.
+time $\tilde{O}(q^{1/4})$ using $\tilde{O}(q^{1/4})$ storage, hence becomes
+unreasonable when $q$ has about 30~digits. If the \tet{seadata} package is
+installed, the \tet{SEA} algorithm becomes available, heuristically in
+$\tilde{O}(\log q)^4$, and primes of the order of 200~digits become feasible.
+In very small characteristic (2,3,5,7 or $13$), we use Harley's algorithm.
 
 The library syntax is \fun{GEN}{ellap}{GEN E, GEN p = NULL}.
 
 \subsec{ellbil$(E,\var{z1},\var{z2})$}\kbdsidx{ellbil}\label{se:ellbil}
-If $z1$ and $z2$ are points on the elliptic
-curve $E$ this function
-computes the value of the canonical bilinear form on $z1$, $z2$:
-$$ ( h(E,z1\kbd{+}z2) - h(E,z1) - h(E,z2) ) / 2 $$
-where \kbd{+} denotes of course addition on $E$. In addition, $z1$ or $z2$
-(but not both) can be vectors or matrices.
+Deprecated alias for \kbd{ellheight(E,P,Q)}.
 
 The library syntax is \fun{GEN}{bilhell}{GEN E, GEN z1, GEN z2, long prec}.
 
@@ -4625,7 +4880,7 @@ This function computes the order of the group $E(\F_q)$ (as would be
 computed by \tet{ellgroup}).
 
 If the curve is defined over $\Q$, $p$ must be explicitly given and the
-function computes the cardinal of the reduction over $\F_p$; the
+function computes the cardinality of the reduction over $\F_p$; the
 equation need not be minimal at $p$, but a minimal model will be more
 efficient. The reduction is allowed to be singular, and we return the order
 of the group of non-singular points in this case.
@@ -4753,6 +5008,89 @@ lattice basis \kbd{$E$.omega} (namely, \kbd{$E$.eta}) are returned.
 
 The library syntax is \fun{GEN}{elleta}{GEN w, long prec}.
 
+\subsec{ellformaldifferential$(E, \{n=\var{seriesprecision}\}, \{t = 'x\})$}\kbdsidx{ellformaldifferential}\label{se:ellformaldifferential}
+Let $\omega := dx / (2y+a_1x+a_3$ be the invariant differential form
+associated to the model $E$ of some elliptic curve (\kbd{ellinit} form),
+and $\eta := x(t)\omega$. Return $n$ terms (\tet{seriesprecision} by default)
+of $f(t),g(t)$ two power series in the formal parameter $t=-x/y$ such that
+$\omega = f(t) dt$, $\eta = g(t) dt$:
+ $$f(t) = 1+a_1 t + (a_1^2 + a_2) t^2 + \dots,\quad
+   g(t) = t^{-2} +\dots $$
+ \bprog
+ ? E = ellinit([-1,1/4]); [f,g] = ellformaldifferential(E,7,'t);
+ ? f
+ %2 = 1 - 2*t^4 + 3/4*t^6 + O(t^7)
+ ? g
+ %3 = t^-2 - t^2 + 1/2*t^4 + O(t^5)
+ at eprog
+
+The library syntax is \fun{GEN}{ellformaldifferential}{GEN E, long precdl, long n = -1}, where \kbd{n} is a variable number.
+
+\subsec{ellformalexp$(E, \{n = \var{seriesprecision}\}, \{z = 'x\})$}\kbdsidx{ellformalexp}\label{se:ellformalexp}
+The elliptic formal exponential \kbd{Exp} attached to $E$ is the
+isomorphism from the formal additive law to the formal group of $E$. It is
+normalized so as to be the inverse of the elliptic logarithm (see
+\tet{ellformallog}): $\kbd{Exp} \circ L = \Id$. Return $n$ terms of this
+power series:
+\bprog
+? E=ellinit([-1,1/4]); Exp = ellformalexp(E,10,'z)
+%1 = z + 2/5*z^5 - 3/28*z^7 + 2/15*z^9 + O(z^11)
+? L = ellformallog(E,10,'t);
+? subst(Exp,z,L)
+%3 = t + O(t^11)
+ at eprog
+
+The library syntax is \fun{GEN}{ellformalexp}{GEN E, long precdl, long n  = -1}, where \kbd{n } is a variable number.
+
+\subsec{ellformallog$(E, \{n = \var{seriesprecision}\}, \{v = 't\})$}\kbdsidx{ellformallog}\label{se:ellformallog}
+The formal elliptic logarithm is a series $L$ in $t K[[t]]$
+such that $d L = \omega = dx / (2y + a_1x + a_3$, the canonical invariant
+differential attached to the model $E$. It gives an isomorphism
+from the formal group of $E$ to the additive formal group.
+\bprog
+? E = ellinit([-1,1/4]); L = ellformallog(E, 9, 't)
+%1 = t - 2/5*t^5 + 3/28*t^7 + 2/3*t^9 + O(t^10)
+? [f,g] = ellformaldifferential(E,8,'t);
+? L' - f
+%3 = O(t^8)
+ at eprog
+
+The library syntax is \fun{GEN}{ellformallog}{GEN E, long precdl, long n  = -1}, where \kbd{n } is a variable number.
+
+\subsec{ellformalpoint$(E, \{n = \var{seriesprecision}\}, \{v = 'x\})$}\kbdsidx{ellformalpoint}\label{se:ellformalpoint}
+If $E$ is an elliptic curve, return the coordinates $x(t), y(t)$ in the
+formal group of the elliptic curve $E$ in the formal parameter $t = -x/y$
+at $\infty$:
+$$ x = t^{-2} -a_1 t^{-1} - a_2 - a_3 t + \dots $$
+$$ y = - t^{-3} -a_1 t^{-2} - a_2t^{-1} -a_3 + \dots $$
+Return $n$ terms (\tet{seriesprecision} by default) of these two power
+series, whose coefficients are in $\Z[a_1,a_2,a_3,a_4,a_6]$.
+\bprog
+? E = ellinit([0,0,1,-1,0]); [x,y] = ellformalpoint(E,8);
+? x
+%2 = x^-2 - x + x^2 - x^4 + 2*x^5 + O(x^6)
+? y
+%3 = -x^-3 + 1 - x + x^3 - 2*x^4 + O(x^5)
+? E = ellinit([0,1/2]); ellformalpoint(E,7)
+%4 = [x^-2 - 1/2*x^4 + O(x^5), -x^-3 + 1/2*x^3 + O(x^4)]
+ at eprog
+
+The library syntax is \fun{GEN}{ellformalpoint}{GEN E, long precdl, long n  = -1}, where \kbd{n } is a variable number.
+
+\subsec{ellformalw$(E, \{n = \var{seriesprecision}\}, \{t = 'x\})$}\kbdsidx{ellformalw}\label{se:ellformalw}
+Return the formal power series $w$ associated to the elliptic curve $E$,
+in the variable $t$:
+$$ w(t) = t^3 + a_1 t^4 + (a_2 + a_1^2) t^5 + \cdots + O(t^{n+3}),$$
+which is the formal expansion of $-1/y$ in the formal parameter $t := -x/y$
+at $\infty$ (take $n = \tet{seriesprecision}$ if $n$ is omitted). The
+coefficients of $w$ belong to $\Z[a_1,a_2,a_3,a_4,a_6]$.
+\bprog
+? E=ellinit([3,2,-4,-2,5]); ellformalw(E, 5, 't)
+%1 = t^3 + 3*t^4 + 11*t^5 + 35*t^6 + 101*t^7 + O(t^8)
+ at eprog
+
+The library syntax is \fun{GEN}{ellformalw}{GEN E, long precdl, long n  = -1}, where \kbd{n } is a variable number.
+
 \subsec{ellfromj$(j)$}\kbdsidx{ellfromj}\label{se:ellfromj}
 Returns the coefficients $[a_1,a_2,a_3,a_4,a_6]$ of a fixed elliptic curve
 with $j$-invariant $j$.
@@ -4877,22 +5215,19 @@ height of the point (thus, it is preferable to apply it to strong Weil curves).
 
 The library syntax is \fun{GEN}{ellheegner}{GEN E}.
 
-\subsec{ellheight$(E,x,\{\fl=2\})$}\kbdsidx{ellheight}\label{se:ellheight}
-Global N\'eron-Tate height of the point $z$ on the elliptic curve
-$E$ (defined over $\Q$), using the normalization in Cremona's
-\emph{Algorithms for modular elliptic curves}. $E$
-must be an \kbd{ell} as output by \kbd{ellinit}; it needs not be given by a
-minimal model although the computation will be faster if it is. \fl\ selects
-the algorithm used to compute the Archimedean local height. If $\fl=0$,
-we use sigma and theta-functions and Silverman's trick (Computing
-heights on elliptic curves, \emph{Math.~Comp.} {\bf 51}; note that
-our height is twice Silverman's height). If
-$\fl=1$, use Tate's $4^n$ algorithm. If $\fl=2$, use Mestre's AGM algorithm.
-The latter converges quadratically and is much faster than the other two.
-
-The library syntax is \fun{GEN}{ellheight0}{GEN E, GEN x, long flag, long prec}.
-Also available is \fun{GEN}{ghell}{GEN E, GEN x, long prec}
-($\fl=2$).
+\subsec{ellheight$(E,P,\{Q\})$}\kbdsidx{ellheight}\label{se:ellheight}
+Global N\'eron-Tate height $h(P)$ of the point $P$ on the elliptic curve
+$E/\Q$, using the normalization in Cremona's \emph{Algorithms for modular
+elliptic curves}. $E$ must be an \kbd{ell} as output by \kbd{ellinit}; it
+needs not be given by a minimal model although the computation will be faster
+if it is.
+
+If the argument $Q$ is present, computes the value of the bilinear
+form $(h(P+Q)-h(P-Q)) / 4$.
+
+The library syntax is \fun{GEN}{ellheight0}{GEN E, GEN P, GEN Q = NULL, long prec}.
+Also available is \fun{GEN}{ellheight}{GEN E, GEN P, long prec}
+($Q$ omitted).
 
 \subsec{ellheightmatrix$(E,x)$}\kbdsidx{ellheightmatrix}\label{se:ellheightmatrix}
 $x$ being a vector of points, this
@@ -4905,7 +5240,7 @@ the regulator of $E$. Note our height normalization follows Cremona's
 \emph{Algorithms for modular elliptic curves}: this matrix should be divided
 by 2 to be in accordance with, e.g., Silverman's normalizations.
 
-The library syntax is \fun{GEN}{mathell}{GEN E, GEN x, long prec}.
+The library syntax is \fun{GEN}{ellheightmatrix}{GEN E, GEN x, long prec}.
 
 \subsec{ellidentify$(E)$}\kbdsidx{ellidentify}\label{se:ellidentify}
 Look up the elliptic curve $E$, defined by an arbitrary model over $\Q$,
@@ -4958,6 +5293,12 @@ point quantities are by default computed to a relative accuracy of
 \kbd{precision}$(x)$. If no such argument is given, the value of
 \kbd{realprecision} at the time \kbd{ellinit} is called will be used.
 
+\item a number field $K$, given by a \var{nf} or \var{bnf} structure.
+
+\item a prime ideal $\goth{p}$, given by a \var{prid} structure; valid if
+$x$ is a curve defined over a number field $K$ and the equation is integral
+and minimal at $\goth{p}$.
+
 This argument $D$ is indicative: the curve coefficients are checked for
 compatibility, possibly changing $D$; for instance if $D = 1$ and
 an \typ{INTMOD} is found. If inconsistencies are detected, an error is
@@ -5015,6 +5356,79 @@ beginning of this section.
 
 The library syntax is \fun{GEN}{ellinit}{GEN x, GEN D = NULL, long prec}.
 
+\subsec{ellisdivisible$(E,P,n,\{\&Q\}))$}\kbdsidx{ellisdivisible}\label{se:ellisdivisible}
+Given $E/K$ a number field and $P$ in $E(K)$
+return $1$ if $P = [n]R$ for some $R$ in $E(K)$ and set $Q$ to one such $R$;
+and return $0$ otherwise. The integer $n \geq 0$ may be given as
+\kbd{ellxn(E,n)}, if many points need to be tested.
+\bprog
+? K = nfinit(polcyclo(11,t));
+? E = ellinit([0,-1,1,0,0], K);
+? P = [0,0];
+? ellorder(E,P)
+%4 = 5
+? ellisdivisible(E,P,5, &Q)
+%5 = 1
+? lift(Q)
+%6 = [-t^7-t^6-t^5-t^4+1, -t^9-2*t^8-2*t^7-3*t^6-3*t^5-2*t^4-2*t^3-t^2-1]
+? ellorder(E, Q)
+%7 = 25
+ at eprog\noindent The complexity of the underlying algorithm is at least in
+$O(n^4)$, so it is advisable to first factor $n$, then use a chain of checks
+associated to the prime divisors of n: the function will do it itself unless
+$n$ is given in \kbd{ellxn} form.
+
+The library syntax is \fun{long}{ellisdivisible}{GEN E, GEN P, GEN n, GEN *Q) = NULL}.
+
+\subsec{ellisogeny$(E, G, \{\var{only\_image} = 0\}, \{x = 'x\}, \{y = 'y\})$}\kbdsidx{ellisogeny}\label{se:ellisogeny}
+Given an elliptic curve $E$, a finite subgroup $G$ of $E$ is given either
+as a generating point $P$ (for a cyclic $G$) or as a polynomial whose roots
+vanish on the $x$-coordinates of the non-zero elements of $G$ (general case
+and more efficient if available). This function returns the
+$[a_1,a_2,a_3,a_4,a_6]$ invariants of the quotient elliptic curve $E/G$ and
+(if \var{only\_image} is zero (the default)) a vector of rational
+functions $[f, g, h]$ such that the isogeny $E \to E/G$ is given by $(x,y)
+\mapsto (f(x)/h(x)^2, g(x,y)/h(x)^3)$.
+\bprog
+? E = ellinit([0,1]);
+? elltors(e)
+%2 = [6, [6], [[2, 3]]]
+? ellisogeny(E, [2,3], 1)  \\ Weierstrass model for E/<P>
+%3 = [0, 0, 0, -135, -594]
+? ellisogeny(E,[-1,0])
+%4 = [[0,0,0,-15,22], [x^3+2*x^2+4*x+3, y*x^3+3*y*x^2-2*y, x+1]]
+ at eprog
+
+The library syntax is \fun{GEN}{ellisogeny}{GEN E, GEN G, long only_image , long x  = -1, long y  = -1}, where \kbd{x }, \kbd{y } are variable numbers.
+
+\subsec{ellisogenyapply$(f, g)$}\kbdsidx{ellisogenyapply}\label{se:ellisogenyapply}
+Given an isogeny of elliptic curves $f:E'\to E$ (being the result of a call
+to \tet{ellisogeny}), apply $f$ to $x$:
+
+\item if $x$ is a point $P$ in the domain of $f$, return the image $f(P)$;
+
+\item if $x$ is a compatible isogeny $g:E''\to E'$, return the composite
+isogeny $f \circ g:  E''\to E$.
+
+\bprog
+? one = ffgen(101, 't)^0;
+? E = ellinit([6, 53, 85, 32, 34] * one);
+? P = [84, 71] * one;
+? ellorder(E, P)
+%4 = 5
+? [F, f] = ellisogeny(E, P);  \\ f: E->F = E/<P>
+? ellisogenyapply(f, P)
+%6 = [0]
+? F = ellinit(F);
+? Q = [89, 44] * one;
+? ellorder(F, Q)
+%9 = 2;
+? [G, g] = ellisogeny(F, Q); \\  g: F->G = F/<Q>
+? gof = ellisogenyapply(g, f); \\ gof: E -> G
+ at eprog
+
+The library syntax is \fun{GEN}{ellisogenyapply}{GEN f, GEN g}.
+
 \subsec{ellisoncurve$(E,z)$}\kbdsidx{ellisoncurve}\label{se:ellisoncurve}
 Gives 1 (i.e.~true) if the point $z$ is on the elliptic curve $E$, 0
 otherwise. If $E$ or $z$ have imprecise coefficients, an attempt is made to
@@ -5026,6 +5440,25 @@ The library syntax is \fun{GEN}{ellisoncurve}{GEN E, GEN z}.
 Also available is \fun{int}{oncurve}{GEN E, GEN z} which does not
 accept vectors of points.
 
+\subsec{ellissupersingular$(E,\{p\})$}\kbdsidx{ellissupersingular}\label{se:ellissupersingular}
+Return 1 if the elliptic curve $E$ defined over Q or a finite field is supersingular
+at $p$, and $0$ otherwise.
+If the curve is defined over $\Q$, $p$ must be explicitly given and have good
+reduction at $p$.
+Alternatively, $E$ can be given byt its $j$-invariant in a finite field. In
+this case $p$ must be omitted.
+\bprog
+? g = ffprimroot(ffgen(7^5))
+%1 = x^3 + 2*x^2 + 3*x + 1
+? [g^n | n <- [1 .. 7^5 - 1], ellissupersingular(g^n)]
+%2 = [6]
+ at eprog
+
+The library syntax is \fun{GEN}{ellissupersingular}{GEN E, GEN p = NULL}.
+Also available is
+\fun{int}{elljissupersingular}{GEN j} where $j$ is a $j$-invariant of a curve
+over a finite field.
+
 \subsec{ellj$(x)$}\kbdsidx{ellj}\label{se:ellj}
 Elliptic $j$-invariant. $x$ must be a complex number
 with positive imaginary part, or convertible into a power series or a
@@ -5035,8 +5468,10 @@ The library syntax is \fun{GEN}{jell}{GEN x, long prec}.
 
 \subsec{elllocalred$(E,p)$}\kbdsidx{elllocalred}\label{se:elllocalred}
 Calculates the \idx{Kodaira} type of the local fiber of the elliptic curve
-$E$ at the prime $p$. $E$ must be an \var{ell} structure as output by
-\kbd{ellinit}, and is assumed to have all its coefficients $a_i$ in $\Z$.
+$E$ at $p$. $E$ must be an \var{ell} structure as output by
+\kbd{ellinit}, over $\Q$ ($p$ a rational prime) or a number field $K$ ($p$
+a maximal ideal given by a \var{prid} structure), and is assumed to have all
+its coefficients $a_i$ integral.
 The result is a 4-component vector $[f,kod,v,c]$. Here $f$ is the exponent of
 $p$ in the arithmetic conductor of $E$, and $kod$ is the Kodaira type which
 is coded as follows:
@@ -5049,6 +5484,9 @@ giving the coordinate changes done during the local reduction;
 $u = 1$ if and only if the given equation was already minimal at $p$.
 Finally, the last component $c$ is the local \idx{Tamagawa number} $c_p$.
 
+\misctitle{Caveat} If $E$ is not defined over $\Q$, the current
+implementation requires that $p$ be above a prime $\geq 5$.
+
 The library syntax is \fun{GEN}{elllocalred}{GEN E, GEN p}.
 
 \subsec{elllog$(E,P,G,\{o\})$}\kbdsidx{elllog}\label{se:elllog}
@@ -5193,25 +5631,45 @@ Opposite of the point $z$ on elliptic curve $E$.
 
 The library syntax is \fun{GEN}{ellneg}{GEN E, GEN z}.
 
+\subsec{ellnonsingularmultiple$(E,P)$}\kbdsidx{ellnonsingularmultiple}\label{se:ellnonsingularmultiple}
+Given an elliptic curve $E/\Q$ (more precisely, a model defined over $\Q$
+of a curve) and a rational point $P \in E(\Q)$, returns the pair $[R,n]$,
+where $n$ is the least positive integer such that $R := [n]P$ has good
+reduction at every prime. More precisely, its image in a minimal model is
+everywhere non-singular.
+\bprog
+? e = ellinit("57a1"); P = [2,-2];
+? ellnonsingularmultiple(e, P)
+%2 = [[1, -1], 2]
+? e = ellinit("396b2"); P = [35, -198];
+? [R,n] = ellnonsingularmultiple(e, P);
+? n
+%5 = 12
+ at eprog
+
+The library syntax is \fun{GEN}{ellnonsingularmultiple}{GEN E, GEN P}.
+
 \subsec{ellorder$(E,z,\{o\})$}\kbdsidx{ellorder}\label{se:ellorder}
 Gives the order of the point $z$ on the elliptic
-curve $E$, defined over $\Q$ or a finite field.
-If the curve is defined over $\Q$, return (the impossible value) zero if the
-point has infinite order.
+curve $E$, defined over a finite field or a number field.
+Return (the impossible value) zero if the point has infinite order.
 \bprog
 ? E = ellinit([-157^2,0]);  \\ the "157-is-congruent" curve
 ? P = [2,2]; ellorder(E, P)
 %2 = 2
 ? P = ellheegner(E); ellorder(E, P) \\ infinite order
 %3 = 0
+? K = nfinit(polcyclo(11,t)); E=ellinit("11a3", K); T = elltors(E);
+? ellorder(E, T.gen[1])
+%5 = 25
 ? E = ellinit(ellfromj(ffgen(5^10)));
 ? ellcard(E)
-%5 = 9762580
+%7 = 9762580
 ? P = random(E); ellorder(E, P)
-%6 = 4881290
+%8 = 4881290
 ? p = 2^160+7; E = ellinit([1,2], p);
 ? N = ellcard(E)
-%8 = 1461501637330902918203686560289225285992592471152
+%9 = 1461501637330902918203686560289225285992592471152
 ? o = [N, factor(N)];
 ? for(i=1,100, ellorder(E,random(E)))
 time = 260 ms.
@@ -5242,6 +5700,201 @@ $x$-coordinate.
 
 The library syntax is \fun{GEN}{ellordinate}{GEN E, GEN x, long prec}.
 
+\subsec{ellpadicL$(E, p, n, \{r = 0\}, \{D\}, \{\var{char}\})$}\kbdsidx{ellpadicL}\label{se:ellpadicL}
+The $p$-adic $L$ function is defined on the set of continuous characters
+ of $\text{Gal}(\Q(\mu_{p^{\infty}})/ \Q)$, identified to $\Z_p^*$
+ via the cyclotomic character $\chi_p$ with values in $\overline{Q_p}^*$.
+ Denote by $tau:\Z_p^*\to\Z_p^*$ the Teichm\"uller character.
+
+ When $E$ has good supersingular reduction, the $L$ function takes its
+ values in $\Q_p \otimes H^1_{dR}(E/\Q)$ and satisfies
+ $$(1-p^{-1} F)^{-2} L_p(E, \tau^0)= (L(E,1) / \Omega) \cdot \omega$$
+ where $F$ is the Frobenius, $L(E,1)$ is the value of the complex $L$
+ function at $1$, $\omega$ is the N\'eron differential
+ and $\Omega$ its associated period on $E(\R)$. Here, $\tau^0$ represents
+ the trivial character.
+
+ The derivative is taken at $s=1$ along $\langle\chi_p^s\rangle$.
+ In other words, the function $L_p$ is defined as
+ $\int_{\Z_p^*} d \mu$ for a certain $p$-adic distribution $\mu$ on
+ $\Z_p^*$, and we have
+  $$L_p^{(r)}(E, \tau^0) = \int_{\Z_p^*} \log_p^r(a) d\mu(a).$$
+ The function returns the components of $L_p{(r)}(E,\tau^0)$ in
+ the basis $(\omega, F(\omega))$.
+ \smallskip
+
+ When $E$ has ordinary good reduction, this method only defines
+ the projection of $L_p(E,\tau^0)$ on the $\alpha$-eigenspace,
+ where $\alpha$ is the unit eigenvalue for $F$. This is what the function
+ returns. This value satisfies
+ $$(1- \alpha^{-1})^{-2} L_{p,\alpha}(E,\tau^0)= L(E,1) / \Omega.$$
+
+ \bprog
+ ? cxL(e) = bestappr( ellL1(e,0) / e.omega[1] );
+
+ ? e = ellinit("17a1"); p=3; \\ supersingular
+ ? L = ellpadicL(e,p,4);
+ ? F = [0,-p;1,ellap(e,p)]; \\ Frobenius matrix in the basis (omega,F(omega)
+ ? (1-p^(-1)*F)^-2 * L~ / cxL(e)
+ %4 = [1 + O(3^4), O(3^4)]~
+
+ ? p=5; ap = ellap(e,p); \\ ordinary
+ ? L = ellpadicL(e,p,4);
+ ? al = padicappr(x^2 - ap*x + p, ap + O(p^7))[1];
+ ? (1-al^(-1))^(-2) * L / cxL(e)
+ %8 = 1 + O(5^4)
+
+ ? e = ellinit("116a1"); p=3; \\ supersingular
+ ? L = ellpadicL(e,p,4);
+ ? F = [0,-p; 1,ellap(e,p)];
+ ? (1-p^(-1)*F)^-2*L~ / cxL(e)
+ %12 = [1 + O(3^4), O(3^5)]~
+
+ ? e = ellinit("26b1"); p=3;
+ ? L = ellpadicL(e,p,4);
+ ? F = [0,-p;1,ellap(e,p)];
+ ? (1-p^(-1)*F)^-2*L~ / cxL(e)
+ %16 = [1 + O(3^4), O(3^5)]~
+ @eprog
+
+The library syntax is \fun{GEN}{ellpadicL}{GEN E, GEN p, long n, long r , GEN D = NULL, GEN char = NULL}.
+
+\subsec{ellpadicfrobenius$(E,p,n)$}\kbdsidx{ellpadicfrobenius}\label{se:ellpadicfrobenius}
+If $p>2$ is a prime and $E$ is a elliptic curve on $\Q$ with good
+reduction at $p$, return the matrix of the Frobenius endomorphism $\varphi$ on
+the crystalline module $D_p(E)= \Q_p \otimes H^1_{dR}(E/\Q)$ with respect to
+the basis of the given model $(\omega, \eta=x\*\omega)$, where
+$\omega = dx/(2\*y+a_1\*x+a_3)$ is the invariant differential.
+The characteristic polynomial of $\varphi$ is $x^2 - a_p\*x + p$.
+The matrix is computed to absolute $p$-adic precision $p^n$.
+
+\bprog
+? E = ellinit([1,-1,1,0,0]);
+? F = ellpadicfrobenius(E,5,3);
+? lift(F)
+%3 =
+[120 29]
+
+[ 55  5]
+? charpoly(F)
+%4 = x^2 + O(5^3)*x + (5 + O(5^3))
+? ellap(E, 5)
+%5 = 0
+ at eprog
+
+The library syntax is \fun{GEN}{ellpadicfrobenius}{GEN E, long p, long n}.
+
+\subsec{ellpadicheight$(E, p,n, P,\{Q\})$}\kbdsidx{ellpadicheight}\label{se:ellpadicheight}
+Cyclotomic $p$-adic height of the rational point $P$ on the elliptic curve
+$E$ (defined over $\Q$), given to $n$ $p$-adic digits.
+If the argument $Q$ is present, computes the value of the bilinear
+form $(h(P+Q)-h(P-Q)) / 4$.
+
+Let $D_{dR}(E) := H^1_{dR}(E) \otimes_\Q \Q_p$ be the $\Q_p$ vector space
+spanned by $\omega$
+(invariant differential $dx/(2y+a_1x+a3)$ related to the given model) and
+$\eta = x \omega$. Then the cyclotomic $p$-adic height associates to
+$P\in E(\Q)$ an element $f \omega + g\eta$ in $D_{dR}$.
+This routine returns the vector $[f, g]$ to $n$ $p$-adic digits.
+
+If $P\in E(\Q)$ is in the kernel of reduction mod $p$ and if its reduction
+at all finite places is non singular, then $g = -(\log_E P)^2$, where
+$\log_E$ is the logarithm for the formal group of $E$ at $p$.
+
+If furthermore the model is of the form $Y^2 = X^3 + a X + b$ and $P = (x,y)$,
+then
+  $$ f = \log_p(\kbd{denominator}(x)) - 2 \log_p(\sigma(P))$$
+where $\sigma(P)$ is given by \kbd{ellsigma}$(E,P)$.
+
+Recall (\emph{Advanced topics in the arithmetic of elliptic
+curves}, Theorem~3.2) that the local height function over the complex numbers
+is of the form
+  $$ \lambda(z) = -\log (|\kbd{E.disc}|) / 6 + \Re(z \eta(z)) - 2 \log(
+  \sigma(z). $$
+(N.B. our normalization for local and global heights is twice that of
+Silverman's).
+\bprog
+ ? E = ellinit([1,-1,1,0,0]); P = [0,0];
+ ? ellpadicheight(E,5,4, P)
+ %2 = [3*5 + 5^2 + 2*5^3 + O(5^4), 5^2 + 4*5^4 + O(5^6)]
+ ? E = ellinit("11a1"); P = [5,5]; \\ torsion point
+ ? ellpadicheight(E,19,6, P)
+ %4 = O(19^6)
+ ? E = ellinit([0,0,1,-4,2]); P = [-2,1];
+ ? ellpadicheight(E,3,5, P)
+ %6 = [2*3^2 + 2*3^3 + 3^4 + O(3^5), 2*3^2 + 3^4 + 2*3^5 + 3^6 + O(3^7)]
+ ? ellpadicheight(E,3,5, P, elladd(E,P,P))
+ at eprog
+
+One can replace the parameter $p$ prime by a vector $[p,[a,b]]$, in which
+case the routine returns the $p$-adic number $af + bg$.
+
+When $E$ has good ordinary reduction at $p$, the ``canonical''
+$p$-adic height is given by
+\bprog
+s2 = ellpadics2(E,p,n);
+ellpadicheight(E, [p,[1,-s2]], n, P)
+ at eprog\noindent Since $s_2$ does not depend on $P$, it is preferable to
+compute it only once:
+\bprog
+? E = ellinit("5077a1"); p = 5; n = 7;
+? s2 = ellpadics2(E,p,n);
+? M = ellpadicheightmatrix(E,[p,[1,-s2]], n, E.gen);
+? matdet(M)   \\ p-adic regulator
+%4 = 5 + 5^2 + 4*5^3 + 2*5^4 + 2*5^5 + 5^6 + O(5^7)
+ at eprog
+
+The library syntax is \fun{GEN}{ellpadicheight0}{GEN E, GEN p, long n, GEN P, GEN Q = NULL}.
+
+\subsec{ellpadicheightmatrix$(E,p,n,v)$}\kbdsidx{ellpadicheightmatrix}\label{se:ellpadicheightmatrix}
+$v$ being a vector of points, this function outputs the Gram matrix of
+$v$ with respect to the cyclotomic $p$-adic height, given to $n$ $p$-adic
+digits; in other words, the $(i,j)$ component of the matrix is equal to
+\kbd{ellpadicheight}$(E,p,n, v[i],v[j]) = [f,g]$.
+
+See \tet{ellpadicheight}; in particular one can replace the parameter $p$
+prime by a vector $[p,[a,b]]$, in which case the routine returns the matrix
+containing the $p$-adic numbers $af + bg$.
+
+The library syntax is \fun{GEN}{ellpadicheightmatrix}{GEN E, GEN p, long n, GEN v}.
+
+\subsec{ellpadiclog$(E,p,n,P)$}\kbdsidx{ellpadiclog}\label{se:ellpadiclog}
+Given $E$ defined over $K = \Q$ or $\Q_p$ and $P = [x,y]$ on $E(K)$ in the
+kernel of reduction mod $p$, let $t(P) = -x/y$ be the formal group
+parameter; this function returns $L(t)$, where $L$ denotes the formal
+logarithm (mapping  the formal group of $E$  to the additive formal group)
+attached to the canonical invariant differential:
+$dL = dx/(2y + a_1x + a_3)$.
+
+The library syntax is \fun{GEN}{ellpadiclog}{GEN E, GEN p, long n, GEN P}.
+
+\subsec{ellpadics2$(E,p,n)$}\kbdsidx{ellpadics2}\label{se:ellpadics2}
+If $p>2$ is a prime and $E/\Q$ is a elliptic curve with ordinary good
+reduction at $p$, returns the slope of the unit eigenvector
+of \kbd{ellpadicfrobenius(E,p,n)}, i.e. the action of Frobenius $\varphi$ on
+the crystalline module $D_p(E)= \Q_p \otimes H^1_{dR}(E/\Q)$ in the basis of
+the given model $(\omega, \eta=x\*\omega)$, where $\omega$ is the invariant
+differential $dx/(2\*y+a_1\*x+a_3)$. In other words, $\eta + s_2\omega$
+is an eigenvector for the unit eigenvalue of $\varphi$.
+
+This slope is the unique $c \in 3^{-1}\Z_p$ such that the odd solution
+  $\sigma(t) = t + O(t^2)$ of
+$$ - d(\dfrac{1}{\sigma} \dfrac{d \sigma}{\omega})
+ = (x(t) + c) \omega$$
+is in $t\Z_p[[t]]$.
+
+It is equal to $b_2/12 - E_2/12$ where $E_2$ is the value of the Katz
+$p$-adic Eisenstein series of weight 2 on $(E,\omega)$. This is
+used to construct a canonical $p$-adic height when $E$ has good ordinary
+reduction at $p$ as follows
+\bprog
+s2 = ellpadics2(E,p,n);
+h(E,p,n, P, s2) = ellpadicheight(E, [p,[1,-s2]],n, P);
+ at eprog\noindent Since $s_2$ does not depend on the point $P$, we compute it
+only once.
+
+The library syntax is \fun{GEN}{ellpadics2}{GEN E, GEN p, long n}.
+
 \subsec{ellperiods$(w, \{\fl = 0\})$}\kbdsidx{ellperiods}\label{se:ellperiods}
 Let $w$ describe a complex period lattice ($w = [w_1,w_2]$
 or an ellinit structure). Returns normalized periods $[W_1,W_2]$ generating
@@ -5423,33 +6076,22 @@ curve $E$. The point $P$ must be of $m$-torsion.
 
 The library syntax is \fun{GEN}{elltatepairing}{GEN E, GEN P, GEN Q, GEN m}.
 
-\subsec{elltors$(E,\{\fl=0\})$}\kbdsidx{elltors}\label{se:elltors}
-If $E$ is an elliptic curve \emph{defined over $\Q$}, outputs the torsion
-subgroup of $E$ as a 3-component vector \kbd{[t,v1,v2]}, where \kbd{t} is the
-order of the torsion group, \kbd{v1} gives the structure of the torsion group
-as a product of cyclic groups (sorted by decreasing order), and \kbd{v2}
-gives generators for these cyclic groups. $E$ must be an \var{ell} structure
-as output by \kbd{ellinit}, defined over $\Q$.
-
+\subsec{elltors$(E)$}\kbdsidx{elltors}\label{se:elltors}
+If $E$ is an elliptic curve defined over a number field or a finite field,
+outputs the torsion subgroup of $E$ as a 3-component vector \kbd{[t,v1,v2]},
+where \kbd{t} is the order of the torsion group, \kbd{v1} gives the structure
+of the torsion group as a product of cyclic groups (sorted by decreasing
+order), and \kbd{v2} gives generators for these cyclic groups. $E$ must be an
+\var{ell} structure as output by \kbd{ellinit}.
 \bprog
 ?  E = ellinit([-1,0]);
 ?  elltors(E)
 %1 = [4, [2, 2], [[0, 0], [1, 0]]]
- at eprog
+ at eprog\noindent
 Here, the torsion subgroup is isomorphic to $\Z/2\Z \times \Z/2\Z$, with
 generators $[0,0]$ and $[1,0]$.
 
-If $\fl = 0$, find rational roots of division polynomials.
-
-If $\fl = 1$, use Lutz-Nagell (\emph{much} slower).
-
-If $\fl = 2$, use Doud's algorithm: bound torsion by computing $\#E(\F_p)$
-for small primes of good reduction, then look for torsion points using
-Weierstrass $\wp$ function (and Mazur's classification). For this variant,
-$E$ must be an \var{ell}.
-
-The library syntax is \fun{GEN}{elltors0}{GEN E, long flag}.
-Also available is \fun{GEN}{elltors}{GEN E} for \kbd{elltors(E, 0)}.
+The library syntax is \fun{GEN}{elltors}{GEN E}.
 
 \subsec{ellweilpairing$(E, P, Q, m)$}\kbdsidx{ellweilpairing}\label{se:ellweilpairing}
 Computes the Weil pairing of the two points of $m$-torsion $P$ and $Q$
@@ -5487,6 +6129,17 @@ For $\fl = 0$, we also have
 \fun{GEN}{ellwpseries}{GEN E, long v, long precdl} for the power series in
 variable $v$.
 
+\subsec{ellxn$(E,n,\{v='x\})$}\kbdsidx{ellxn}\label{se:ellxn}
+In standard notation, for any affine point $P = (v,w)$ on the
+curve $E$, we have
+$$[n]P = (\phi_n(P)\psi_n(P) : \omega_n(P) : \psi_n(P)^3)$$
+for some polynomials $\phi_n,\omega_n,\psi_n$ in
+$\Z[a_1,a_2,a_3,a_4,a_6][v,w]$. This function returns
+$[\phi_n(P),\psi_n(P)^2]$, which give the numerator and denominator of
+the abcissa of $[n]P$ and depend only on $v$.
+
+The library syntax is \fun{GEN}{ellxn}{GEN E, long n, long v = -1}, where \kbd{v} is a variable number.
+
 \subsec{ellzeta$(w,\{z='x\})$}\kbdsidx{ellzeta}\label{se:ellzeta}
 Computes the value at $z$ of the Weierstrass $\zeta$ function attached to
 the lattice $w$ as given by \tet{ellperiods}$(,1)$: including quasi-periods
@@ -5542,7 +6195,7 @@ divisors of the discriminant.
 
 \noindent This function rewritten from an implementation of Liu's algorithm by
 Cohen and Liu (1994), \kbd{genus2reduction-0.3}, see
-\kbd{http://www.math.u-bordeaux1.fr/\til liu/G2R/}.
+\url{http://www.math.u-bordeaux1.fr/~liu/G2R/}.
 
 \misctitle{CAVEAT} The function interface may change: for the
 time being, it returns $[N,\var{FaN}, T, V]$
@@ -5643,14 +6296,444 @@ Namikawa-Ueno.
 by \kbd{[2I\_0-(m+1)]}.
 
 The library syntax is \fun{GEN}{genus2red}{GEN Q, GEN P, GEN p = NULL}.
+
+\subsec{hyperellcharpoly$(Q)$}\kbdsidx{hyperellcharpoly}\label{se:hyperellcharpoly}
+Let $X$ be the curve defined by $y^2=Q(x)$, where  $Q$ is a polynomial of
+degree $2\*g+1$ over a finite field of characteristic $p\ge 2\*g$,
+return the characteristic polynomial of the Frobenius automorphism.
+
+The library syntax is \fun{GEN}{hyperellcharpoly}{GEN Q}.
+
+\subsec{hyperellpadicfrobenius$(Q,p,n)$}\kbdsidx{hyperellpadicfrobenius}\label{se:hyperellpadicfrobenius}
+Let $X$ be the curve defined by $y^2=Q(x)$, where  $Q$ is a polynomial of
+degree $2\*g+1$ over $\Q$ and $p\ge g$ a prime such that $X$ has good reduction
+at $p$ return the matrix of the Frobenius endomorphism $\varphi$ on the
+crystalline module $D_p(E) = \Q_p \otimes H^1_{dR}(E/\Q)$ with respect to the
+basis of the given model $(\omega, x\*\omega,\ldots,x^{g-1}\*\omega)$, where
+$\omega = dx/(2\*y)$ is the invariant differential.  The characteristic
+polynomial of $\varphi$ is the numerator of the zeta-function of the reduction
+of the curve $X$ modlo $p$. The matrix is computed to absolute $p$-adic
+precision $p^n$.
+
+The library syntax is \fun{GEN}{hyperellpadicfrobenius}{GEN Q, long p}.
 %SECTION: elliptic_curves
 
+\section{Functions related to modular forms and modular symbols}
+
+Let $\Delta := \text{Div}^0(\P^1(\Q))$ be the abelian group of divisors of
+degree $0$ on the rational projective line. The standard $\text{GL}(2,\Q)$
+action on $\P^1(\Q)$ via homographies naturally extends to $\Delta$. Given
+
+\item $G$ a finite index subgroup of $\text{SL}(2,\Z)$,
+
+\item a field $F$ and a finite dimensional representation $V/F$ of
+  $\text{GL}(2,\Q)$,
+
+\noindent we consider the space of \emph{modular symbols} $M :=
+\text{Hom}_G(\Delta, V)$. This finite dimensional $F$-vector
+space is a $G$-module, canonically isomorphic to $H^1_c(X(G), V)$,
+and allows to compute modular forms for $G$.
+
+Currently, we only support the groups $\Gamma_0(N)$ ($N > 1$ an integer)
+and the representations $V_k = \Q[X,Y]_{k-2}$ ($k \geq 2$ an integer) over
+$\Q$. We represent a space of modular symbols by an \var{ms} structure,
+created by the function \tet{msinit}. It encodes basic data associated to the
+space: chosen $\Z[G]$-generators $(g_i)$ for $\Delta$ (and relations among
+those) and an $F$-basis of $M$. A modular symbol $s$ is thus given either in
+terms of this fixed basis, or as a collection of values $s(g_i)$
+satisfying certain relations.
+
+A subspace of $M$ (e.g. the cuspidal or Eisenstein subspaces, the new or
+old modular symbols, etc.) is given by a structure allowing quick projection
+and restriction of linear operators; its first component is a matrix whose
+columns  form  an $F$-basis  of the subspace.
+
+
+\subsec{msatkinlehner$(M,Q,\{H\})$}\kbdsidx{msatkinlehner}\label{se:msatkinlehner}
+Let $M$ be a full modular symbol space of level $N$,
+as given by \kbd{msinit}, let $Q \mid N$, $(Q,N/Q) = 1$,
+and let $H$ be a subspace stable under the Atkin-Lehner involution $w_Q$.
+Return the matrix of $w_Q$ acting on $H$ ($M$ if omitted).
+\bprog
+? M = msinit(36,2); \\ M_2(Gamma_0(36))
+? w = msatkinlehner(M,4); w^2 == 1
+%2 = 1
+? #w   \\ involution acts on a 13-dimensional space
+%3 = 13
+? M = msinit(36,2, -1); \\ M_2(Gamma_0(36))^-
+? w = msatkinlehner(M,4); w^2 == 1
+%5 = 1
+? #w
+%6 = 4
+ at eprog
+
+The library syntax is \fun{GEN}{msatkinlehner}{GEN M, long Q, GEN H = NULL}.
+
+\subsec{mscuspidal$(M, \{\fl=0\})$}\kbdsidx{mscuspidal}\label{se:mscuspidal}
+$M$ being a full modular symbol space, as given by \kbd{msinit},
+return its cuspidal part $S$. If $\fl = 1$, return
+$[S,E]$ its decomposition into cuspidal and Eisenstein parts.
+
+A subspace is given by a structure allowing quick projection and
+restriction of linear operators; its first component is
+a matrix with integer coefficients whose columns form a $\Q$-basis of
+the subspace.
+\bprog
+? M = msinit(2,8, 1); \\ M_8(Gamma_0(2))^+
+? [S,E] = mscuspidal(M, 1);
+? E[1]  \\ 2-dimensional
+%3 =
+[0 -10]
+
+[0 -15]
+
+[0  -3]
+
+[1   0]
+
+? S[1]  \\ 1-dimensional
+%4 =
+[ 3]
+
+[30]
+
+[ 6]
+
+[-8]
+ at eprog
+
+The library syntax is \fun{GEN}{mscuspidal}{GEN M, long flag}.
+
+\subsec{mseisenstein$(M)$}\kbdsidx{mseisenstein}\label{se:mseisenstein}
+$M$ being a full modular symbol space, as given by \kbd{msinit},
+return its Eisenstein subspace.
+A subspace is given by a structure allowing quick projection and
+restriction of linear operators; its first component is
+a matrix with integer coefficients whose columns form a $\Q$-basis of
+the subspace.
+This is the same basis as given by the second component of
+\kbd{mscuspidal}$(M, 1)$.
+\bprog
+? M = msinit(2,8, 1); \\ M_8(Gamma_0(2))^+
+? E = mseisenstein(M);
+? E[1]  \\ 2-dimensional
+%3 =
+[0 -10]
+
+[0 -15]
+
+[0  -3]
+
+[1   0]
+
+? E == mscuspidal(M,1)[2]
+%4 = 1
+ at eprog
+
+The library syntax is \fun{GEN}{mseisenstein}{GEN M}.
+
+\subsec{mseval$(M,s,\{p\})$}\kbdsidx{mseval}\label{se:mseval}
+Let $\Delta:=\text{Div}^0(\P^1 (\Q))$.
+Let $M$ be a full modular symbol space, as given by \kbd{msinit},
+let $s$ be a modular symbol from $M$, i.e. an element
+of $\text{Hom}_G(\Delta, V)$, and let $p=[a,b] \in \Delta$ be a path between
+two elements in $\P^1(\Q)$, return $s(p)\in V$. The path extremities $a$ and
+$b$ may be given as \typ{INT}, \typ{FRAC} or $\kbd{oo} = (1:0)$.
+The symbol $s$ is either
+
+\item a \typ{COL} coding an element of a modular symbol subspace in terms of
+the fixed basis of $\text{Hom}_G(\Delta,V)$ chosen in $M$;
+
+\item a \typ{VEC} $(v_i)$ of elements of $V$, where the $v_i = s(g_i)$ give
+the image of the generators $g_i$ of $\Delta$, see \tet{mspathgens}.
+We assume that $s$ is a proper symbol, i.e.~that the $v_i$ satisfy
+the \kbd{mspathgens} relations.
+
+If $p$ is omitted, convert the symbol $s$ to the second form: a vector of
+the $s(g_i)$.
+\bprog
+? M = msinit(2,8,1); \\ M_8(Gamma_0(2))^+
+? g = mspathgens(M)[1]
+%2 = [[+oo, 0], [0, 1]]
+? N = msnew(M)[1]; \\ Q-basis of new subspace
+? s = N[,1]         \\ t_COL representation
+%4 = [3, 30, 6, -8]~
+? S = mseval(M, s)   \\ t_VEC representation
+%5 = [64*x^6-272*x^4+136*x^2-8, 384*x^5+960*x^4+192*x^3-672*x^2-432*x-72]
+? mseval(M,s, g[1])
+%6 = 64*x^6 - 272*x^4 + 136*x^2 - 8
+? mseval(M,S, g[1])
+%6 = 64*x^6 - 272*x^4 + 136*x^2 - 8
+ at eprog\noindent Note that the symbol should have values in
+$V = \Q[x,y]_{k-2}$, we return the de-homogenized values corresponding to $y
+= 1$ instead.
+
+The library syntax is \fun{GEN}{mseval}{GEN M, GEN s, GEN p = NULL}.
+
+\subsec{msfromell$(E, \{\var{sign}=1\})$}\kbdsidx{msfromell}\label{se:msfromell}
+Let $E/\Q$ be an elliptic curve of conductor $N$. Return the (cuspidal,
+new) modular symbol $x^+$ in $H^1_c(X_0(N),\Q)^+$ (resp.~$x^-$ in
+$H^1_c(X_0(N),\Q)^-$ if $\var{sign} = -1$) associated to
+$E$. For all primes $p$ not dividing $N$ we have
+$T_p(x^\pm) =  a_p x^\pm$, where $a_p = p+1-\#E(\F_p)$.
+This defines a unique symbol up to multiplication by a constant
+and we normalize it so that the associated $p$-adic measure yields the
+$p$-adic $L$-function. Namely, we have
+$$ x^{\pm}([0]-[\infty]) = L(E,1) / \Omega,$$
+for $\Omega$ the real period of $E$ (which fixes $x^{\pm}$ unless $L(E,1)=0$).
+Furthermore, for all odd fundamental discriminants $d$ coprime to $N$ such
+that $\var{sign}\cdot d > 0$ and $L(E^{(d)},1) \neq 0$, we also have
+$$\sum_{0\leq a<|d|} (d|a) x^{\pm}([a/|d|]-[\infty])
+   = L(E^{(d)},1) / \Omega_d,$$
+where $(d|a)$ is the Kronecker symbol and $\Omega_d$ is the real
+period of the twist $E^{(d)}$.
+
+This function returns the pair $[M, x]$, where $M$ is
+\kbd{msinit}$(N,2)$ and $x$ is $x^\pm$ as a \typ{COL} (in terms
+of the fixed basis of $\text{Hom}_G(\Delta,\Q)$ chosen in $M$).
+\bprog
+? E=ellinit([0,-1,1,-10,-20]);  \\ X_0(11)
+? [M,xpm]= msfromell(E,1);
+? xpm
+%3 = [1/5, -1/2, -1/2]~
+? p = 101; (mshecke(M,p) - ellap(E,p))*xpm
+%4 = [0, 0, 0]~ \\ true at all primes
+ at eprog
+
+The library syntax is \fun{GEN}{msfromell}{GEN E, long sign}.
+
+\subsec{mshecke$(M,p,\{H\})$}\kbdsidx{mshecke}\label{se:mshecke}
+$M$ being a full modular symbol space, as given by \kbd{msinit},
+$p$ being a prime number, and $H$ being a Hecke-stable subspace ($M$ if
+omitted) return the matrix of $T_p$ acting on $H$
+($U_p$ if $p$ divides $N$). Result is undefined if $H$ is not stable
+by $T_p$ (resp.~$U_p$).
+\bprog
+? M = msinit(11,2); \\ M_2(Gamma_0(11))
+? T2 = mshecke(M,2)
+%2 =
+[3  0  0]
+
+[1 -2  0]
+
+[1  0 -2]
+? M = msinit(11,2, 1); \\ M_2(Gamma_0(11))^+
+? T2 = mshecke(M,2)
+%4 =
+[ 3  0]
+
+[-1 -2]
+
+? N = msnew(M)[1]; \\ Q-basis of new cuspidal subspace
+%5 =
+[ 0]
+
+[-1]
+
+[-1]
+? p = 1009; mshecke(M, p, N) \\ action of T_1009 on N
+%6 =
+[-10]
+? ellap(ellinit("11a1"), p)
+%7 = -10
+ at eprog
+
+The library syntax is \fun{GEN}{mshecke}{GEN M, long p, GEN H = NULL}.
+
+\subsec{msinit$(G, V, \{\var{sign}=0\})$}\kbdsidx{msinit}\label{se:msinit}
+Given $G$ a finite index subgroup of $\text{SL}(2,\Z)$
+and a finite dimensional representation $V$ of $\text{GL}(2,\Q)$, creates a
+space of modular symbols, the $G$-module $\text{Hom}_G(\text{Div}^0(\P^1
+(\Q)), V)$. This is canonically isomorphic to $H^1_c(X(G), V)$, and allows to
+compute modular forms for $G$. If \emph{sign} is present and non-zero, it
+must be $\pm1$ and we consider the subspace defined by $\text{Ker} (\sigma -
+\var{sign})$, where $\sigma$ is induced by \kbd{[-1,0;0,1]}. Currently the
+only supported groups are the $\Gamma_0(N)$, coded by the integer $N > 1$.
+The only supported representation is $V_k = \Q[X,Y]_{k-2}$, coded by the
+integer $k \geq 2$.
+
+The library syntax is \fun{GEN}{msinit}{GEN G, GEN V, long sign}.
+
+\subsec{msissymbol$(M,s)$}\kbdsidx{msissymbol}\label{se:msissymbol}
+$M$ being a full modular symbol space, as given by \kbd{msinit},
+check whether $s$ is a modular symbol associated to $M$.
+\bprog
+? M = msinit(7,8, 1); \\ M_8(Gamma_0(7))^+
+? N = msnew(M)[1];
+? s = N[,1];
+? msissymbol(M, s)
+%4 = 1
+? S = mseval(M,s);
+? msissymbol(M, S)
+%6 = 1
+? [g,R] = mspathgens(M); g
+%7 = [[+oo, 0], [0, 1/2], [1/2, 1]]
+? #R  \\ 3 relations among the generators g_i
+%8 = 3
+? T = S; T[3]++; \\ randomly perturb S(g_3)
+? msissymbol(M, T)
+%10 = 0  \\ no longer satisfies the relations
+ at eprog
+
+The library syntax is \fun{long}{msissymbol}{GEN M, GEN s}.
+
+\subsec{msnew$(M)$}\kbdsidx{msnew}\label{se:msnew}
+$M$ being a full modular symbol space, as given by \kbd{msinit},
+return the \emph{new} part of its cuspidal subspace. A subspace is given by
+a structure allowing quick projection and restriction of linear operators;
+its first component is a matrix with integer coefficients whose columns form
+a $\Q$-basis of the subspace.
+\bprog
+? M = msinit(11,8, 1); \\ M_8(Gamma_0(11))^+
+? N = msnew(M);
+? #N[1]  \\ 6-dimensional
+%3 = 6
+ at eprog
+
+The library syntax is \fun{GEN}{msnew}{GEN M}.
+
+\subsec{mspathgens$(M)$}\kbdsidx{mspathgens}\label{se:mspathgens}
+Let $\Delta:=\text{Div}^0(\P^1(\Q))$.
+Let $M$ being a full modular symbol space, as given by \kbd{msinit},
+return a set of $\Z[G]$-generators for $\Delta$. The output
+is $[g,R]$, where $g$ is a minimal system of generators and $R$
+the vector of $\Z[G]$-relations between the given generators. A
+relation is coded by a vector of pairs $[a_i,i]$ with $a_i\in \Z[G]$
+and $i$ the index of a generator, so that $\sum_i a_i g[i] = 0$.
+
+An element $[v]-[u]$ in $\Delta$ is coded by the ``path'' $[u,v]$,
+where \kbd{oo} denotes the point at infinity $(1:0)$ on the projective
+line.
+An element of $\Z[G]$ is coded by a ``factorization matrix'': the first
+column contains distinct elements of $G$, and the second integers:
+\bprog
+? M = msinit(11,8); \\ M_8(Gamma_0(11))
+? [g,R] = mspathgens(M);
+? g
+%3 = [[+oo, 0], [0, 1/3], [1/3, 1/2]] \\ 3 paths
+? #R  \\ a single relation
+%4 = 1
+? r = R[1]; #r \\ ...involving all 3 generators
+%5 = 3
+? r[1]
+%6 = [[1, 1; [1, 1; 0, 1], -1], 1]
+? r[2]
+%7 = [[1, 1; [7, -2; 11, -3], -1], 2]
+? r[3]
+%8 = [[1, 1; [8, -3; 11, -4], -1], 3]
+ at eprog\noindent
+The given relation is of the form $\sum_i (1-\gamma_i) g_i = 0$, with
+$\gamma_i\in \Gamma_0(11)$. There will always be a single relation involving
+all generators (corresponding to a round trip along all cusps), then
+relations involving a single generator (corresponding to $2$ and $3$-torsion
+elements in the group:
+\bprog
+? M = msinit(2,8); \\ M_8(Gamma_0(2))
+? [g,R] = mspathgens(M);
+? g
+%3 = [[+oo, 0], [0, 1]]
+ at eprog\noindent
+Note that the output depends only on the group $G$, not on the
+representation $V$.
+
+The library syntax is \fun{GEN}{mspathgens}{GEN M}.
+
+\subsec{mspathlog$(M,p)$}\kbdsidx{mspathlog}\label{se:mspathlog}
+Let $\Delta:=\text{Div}^0(\P^1(\Q))$.
+Let $M$ being a full modular symbol space, as given by \kbd{msinit},
+encoding fixed $\Z[G]$-generators $(g_i)$ of $\Delta$ (see \tet{mspathgens}).
+A path $p=[a,b]$ between two elements in $\P^1(\Q)$ corresponds to
+$[b]-[a]\in \Delta$. The path extremities $a$ and $b$ may be given as
+\typ{INT}, \typ{FRAC} or $\kbd{oo} = (1:0)$.
+
+Returns $(p_i)$ in $\Z[G]$ such that $p = \sum_i p_i g_i$.
+\bprog
+? M = msinit(2,8); \\ M_8(Gamma_0(2))
+? [g,R] = mspathgens(M);
+? g
+%3 = [[+oo, 0], [0, 1]]
+? p = mspathlog(M, [1/2,2/3]);
+? p[1]
+%6 =
+[[1, 0; 2, 1] 1]
+
+? p[2]
+%7 =
+[  [1, 0; 0, 1] 1]
+
+[[3, -1; 4, -1] 1]
+
+ at eprog\noindent
+Note that the output depends only on the group $G$, not on the
+representation $V$.
+
+The library syntax is \fun{GEN}{mspathlog}{GEN M, GEN p}.
+
+\subsec{msqexpansion$(M,\var{projH},\{B = \var{seriesprecision}\})$}\kbdsidx{msqexpansion}\label{se:msqexpansion}
+$M$ being a full modular symbol space, as given by \kbd{msinit},
+and \var{projH} being a projector on a Hecke-simple subspace (as given
+by \tet{mssplit}), return the Fourier coefficients $a_n$, $n\leq B$ of the
+corresponding normalized newform. If $B$ is omitted, use
+\kbd{seriesprecision}.
+
+This function uses a naive $O(B^2 d^3)$
+algorithm, where $d = O(kN)$ is the dimension of $M_k(\Gamma_0(N))$.
+\bprog
+? M = msinit(11,2, 1); \\ M_2(Gamma_0(11))^+
+? L = mssplit(M, msnew(M));
+? msqexpansion(M,L[1], 20)
+%3 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2, 1, -2, 4, 4, -1, -4, -2, 4, 0, 2]
+? ellan(ellinit("11a1"), 20)
+%4 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2, 1, -2, 4, 4, -1, -4, -2, 4, 0, 2]
+ at eprog
+
+The library syntax is \fun{GEN}{msqexpansion}{GEN M, GEN projH, long precdl}.
+
+\subsec{mssplit$(M,H)$}\kbdsidx{mssplit}\label{se:mssplit}
+$M$ being a full modular symbol space, as given by \kbd{msinit}$(N,k,1)$
+or $\kbd{msinit}(N,k,-1)$
+and $H$ being a Hecke-stable subspace of \kbd{msnew}$(M)$, split $H$ into
+Hecke-simple subspaces.
+A subspace is given by a structure allowing quick projection and restriction
+of linear operators; its first component is a matrix with integer
+coefficients whose columns form a $\Q$-basis of the subspace.
+\bprog
+? M = msinit(11,8, 1); \\ M_8(Gamma_0(11))^+
+? L = mssplit(M, msnew(M));
+? #L
+%3 = 2
+? f = msqexpansion(M,L[1],5); f[1].mod
+%4 = x^2 + 8*x - 44
+? lift(f)
+%5 = [1, x, -6*x - 27, -8*x - 84, 20*x - 155]
+? g = msqexpansion(M,L[2],5); g[1].mod
+%6 = x^4 - 558*x^2 + 140*x + 51744
+ at eprog\noindent To a Hecke-simple subspace corresponds an orbit of
+(normalized) newforms, defined over a number field. In the above example,
+we printed the polynomials defining the said fields, as well as the first
+5 Fourier coefficients (at the infinite cusp) of one such form.
+
+The library syntax is \fun{GEN}{mssplit}{GEN M, GEN H}.
+
+\subsec{msstar$(M,\{H\})$}\kbdsidx{msstar}\label{se:msstar}
+$M$ being a full modular symbol space, as given by \kbd{msinit},
+return the matrix of the \kbd{*} involution, induced by complex conjugation,
+acting on the (stable) subspace $H$ ($M$ if omitted).
+\bprog
+? M = msinit(11,2); \\ M_2(Gamma_0(11))
+? w = msstar(M);
+? w^2 == 1
+%3 = 1
+ at eprog
+
+The library syntax is \fun{GEN}{msstar}{GEN M, GEN H = NULL}.
+%SECTION: modular_forms
+
 \section{Functions related to general number fields}
 
-In this section can be found functions which are used almost exclusively for
-working in general number fields. Other less specific functions can be found
-in the next section on polynomials. Functions related to quadratic number
-fields are found in section \secref{se:arithmetic} (Arithmetic functions).
+In this section, we describe functions related to general number fields.
+Functions related to quadratic number fields are found in
+section \secref{se:arithmetic} (Arithmetic functions).
 
 \subsec{Number field structures}
 
@@ -6594,6 +7677,27 @@ or \tet{bnrdisc} is more efficient.
 
 The library syntax is \fun{GEN}{bnrdisclist0}{GEN bnf, GEN bound, GEN arch = NULL}.
 
+\subsec{bnrgaloisapply$(\var{bnr}, \var{mat}, H)$}\kbdsidx{bnrgaloisapply}\label{se:bnrgaloisapply}
+Apply the automorphism given by its matrix \var{mat} to the congruence
+subgroup $H$ given as a HNF matrix.
+The matrix \var{mat} can be computed with \tet{bnrgaloismatrix}.
+
+The library syntax is \fun{GEN}{bnrgaloisapply}{GEN bnr, GEN mat, GEN H}.
+
+\subsec{bnrgaloismatrix$(\var{bnr},\var{aut})$}\kbdsidx{bnrgaloismatrix}\label{se:bnrgaloismatrix}
+Return the matrix of the action of the automorphism \var{aut} of the base
+field \kbd{bnf.nf} on the generators of the ray class field \kbd{bnr.gen}.
+\var{aut} can be given as a polynomial, an algebraic number, or a vector of
+automorphisms or a Galois group as output by \kbd{galoisinit}, in which case a
+vector of matrices is returned (in the later case, only for the generators
+\kbd{aut.gen}).
+
+See \kbd{bnrisgalois} for an example.
+
+The library syntax is \fun{GEN}{bnrgaloismatrix}{GEN bnr, GEN aut}.
+When $aut$ is a polynomial or an algebraic number,
+\fun{GEN}{bnrautmatrix}{GEN bnr, GEN aut} is available.
+
 \subsec{bnrinit$(\var{bnf},f,\{\fl=0\})$}\kbdsidx{bnrinit}\label{se:bnrinit}
 $\var{bnf}$ is as
 output by \kbd{bnfinit}, $f$ is a modulus, initializes data linked to
@@ -6628,8 +7732,8 @@ The library syntax is \fun{GEN}{bnrinit0}{GEN bnf, GEN f, long flag}.
 Instead the above  hardcoded  numerical flags,  one should rather use
 \fun{GEN}{Buchray}{GEN bnf, GEN module, long flag}
 where flag is an or-ed combination of \kbd{nf\_GEN} (include generators)
-and \kbd{nf\_INIT} (if omitted, return just the cardinal of the ray class group
-and its structure), possibly 0.
+and \kbd{nf\_INIT} (if omitted, return just the cardinality of the ray class
+group and its structure), possibly 0.
 
 \subsec{bnrisconductor$(A,\{B\},\{C\})$}\kbdsidx{bnrisconductor}\label{se:bnrisconductor}
 $A$, $B$, $C$ represent
@@ -6639,6 +7743,33 @@ otherwise. This is slightly faster than \kbd{bnrconductor}.
 
 The library syntax is \fun{long}{bnrisconductor0}{GEN A, GEN B = NULL, GEN C = NULL}.
 
+\subsec{bnrisgalois$(\var{bnr}, \var{gal}, H)$}\kbdsidx{bnrisgalois}\label{se:bnrisgalois}
+Check whether the class field associated to the subgroup $H$ is Galois
+over the subfield of \kbd{bnr.nf} fixed by the group \var{gal}, which can be
+given as output by \tet{galoisinit}, or as a matrix or a vector of matrices as
+output by \kbd{bnrgaloismatrix}, the second option being preferable, since it
+saves the recomputation of the matrices.  Note: The function assumes that the
+ray class field associated to bnr is Galois, which is not checked.
+
+In the following example, we lists the congruence subgroups of subextension of
+degree at most $3$ of the ray class field of conductor $9$ which are Galois
+over the rationals.
+
+\bprog
+K=bnfinit(a^4-3*a^2+253009);
+G=galoisinit(K);
+B=bnrinit(K,9,1);
+L1=[H|H<-subgrouplist(B,3), bnrisgalois(B,G,H)]
+##
+M=bnrgaloismatrix(B,G)
+L2=[H|H<-subgrouplist(B,3), bnrisgalois(B,M,H)]
+##
+ at eprog
+The second computation is much faster since \kbd{bnrgaloismatrix(B,G)} is
+computed only once.
+
+The library syntax is \fun{long}{bnrisgalois}{GEN bnr, GEN gal, GEN H}.
+
 \subsec{bnrisprincipal$(\var{bnr},x,\{\fl=1\})$}\kbdsidx{bnrisprincipal}\label{se:bnrisprincipal}
 \var{bnr} being the
 number field data which is output by \kbd{bnrinit}$(,,1)$ and $x$ being an
@@ -7071,7 +8202,7 @@ Outputs all the subgroups of the Galois group \kbd{gal}. A subgroup is a
 vector [\var{gen}, \var{orders}], with the same meaning
 as for $\var{gal}.gen$ and $\var{gal}.orders$. Hence \var{gen} is a vector of
 permutations generating the subgroup, and \var{orders} is the relatives
-orders of the generators. The cardinal of a subgroup is the product of the
+orders of the generators. The cardinality of a subgroup is the product of the
 relative orders. Such subgroup can be used instead of a Galois group in the
 following command: \kbd{galoisisabelian}, \kbd{galoissubgroups},
 \kbd{galoisexport} and \kbd{galoisidentify}.
@@ -7536,10 +8667,12 @@ The library syntax is \fun{GEN}{idealpow0}{GEN nf, GEN x, GEN k, long flag}.
 \fun{GEN}{idealpows}{GEN nf, GEN x, long k} ($\fl = 0$).
 Corresponding to $\fl=1$ is \fun{GEN}{idealpowred}{GEN nf, GEN vp, GEN k}.
 
-\subsec{idealprimedec$(\var{nf},p)$}\kbdsidx{idealprimedec}\label{se:idealprimedec}
+\subsec{idealprimedec$(\var{nf},p,\{f=0\})$}\kbdsidx{idealprimedec}\label{se:idealprimedec}
 Computes the prime ideal
 decomposition of the (positive) prime number $p$ in the number field $K$
 represented by \var{nf}. If a non-prime $p$ is given the result is undefined.
+If $f$ is present and non-zero, restrict the result to primes of residue
+degree $\leq f$.
 
 The result is a vector of \tev{prid} structures, each representing one of the
 prime ideals above $p$ in the number field $\var{nf}$. The representation
@@ -7560,10 +8693,10 @@ The components of \kbd{pr} should be accessed by member functions: \kbd{pr.p},
 \kbd{pr.e}, \kbd{pr.f}, and \kbd{pr.gen} (returns the vector $[p,a]$):
 \bprog
 ? K = nfinit(x^3-2);
-? L = idealprimedec(K, 5);
-? #L       \\ 2 primes above 5 in Q(2^(1/3))
+? P = idealprimedec(K, 5);
+? #P       \\ 2 primes above 5 in Q(2^(1/3))
 %3 = 2
-? p1 = L[1]; p2 = L[2];
+? [p1,p2] = P;
 ? [p1.e, p1.f]    \\ the first is unramified of degree 1
 %4 = [1, 1]
 ? [p2.e, p2.f]    \\ the second is unramified of degree 2
@@ -7572,9 +8705,11 @@ The components of \kbd{pr} should be accessed by member functions: \kbd{pr.p},
 %6 = [5, [2, 1, 0]~]
 ? nfbasistoalg(K, %[2])  \\ a uniformizer for p1
 %7 = Mod(x + 2, x^3 - 2)
+? #idealprimedec(K, 5, 1) \\ restrict to f = 1
+%8 = 1            \\ now only p1
 @eprog
 
-The library syntax is \fun{GEN}{idealprimedec}{GEN nf, GEN p}.
+The library syntax is \fun{GEN}{idealprimedec_limit_f}{GEN nf, GEN p, long f}.
 
 \subsec{idealprincipalunits$(\var{nf},\var{pr},k)$}\kbdsidx{idealprincipalunits}\label{se:idealprincipalunits}
 Given a prime ideal in \tet{idealprimedec} format,
@@ -7752,8 +8887,12 @@ Also available are
 \subsec{idealval$(\var{nf},x,\var{pr})$}\kbdsidx{idealval}\label{se:idealval}
 Gives the valuation of the ideal $x$ at the prime ideal \var{pr} in the
 number field $\var{nf}$, where \var{pr} is in \kbd{idealprimedec} format.
+The valuation of the $0$ ideal is \kbd{+oo}.
 
-The library syntax is \fun{long}{idealval}{GEN nf, GEN x, GEN pr}.
+The library syntax is \fun{GEN}{gpidealval}{GEN nf, GEN x, GEN pr}.
+Also available is
+\fun{long}{idealval}{GEN nf, GEN x, GEN pr}, which returns
+\tet{LONG_MAX} if $x = 0$ and the valuation as a \kbd{long} integer.
 
 \subsec{matalgtobasis$(\var{nf},x)$}\kbdsidx{matalgtobasis}\label{se:matalgtobasis}
 $\var{nf}$ being a number field in \kbd{nfinit} format, and $x$ a
@@ -7980,6 +9119,64 @@ them, then check whether \kbd{nfdisc(nf.pol)} is equal to \kbd{nf.disc}.
 
 The library syntax is \fun{GEN}{nfcertify}{GEN nf}.
 
+\subsec{nfcompositum$(\var{nf},P,Q,\{\fl=0\})$}\kbdsidx{nfcompositum}\label{se:nfcompositum}
+Let \var{nf} be a number field structure associated to the field $K$
+and let \sidx{compositum} $P$ and $Q$
+be squarefree polynomials in $K[X]$ in the same variable. Outputs
+the simple factors of the \'etale $K$-algebra $A = K(X, Y) / (P(X), Q(Y))$.
+The factors are given by a list of polynomials $R$ in $K[X]$, associated to
+the number field $K(X)/ (R)$, and sorted by increasing degree (with respect
+to lexicographic ordering for factors of equal degrees). Returns an error if
+one of the polynomials is not squarefree.
+
+Note that it is more efficient to reduce to the case where $P$ and $Q$ are
+irreducible first. The routine will not perform this for you, since it may be
+expensive, and the inputs are irreducible in most applications anyway. In
+this case, there will be a single factor $R$ if and only if the number
+fields defined by $P$ and $Q$ are linearly disjoint (their intersection is
+$K$).
+
+The binary digits of $\fl$ mean
+
+1: outputs a vector of 4-component vectors $[R,a,b,k]$, where $R$
+ranges through the list of all possible compositums as above, and $a$
+(resp. $b$) expresses the root of $P$ (resp. $Q$) as an element of
+$K(X)/(R)$. Finally, $k$ is a small integer such that $b + ka = X$ modulo
+$R$.
+
+2: assume that $P$ and $Q$ define number fields which are linearly disjoint:
+both polynomials are irreducible and the corresponding number fields
+have no common subfield besides $K$. This allows to save a costly
+factorization over $K$. In this case return the single simple factor
+instead of a vector with one element.
+
+A compositum is often defined by a complicated polynomial, which it is
+advisable to reduce before further work. Here is an example involving
+the field $K(\zeta_5, 5^{1/5})$, $K=\Q(\sqrt{5})$:
+\bprog
+? K = nfinit(y^2-5);
+? L = nfcompositum(K, x^5 - y, polcyclo(5), 1); \\@com list of $[R,a,b,k]$
+? [R, a] = L[1];  \\@com pick the single factor, extract $R,a$ (ignore $b,k$)
+? lift(R)         \\@com defines the compositum
+%3 = x^10 + (-5/2*y + 5/2)*x^9 + (-5*y + 20)*x^8 + (-20*y + 30)*x^7 + \
+(-45/2*y + 145/2)*x^6 + (-71/2*y + 121/2)*x^5 + (-20*y + 60)*x^4 +    \
+(-25*y + 5)*x^3 + 45*x^2 + (-5*y + 15)*x + (-2*y + 6)
+? a^5 - y         \\@com a fifth root of $y$
+%4 = 0
+? [T, X] = rnfpolredbest(K, R, 1);
+? lift(T)     \\@com simpler defining polynomial for $K[x]/(R)$
+%6 = x^10 + (-11/2*y + 25/2)
+? liftall(X)  \\ @com root of $R$ in $K[x]/(T(x))$
+%7 = (3/4*y + 7/4)*x^7 + (-1/2*y - 1)*x^5 + 1/2*x^2 + (1/4*y - 1/4)
+? a = subst(a.pol, 'x, X);  \\@com \kbd{a} in the new coordinates
+? liftall(a)
+%8 = (-3/4*y - 7/4)*x^7 - 1/2*x^2
+? a^5 - y
+%9 = 0
+ at eprog
+
+The library syntax is \fun{GEN}{nfcompositum}{GEN nf, GEN P, GEN Q, long flag}.
+
 \subsec{nfdetint$(\var{nf},x)$}\kbdsidx{nfdetint}\label{se:nfdetint}
 Given a pseudo-matrix $x$, computes a
 non-zero ideal contained in (i.e.~multiple of) the determinant of $x$. This
@@ -8126,15 +9323,43 @@ Returns the absolute trace of $x$.
 
 The library syntax is \fun{GEN}{nftrace}{GEN nf, GEN x}.
 
-\subsec{nfeltval$(\var{nf},x,\var{pr})$}\kbdsidx{nfeltval}\label{se:nfeltval}
+\subsec{nfeltval$(\var{nf},x,\var{pr},\{\&y\})$}\kbdsidx{nfeltval}\label{se:nfeltval}
 Given an element $x$ in
 \var{nf} and a prime ideal \var{pr} in the format output by
-\kbd{idealprimedec}, computes the valuation at \var{pr} of the
-element $x$. The same result can be obtained using
+\kbd{idealprimedec}, computes the valuation $v$ at \var{pr} of the
+element $x$. The valuation of $0$ is \kbd{+oo}.
+\bprog
+? nf = nfinit(x^2 + 1);
+? P = idealprimedec(nf, 2)[1];
+? nfeltval(nf, x+1, P)
+%3 = 1
+ at eprog\noindent
+This particular valuation can also be obtained using
 \kbd{idealval(\var{nf},x,\var{pr})}, since $x$ is then converted to a
 principal ideal.
 
-The library syntax is \fun{long}{nfval}{GEN nf, GEN x, GEN pr}.
+If the $y$ argument is present, sets $y = x \tau^v$, where $\tau$ is a
+fixed ``anti-uniformizer'' for \var{pr}: its valuation at \var{pr} is $-1$;
+its valuation is $0$ at other prime ideals dividing \kbd{\var{pr}.p} and
+nonnegative at all other primes. In other words $y$ is the part of $x$
+coprime to \var{pr}. If $x$ is an algebraic integer, so is $y$.
+\bprog
+? nfeltval(nf, x+1, P, &y); y
+%4 = [0, 1]~
+ at eprog
+For instance if $x = \prod_i x_i^{e_i}$ is known to be coprime to \var{pr},
+where the $x_i$ are algebraic integers and $e_i\in\Z$ then,
+if $v_i = \kbd{nfeltval}(\var{nf}, x_i, \var{pr}, \&y_i)$, we still
+have $x = \prod_i y_i^{e_i}$, where the $y_i$ are still algebraic integers
+but now all of them are coprime to \var{pr}. They can then be mapped to
+the residue field of \var{pr} more efficiently than if the product had
+been expanded beforehand: we can reduce mod \var{pr} after each ring
+operation.
+
+The library syntax is \fun{GEN}{gpnfvalrem}{GEN nf, GEN x, GEN pr, GEN *y = NULL}.
+Also available is
+\fun{long}{nfvalrem}{GEN nf, GEN x, GEN pr, GEN *y = NULL}, which returns
+\tet{LONG_MAX} if $x = 0$ and the valuation as a \kbd{long} integer.
 
 \subsec{nffactor$(\var{nf},T)$}\kbdsidx{nffactor}\label{se:nffactor}
 Factorization of the univariate
@@ -8308,6 +9533,31 @@ Use directly
 \fun{GEN}{galoisconj}{GEN nf, GEN d}, corresponding to $\fl = 0$, the others
 only have historical interest.
 
+\subsec{nfgrunwaldwang$(\var{nf},\var{Lpr},\var{Ld},\var{pl},\{v='x\})$}\kbdsidx{nfgrunwaldwang}\label{se:nfgrunwaldwang}
+Given \var{nf} a number field in \var{nf} or \var{bnf} format,
+a \typ{VEC} \var{Lpr} of primes of \var{nf} and a \typ{VEC} \var{Ld} of
+positive integers of the same length, a \typ{VECSMALL} \var{pl} of length
+$r_1$ the number of real places of \var{nf}, computes a polynomial with
+coefficients in \var{nf} defining a cyclic extension of \var{nf} of
+minimal degree satisfying certain local conditions:
+
+\item at the prime \kbd{Lpr[i]}, the extension has local degree a multiple of
+\kbd{Ld[i]};
+
+\item at the $i$-th real place of \var{nf}, it is complex if $pl[i]=-1$
+(no condition if $pl[i]=1$).
+
+The extension has degree the LCM of the local degrees. Currently, the degree
+is restricted to be a prime power for the search, and to be prime for the
+construction because of the \kbd{rnfkummer} restrictions.
+
+\misctitle{Warning} If the number field \var{nf} does not contain the $n$-th
+roots of unity where $n$ is the degree of the extension to be computed,
+triggers the computation of the \var{bnf} of $nf(\zeta_n)$, which may be
+costly.
+
+The library syntax is \fun{GEN}{nfgrunwaldwang}{GEN nf, GEN Lpr, GEN Ld, GEN pl, long v = -1}, where \kbd{v} is a variable number.
+
 \subsec{nfhilbert$(\var{nf},a,b,\{\var{pr}\})$}\kbdsidx{nfhilbert}\label{se:nfhilbert}
 If \var{pr} is omitted,
 compute the global quadratic \idx{Hilbert symbol} $(a,b)$ in $\var{nf}$, that
@@ -8320,13 +9570,17 @@ The library syntax is \fun{long}{nfhilbert0}{GEN nf, GEN a, GEN b, GEN pr = NULL
 Also available is \fun{long}{nfhilbert}{GEN bnf,GEN a,GEN b} (global
 quadratic Hilbert symbol).
 
-\subsec{nfhnf$(\var{nf},x)$}\kbdsidx{nfhnf}\label{se:nfhnf}
+\subsec{nfhnf$(\var{nf},x,\{\fl=0\})$}\kbdsidx{nfhnf}\label{se:nfhnf}
 Given a pseudo-matrix $(A,I)$, finds a
-pseudo-basis in \idx{Hermite normal form} of the module it generates.
+pseudo-basis $(B,J)$ in \idx{Hermite normal form} of the module it generates.
+If $\fl$ is non-zero, also return the transfomation matrix $U$ such that
+$AU = [0|B]$.
 
-The library syntax is \fun{GEN}{nfhnf}{GEN nf, GEN x}.
+The library syntax is \fun{GEN}{nfhnf0}{GEN nf, GEN x, long flag}.
 Also available:
 
+\fun{GEN}{nfhnf}{GEN nf, GEN x} ($\fl = 0$).
+
 \fun{GEN}{rnfsimplifybasis}{GEN bnf, GEN x} simplifies the pseudo-basis
 given by $x = (A,I)$. The ideals in the list $I$ are integral, primitive and
 either trivial (equal to the full ring of integer) or non-principal.
@@ -8411,8 +9665,10 @@ of the integral basis.
 
 If a non monic polynomial is input, \kbd{nfinit} will transform it into a
 monic one, then reduce it (see $\fl=3$). It is allowed, though not very
-useful given the existence of \tet{nfnewprec}, to input a \kbd{nf} or a
-\kbd{bnf} instead of a polynomial.
+useful given the existence of \tet{nfnewprec}, to input a \var{nf} or a
+\var{bnf} instead of a polynomial. It is also allowed to
+input a \var{rnf}, in which case an \var{nf} structure associated to the
+absolute defining polynomial \kbd{polabs} is returned (\fl is then ignored).
 
 \bprog
 ? nf = nfinit(x^3 - 12); \\ initialize number field Q[X] / (X^3 - 12)
@@ -8603,11 +9859,13 @@ faster than the default when there \emph{are} roots of $1$ in the field
 (say twice faster), but can be much slower (say, \emph{days} slower), since
 the algorithm is a priori exponential in the field degree.
 
-\subsec{nfsnf$(\var{nf},x)$}\kbdsidx{nfsnf}\label{se:nfsnf}
-Given a $\Z_K$-module $x$ associated to the integral pseudo-matrix
-$(A,I,J)$, returns an ideal list $d_1,\dots,d_n$ which is the \idx{Smith
-normal form} of $x$. In other words, $x$ is isomorphic to
-$\Z_K/d_1\oplus\cdots\oplus\Z_K/d_n$ and $d_i$ divides $d_{i-1}$ for $i\ge2$.
+\subsec{nfsnf$(\var{nf},x,\{\fl=0\})$}\kbdsidx{nfsnf}\label{se:nfsnf}
+Given a torsion $\Z_K$-module $x$ associated to the square integral
+invertible pseudo-matrix $(A,I,J)$, returns an ideal list
+$D=[d_1,\dots,d_n]$ which is the \idx{Smith normal form} of $x$. In other
+words, $x$ is isomorphic to $\Z_K/d_1\oplus\cdots\oplus\Z_K/d_n$ and $d_i$
+divides $d_{i-1}$ for $i\ge2$. If $\fl$ is non-zero return $[D,U,V]$, where
+$UAV$ is the identity.
 
 See \secref{se:ZKmodules} for the definition of integral pseudo-matrix;
 briefly, it is input as a 3-component row vector $[A,I,J]$ where
@@ -8622,7 +9880,10 @@ is not satisfied, then the $d_i$ will not be integral. Note that every
 finitely generated torsion module is isomorphic to a module of this form and
 even with $b_i=Z_K$ for all $i$.
 
-The library syntax is \fun{GEN}{nfsnf}{GEN nf, GEN x}.
+The library syntax is \fun{GEN}{nfsnf0}{GEN nf, GEN x, long flag}.
+Also available:
+
+\fun{GEN}{nfsnf}{GEN nf, GEN x} ($\fl = 0$).
 
 \subsec{nfsolvemodpr$(\var{nf},a,b,P)$}\kbdsidx{nfsolvemodpr}\label{se:nfsolvemodpr}
 Let $P$ be a prime ideal in \key{modpr} format (see \kbd{nfmodprinit}),
@@ -8642,6 +9903,29 @@ The library syntax is \fun{GEN}{nfsolvemodpr}{GEN nf, GEN a, GEN b, GEN P}.
 This function is normally useless in library mode. Project your
 inputs to the residue field using \kbd{nfM\_to\_FqM}, then work there.
 
+\subsec{nfsplitting$(\var{nf},\{d\})$}\kbdsidx{nfsplitting}\label{se:nfsplitting}
+Defining polynomial for the splitting field of \var{nf};
+if $d$ is given, it must be the degree of the splitting field. It
+is possible to input a defining polynomial $T$ instead but this is in
+general less efficient.
+\bprog
+? K = nfinit(x^3-2);
+? nfsplitting(K)
+%2 = x^6 + 108
+?  nfsplitting(x^8-2)
+%3 = x^16 + 272*x^8 + 64
+ at eprog\noindent
+The complexity of the algorithm is polynomial in the degree $d$ of the
+splitting field and the bitsize of $T$; if $d$ is large the result will
+likely be unusable, e.g. \kbd{nfinit} will not be an option:
+\bprog
+? nfsplitting(x^6-x-1)
+[... degree 720 polynomial deleted ...]
+time = 11,020 ms.
+ at eprog
+
+The library syntax is \fun{GEN}{nfsplitting}{GEN nf, GEN d = NULL}.
+
 \subsec{nfsubfields$(\var{pol},\{d=0\})$}\kbdsidx{nfsubfields}\label{se:nfsubfields}
 Finds all subfields of degree
 $d$ of the number field defined by the (monic, integral) polynomial
@@ -8667,7 +9951,8 @@ Note that it is more efficient to reduce to the case where $P$ and $Q$ are
 irreducible first. The routine will not perform this for you, since it may be
 expensive, and the inputs are irreducible in most applications anyway. In
 this case, there will be a single factor $R$ if and only if the number
-fields defined by $P$ and $Q$ are disjoint.
+fields defined by $P$ and $Q$ are linearly disjoint (their intersection is
+$\Q$).
 
 Assuming $P$ is irreducible (of smaller degree than $Q$ for efficiency), it
 is in general much faster to proceed as follows
@@ -8679,12 +9964,20 @@ to obtain the same result. If you are only interested in the degrees of the
 simple factors, the \kbd{rnfequation} instruction can be replaced by a
 trivial \kbd{poldegree(P) * poldegree(L[i])}.
 
-If $\fl=1$, outputs a vector of 4-component vectors $[R,a,b,k]$, where $R$
+The binary digits of $\fl$ mean
+
+1: outputs a vector of 4-component vectors $[R,a,b,k]$, where $R$
 ranges through the list of all possible compositums as above, and $a$
 (resp. $b$) expresses the root of $P$ (resp. $Q$) as an element of
 $\Q(X)/(R)$. Finally, $k$ is a small integer such that $b + ka = X$ modulo
 $R$.
 
+2: assume that $P$ and $Q$ define number fields which are linearly disjoint:
+both polynomials are irreducible and the corresponding number fields
+have no common subfield besides $\Q$. This allows to save a costly
+factorization over $\Q$. In this case return the single simple factor
+instead of a vector with one element.
+
 A compositum is often defined by a complicated polynomial, which it is
 advisable to reduce before further work. Here is an example involving
 the field $\Q(\zeta_5, 5^{1/5})$:
@@ -8708,6 +10001,11 @@ x^20 + 25*x^10 + 5)
 %8 = Mod(1/11*x^14 + 29/11*x^4, x^20 + 25*x^10 + 5)
 ? a^5 - 5
 %9 = 0
+ at eprog\noindent In the above example, $x^5-5$ and the $5$-th cyclotomic
+polynomial are irreducible over $\Q$; they have coprime degrees so
+define linearly disjoint extensions and we could have started by
+\bprog
+? [R,a] = polcompositum(x^5 - 5, polcyclo(5), 3); \\@com $[R,a,b,k]$
 @eprog
 
 The library syntax is \fun{GEN}{polcompositum0}{GEN P, GEN Q, long flag}.
@@ -9318,7 +10616,7 @@ an (absolute) ideal with respect to the $\Z$-basis \kbd{Labs.zk}, then
   rnfidealabstorel(rnf, Labs.zk * m)
 @eprog\noindent converts $m$ to a relative ideal.
 \bprog
-? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); Labs = nfinit(L.pol);
+? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); Labs = nfinit(L);
 ? m = idealhnf(Labs, 17, x^3+2);
 ? B = rnfidealabstorel(L, Labs.zk * m)
 %3 = [[1, 8; 0, 1], [[17, 4; 0, 1], 1]]  \\ pseudo-basis for m as Z_K-module
@@ -9451,6 +10749,14 @@ $r_1$ and $r_2$ the number of real and complex places of $K$. Access to this
 information via \emph{member functions} is preferred since the specific
 data organization specified below will change in the future.
 
+Note that a subsequent \kbd{nfinit}$(\var{rnf})$ will explicitly add an
+\var{nf} structure associated to $L$ to \var{rnf} (and return it as well).
+This is likely to be very expensive if the absolute degree $mn$ is large,
+but fixes an integer basis for $\Z_L$ as a $\Z$-module and allows to input
+and output elements of $L$ in absolute form: as \typ{COL} for elements,
+as \typ{MAT} in HNF for ideals, as \kbd{prid} for prime ideals. Without such
+a call, elements of $L$ are represented as \typ{POLMOD}, etc.
+
 $\var{rnf}[1]$(\kbd{rnf.pol}) contains the relative polynomial \var{pol}.
 
 $\var{rnf}[2]$ contains the integer basis $[A,d]$ of $K$, as
@@ -9483,8 +10789,9 @@ $\var{rnf}[9]$ is currently unused.
 
 $\var{rnf}[10]$ (\kbd{rnf.nf}) is $\var{nf}$.
 
-$\var{rnf}[11]$ is the output of \kbd{rnfequation(K, pol, 1)}. Namely, a
-vector $[P, a, k]$ describing the \emph{absolute} extension
+$\var{rnf}[11]$ is an extension of \kbd{rnfequation(K, pol, 1)}. Namely, a
+vector $[P, a, k, \kbd{K.pol}, \kbd{pol}]$ describing the \emph{absolute}
+extension
 $L/\Q$: $P$ is an absolute equation, more conveniently obtained
 as \kbd{rnf.polabs}; $a$ expresses the generator $\alpha = y \mod \kbd{K.pol}$
 of the number field $K$ as an element of $L$, i.e.~a polynomial modulo the
@@ -9493,7 +10800,7 @@ absolute equation $P$;
 $k$ is a small integer such that, if $\beta$ is an abstract root of \var{pol}
 and $\alpha$ the generator of $K$ given above, then $P(\beta + k\alpha) = 0$.
 
-\misctitle{Caveat.} Be careful if $k\neq0$ when dealing simultaneously with
+\misctitle{Caveat} Be careful if $k\neq0$ when dealing simultaneously with
 absolute and relative quantities since $L = \Q(\beta + k\alpha) =
 K(\alpha)$, and the generator chosen for the absolute extension is not the
 same as for the relative one. If this happens, one can of course go on
@@ -9625,7 +10932,9 @@ to be a multiple of the conductor (i.e.~\var{pol} defines a subextension of
 bnr). The result is the HNF defining the norm group on the given generators
 of \kbd{bnr.gen}. Note that neither the fact that \var{pol} defines an
 Abelian extension nor the fact that the module is a multiple of the conductor
-is checked. The result is undefined if the assumption is not correct.
+is checked. The result is undefined if the assumption is not correct,
+but the function will return the empty matrix \kbd{[;]} if it detects a
+problem; it may also not detect the problem and return a wrong result.
 
 The library syntax is \fun{GEN}{rnfnormgroup}{GEN bnr, GEN pol}.
 
@@ -9867,6 +11176,1212 @@ too many terms (if the discriminant of the number field is too large).
 The library syntax is \fun{GEN}{initzeta}{GEN bnf, long prec}.
 %SECTION: number_fields
 
+\section{Functions related to associative and central simple algebras}
+
+This section collects functions related to associative algebras and central
+simple algebras over number fields. Let $A$ be a finite-dimensional unitary
+associative algebra over a field $K$. We say that $A$ is \emph{central} if
+the center of $A$ is $K$, and that $A$ is \emph{simple} if it has no
+nontrivial two-sided ideals.
+
+\par We provide functions to manipulate associative algebras of finite
+dimension over~$\Q$ or~$\F_p$. We represent them by the left multiplication
+table on a basis over the prime subfield. The function \kbd{algtableinit}
+creates the object representing an associative algebra. We also provide
+functions to manipulate central simple algebras over number fields. We
+represent them either by the left multiplication table on a basis over the
+center, or by a cyclic algebra (see below). The function~\kbd{alginit} creates
+the object representing a central simple algebra.
+
+\par The set of elements of an algebra~$A$ that annihilate every simple left
+$A$-module is a two-sided ideal, called the \emph{Jacobson radical} of~$A$.
+An algebra is \emph{semisimple} if its Jacobson radical is trivial. A
+semisimple algebra is isomorphic to a direct sum of simple algebras. The
+dimension of a central simple algebra~$A$ over $K$ is always a square $d^2$,
+and the integer $d$ is called the \emph{degree} of the algebra~$A$ over~$K$.
+A central simple algebra~$A$ over a field~$K$ is always isomorphic to~$M_d(D)$
+for some integer~$d$ and some central division algebra~$D$ of degree~$e$ : the
+integer~$e$ is called the \emph{index} of~$A$.
+
+\par Let $L/K$ be a cyclic extension of degree $d$, let $\sigma$ be a
+generator of $\text{Gal}(L/K)$ and let $b\in K^*$. Then the \emph{cyclic
+algebra} $(L/K,\sigma,b)$ is the algebra $\bigoplus_{i=0}^{d-1}x^iL$ with
+$x^d=b$ and $\ell x=x\sigma(\ell)$ for all~$\ell\in L$. The algebra
+$(L/K,\sigma,b)$ is a central simple $K$-algebra of degree~$d$, and it is an
+$L$-vector space. Left multiplication is $L$-linear and induces a $K$-algebra
+homomorphism $(L/K,\sigma,b)\to M_d(L)$.
+
+\par Let $K$ be a nonarchimedean local field with uniformizer $\pi$, and let
+$L/K$ be the unique unramified extension of degree $d$. Then every central
+simple algebra $A$ of degree $d$ over $K$ is isomorphic to
+$(L/K,\text{Frob},\pi^h)$ for some integer $h$. The element $h/d\in
+(1/d)\Z/\Z\subset\Q/\Z$ is called the \emph{Hasse invariant} of $A$.
+
+\par Let~$A$ be an algebra of finite dimension over~$\Q$. An \emph{order}
+in~$A$ is a finitely generated $\Z$-submodule~${\cal O}$ such that~$\Q{\cal
+O} = A$, that is also a subring with unit. We define natural orders in
+central simple algebras defined by a cyclic algebra or by a multiplication
+table over the center. Let~$A = (L/K,\sigma,b) = \bigoplus_{i=0}^{d-1}x^iL$
+be a cyclic algebra over a number field~$K$ of degree~$n$ with ring of
+integers~$\Z_K$. Let~$\Z_L$ be the ring of integers of~$L$, and assume
+that~$b$ is integral. Then the submodule~${\cal O} =
+\bigoplus_{i=0}^{d-1}x^i\Z_L$ is an order in~$A$, called the \emph{natural
+order}. Let~$\omega_0,\dots,\omega_{nd-1}$ be a~$\Z$-basis of~$\Z_L$. The
+\emph{natural basis} of~${\cal O}$ is~$b_0,\dots,b_{nd^2-1}$ where~$b_i =
+x^{i/(nd)}\omega_{(i \mod nd)}$. Now let~$A$ be a central simple algebra of
+degree~$d$ over a number field~$K$ of degree~$n$ with ring of
+integers~$\Z_K$. Let~$e_0,\dots,e_{d^2-1}$ be a basis of~$A$ over~$K$ and
+assume that the left multiplication table of~$A$ on~$(e_i)$ is integral. Then
+the submodule~${\cal O} = \bigoplus_{i=0}^{d^2-1}\Z_K e_i$ is an order
+in~$A$, called the \emph{natural order}. Let~$\omega_0,\dots,\omega_{n-1}$ be
+a~$\Z$-basis of~$\Z_K$. The \emph{natural basis} of~${\cal O}$
+is~$b_0,\dots,b_{nd^2-1}$ where~$b_i = \omega_{(i \mod n)}e_{i/n}$.
+
+\par As with number fields, we represent elements of central simple algebras
+in two ways, called the \emph{algebraic representation} and the \emph{basis
+representation}, and you can convert betweeen the two with the functions
+\kbd{algalgtobasis} and \kbd{algbasistoalg}. In every central simple algebra
+object, we store a~$\Z$-basis of an order~${\cal O}_0$, and the basis
+representation is simply a \typ{COL} with coefficients in~$\Q$ expressing the
+element in that basis. If no maximal order was computed, then~${\cal O}_0$ is
+the natural order. If a maximal order was computed, then~${\cal O}_0$ is a
+maximal order containing the natural order. For a cyclic algebra~$A =
+(L/K,\sigma,b)$, the algebraic representation is a \typ{COL} with coefficients
+in~$L$ representing the element in the decomposition~$A =
+\bigoplus_{i=0}^{d-1}x^iL$. For a central simple algebra defined by a
+multiplication table over its center~$K$ on a basis~$(e_i)$, the algebraic
+representation is a \typ{COL} with coefficients in~$K$ representing the element
+on the basis~$(e_i)$.
+
+\misctitle{Warning} The coefficients in the decomposition~$A =
+\bigoplus_{i=0}^{d-1}x^iL$ are not the same as those in the decomposition~$A
+= \bigoplus_{i=0}^{d-1}Lx^i$! The $i$-th coefficients are related by
+conjugating by~$x^i$, which on~$L$ amounts to acting by~$\sigma^i$.
+
+
+\subsec{algabsdim$(\var{al})$}\kbdsidx{algabsdim}\label{se:algabsdim}
+Given an algebra \var{al} output by \tet{alginit} or by
+\tet{algtableinit}, returns the dimension of \var{al} over its prime subfield
+($\Q$ or $\F_p$).
+\bprog
+? nf = nfinit(y^3-y+1);
+? A = alginit(nf, [-1,-1]);
+? algabsdim(A)
+%3 = 12
+ at eprog
+
+The library syntax is \fun{long}{algabsdim}{GEN al}.
+
+\subsec{algadd$(\var{al},x,y)$}\kbdsidx{algadd}\label{se:algadd}
+Given two elements $x$ and $y$ in \var{al}, computes their sum $x+y$ in
+the algebra~\var{al}.
+\bprog
+? A = alginit(nfinit(y),[-1,1]);
+? algadd(A,[1,0]~,[1,2]~)
+%2 = [2, 2]~
+ at eprog
+
+Also accepts matrices with coefficients in \var{al}.
+
+The library syntax is \fun{GEN}{algadd}{GEN al, GEN x, GEN y}.
+
+\subsec{algalgtobasis$(\var{al},x)$}\kbdsidx{algalgtobasis}\label{se:algalgtobasis}
+Given an element \var{x} in the central simple algebra \var{al} output
+by \tet{alginit}, transforms it to a column vector on the integral basis of
+\var{al}. This is the inverse function of \tet{algbasistoalg}.
+\bprog
+? A = alginit(nfinit(y^2-5),[2,y]);
+? algalgtobasis(A,[y,1]~)
+%2 = [0, 2, 0, -1, 2, 0, 0, 0]~
+? algbasistoalg(A,algalgtobasis(A,[y,1]~))
+%3 = [Mod(Mod(y, y^2 - 5), x^2 - 2), 1]~
+ at eprog
+
+The library syntax is \fun{GEN}{algalgtobasis}{GEN al, GEN x}.
+
+\subsec{algaut$(\var{al})$}\kbdsidx{algaut}\label{se:algaut}
+Given a cyclic algebra $\var{al} = (L/K,\sigma,b)$ output by
+\tet{alginit}, returns the automorphism $\sigma$.
+\bprog
+? nf = nfinit(y);
+? p = idealprimedec(nf,7)[1];
+? p2 = idealprimedec(nf,11)[1];
+? A = alginit(nf,[3,[[p,p2],[1/3,2/3]],[0]]);
+? algaut(A)
+%5 = -1/3*x^2 + 1/3*x + 26/3
+ at eprog
+
+The library syntax is \fun{GEN}{algaut}{GEN al}.
+
+\subsec{algb$(\var{al})$}\kbdsidx{algb}\label{se:algb}
+Given a cyclic algebra $\var{al} = (L/K,\sigma,b)$ output by
+\tet{alginit}, returns the element $b\in K$.
+\bprog
+nf = nfinit(y);
+? p = idealprimedec(nf,7)[1];
+? p2 = idealprimedec(nf,11)[1];
+? A = alginit(nf,[3,[[p,p2],[1/3,2/3]],[0]]);
+? algb(A)
+%5 = Mod(-77, y)
+ at eprog
+
+The library syntax is \fun{GEN}{algb}{GEN al}.
+
+\subsec{algbasis$(\var{al})$}\kbdsidx{algbasis}\label{se:algbasis}
+Given an central simple algebra \var{al} output by \tet{alginit}, returns
+a $\Z$-basis of the order~${\cal O}_0$ stored in \var{al} with respect to the
+natural order in \var{al}. It is a maximal order if one has been computed.
+\bprog
+A = alginit(nfinit(y), [-1,-1]);
+? algbasis(A)
+%2 =
+[1 0 0 1/2]
+
+[0 1 0 1/2]
+
+[0 0 1 1/2]
+
+[0 0 0 1/2]
+ at eprog
+
+The library syntax is \fun{GEN}{algbasis}{GEN al}.
+
+\subsec{algbasistoalg$(\var{al},x)$}\kbdsidx{algbasistoalg}\label{se:algbasistoalg}
+Given an element \var{x} in the central simple algebra \var{al} output
+by \tet{alginit}, transforms it to its algebraic representation in \var{al}.
+This is the inverse function of \tet{algalgtobasis}.
+\bprog
+? A = alginit(nfinit(y^2-5),[2,y]);
+? z = algbasistoalg(A,[0,1,0,0,2,-3,0,0]~);
+? liftall(z)
+%3 = [(-1/2*y - 2)*x + (-1/4*y + 5/4), -3/4*y + 7/4]~
+? algalgtobasis(A,z)
+%4 = [0, 1, 0, 0, 2, -3, 0, 0]~
+ at eprog
+
+The library syntax is \fun{GEN}{algbasistoalg}{GEN al, GEN x}.
+
+\subsec{algcenter$(\var{al})$}\kbdsidx{algcenter}\label{se:algcenter}
+If \var{al} is a table algebra output by \tet{algtableinit}, returns a
+basis of the center of the algebra~\var{al} over its prime field ($\Q$ or
+$\F_p$). If \var{al} is a central simple algebra output by \tet{alginit},
+returns the center of~\var{al}, which is stored in \var{al}.
+
+A simple example: the $2\times 2$ upper triangular matrices over $\Q$,
+generated by $I_2$, $a = \kbd{[0,1;0,0]}$ and $b = \kbd{[0,0;0,1]}$,
+such that $a^2 = 0$, $ab = a$, $ba = 0$, $b^2 = b$: the diagonal matrices
+for the center.
+\bprog
+? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
+? A = algtableinit(mt);
+? algcenter(A) \\ = (I_2)
+%3 =
+[1]
+
+[0]
+
+[0]
+ at eprog
+
+An example in the central simple case:
+
+\bprog
+? nf = nfinit(y^3-y+1);
+? A = alginit(nf, [-1,-1]);
+? algcenter(A).pol
+%3 = y^3 - y + 1
+ at eprog
+
+The library syntax is \fun{GEN}{gp_algcenter}{GEN al}.
+
+\subsec{algcentralproj$(\var{al},z,\{\var{maps}=0\})$}\kbdsidx{algcentralproj}\label{se:algcentralproj}
+Given a table algebra \var{al} output by \tet{algtableinit} and a
+\typ{VEC} $\var{z}=[z_1,\dots,z_n]$ of orthogonal central idempotents,
+returns a \typ{VEC} $[al_1,\dots,al_n]$ of algebras such that
+$al_i = z_i\, al$. If $\var{maps}=1$, each $al_i$ is a \typ{VEC}
+$[quo,proj,lift]$ where \var{quo} is the quotient algebra, \var{proj} is a
+\typ{MAT} representing the projection onto this quotient and \var{lift} is a
+\typ{MAT} representing a lift.
+
+A simple example: $\F_2\oplus \F_4$, generated by~$1=(1,1)$, $e=(1,0)$
+and~$x$ such that~$x^2+x+1=0$. We have~$e^2=e$, $x^2=x+1$ and~$ex=0$.
+\bprog
+? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+? A = algtableinit(mt,2);
+? e = [0,1,0]~;
+? e2 = algsub(A,[1,0,0]~,e);
+? [a,a2] = algcentralproj(A,[e,e2]);
+? algdim(a)
+%6 = 1
+? algdim(a2)
+%7 = 2
+ at eprog
+
+The library syntax is \fun{GEN}{alg_centralproj}{GEN al, GEN z, long maps}.
+
+\subsec{algchar$(\var{al})$}\kbdsidx{algchar}\label{se:algchar}
+Given an algebra \var{al} output by \tet{alginit} or \tet{algtableinit},
+returns the characteristic of \var{al}.
+\bprog
+? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+? A = algtableinit(mt,13);
+? algchar(A)
+%3 = 13
+ at eprog
+
+The library syntax is \fun{GEN}{algchar}{GEN al}.
+
+\subsec{algcharpoly$(\var{al},b,\{v='x\})$}\kbdsidx{algcharpoly}\label{se:algcharpoly}
+Given an element $b$ in \var{al}, returns its characteristic polynomial
+as a polynomial in the variable $v$. If \var{al} is a table algebra output
+by \tet{algtableinit}, returns the absolute characteristic polynomial of
+\var{b}, which is an element of $\F_p[v]$ or~$\Q[v]$; if \var{al} is a
+central simple algebra output by \tet{alginit}, returns the reduced
+characteristic polynomial of \var{b}, which is an element of $K[v]$ where~$K$
+is the center of \var{al}.
+\bprog
+? al = alginit(nfinit(y), [-1,-1]); \\ (-1,-1)_Q
+? algcharpoly(al, [0,1]~)
+%2 = x^2 + 1
+ at eprog
+
+Also accepts a square matrix with coefficients in \var{al}.
+
+The library syntax is \fun{GEN}{algcharpoly}{GEN al, GEN b, long v = -1}, where \kbd{v} is a variable number.
+
+\subsec{algdecomposition$(\var{al})$}\kbdsidx{algdecomposition}\label{se:algdecomposition}
+\var{al} being a table algebra output by \tet{algtableinit}, returns
+$[J,[al_1,\dots,al_n]]$ where $J$ is a basis of the Jacobson radical of
+\var{al} and $al_1,\dots,al_n$ are the simple factors of the semisimple
+algebra $al/J$.
+
+The library syntax is \fun{GEN}{alg_decomposition}{GEN al}.
+
+\subsec{algdegree$(\var{al})$}\kbdsidx{algdegree}\label{se:algdegree}
+Given a central simple algebra \var{al} output by \tet{alginit}, returns
+the degree of \var{al}.
+\bprog
+? nf = nfinit(y^3-y+1);
+? A = alginit(nf, [-1,-1]);
+? algdegree(A)
+%3 = 2
+ at eprog
+
+The library syntax is \fun{long}{algdegree}{GEN al}.
+
+\subsec{algdim$(\var{al})$}\kbdsidx{algdim}\label{se:algdim}
+Given a central simple algebra \var{al} output by \tet{alginit}, returns
+the dimension of \var{al} over its center. Given a table algebra \var{al}
+output by \tet{algtableinit}, returns the dimension of \var{al} over its prime
+subfield ($\Q$ or $\F_p$).
+\bprog
+? nf = nfinit(y^3-y+1);
+? A = alginit(nf, [-1,-1]);
+? algdim(A)
+%3 = 4
+ at eprog
+
+The library syntax is \fun{long}{algdim}{GEN al}.
+
+\subsec{algdisc$(\var{al})$}\kbdsidx{algdisc}\label{se:algdisc}
+Given a central simple algebra \var{al} output by \tet{alginit}, computes
+the discriminant of the order ${\cal O}_0$ stored in \var{al}, that is the
+determinant of the trace form $\rm{Tr} : {\cal O}_0\times {\cal O}_0 \to \Z$.
+\bprog
+? nf = nfinit(y^2-5);
+? A = alginit(nf, [-3,1-y]);
+? [PR,h] = alghassef(A);
+%3 = [[[2, [2, 0]~, 1, 2, 1], [3, [3, 0]~, 1, 2, 1]], Vecsmall([0, 1])]
+? n = algdegree(A);
+? D = algabsdim(A);
+? h = vector(#h, i, n - gcd(n,h[i]));
+? n^D * nf.disc^(n^2) * idealnorm(nf, idealfactorback(nf,PR,h))^n
+%4 = 12960000
+? algdisc(A)
+%5 = 12960000
+ at eprog
+
+The library syntax is \fun{GEN}{algdisc}{GEN al}.
+
+\subsec{algdivl$(\var{al},x,y)$}\kbdsidx{algdivl}\label{se:algdivl}
+Given two elements $x$ and $y$ in \var{al}, computes their left quotient
+$x\backslash y$ in the algebra \var{al}. Assumes that $y$ is left divisible
+by $x$. Also accepts matrices with coefficients in \var{al}.
+
+The library syntax is \fun{GEN}{algdivl}{GEN al, GEN x, GEN y}.
+
+\subsec{algdivr$(\var{al},x,y)$}\kbdsidx{algdivr}\label{se:algdivr}
+Given two elements $x$ and $y$ in \var{al}, computes their right quotient
+$x/y$ in the algebra \var{al}. Assumes that $y$ is invertible. Also accepts
+matrices with coefficients in \var{al}.
+
+The library syntax is \fun{GEN}{algdivr}{GEN al, GEN x, GEN y}.
+
+\subsec{alghasse$(\var{al},\var{pl})$}\kbdsidx{alghasse}\label{se:alghasse}
+Given a central simple algebra \var{al} output by \tet{alginit} and a prime
+ideal or an integer between $1$ and $r_1+r_2$, returns a \typ{FRAC} $h$ : the
+local Hasse invariant of \var{al} at the place specified by \var{pl}.
+\bprog
+? nf = nfinit(y^2-5);
+? A = alginit(nf, [-1,y]);
+? alghasse(A, 1)
+%3 = 1/2
+? alghasse(A, 2)
+%4 = 0
+? alghasse(A, idealprimedec(nf,2)[1])
+%5 = 1/2
+? alghasse(A, idealprimedec(nf,5)[1])
+%6 = 0
+ at eprog
+
+The library syntax is \fun{GEN}{alghasse}{GEN al, GEN pl}.
+
+\subsec{alghassef$(\var{al})$}\kbdsidx{alghassef}\label{se:alghassef}
+Given a central simple algebra \var{al} output by \tet{alginit}, returns
+a \typ{VEC} $[\kbd{PR}, h_f]$ describing the local Hasse invariants at the
+finite places of the center: \kbd{PR} is a \typ{VEC} of primes and $h_f$ is a
+\typ{VECSMALL} of integers modulo the degree $d$ of \var{al}.
+\bprog
+? nf = nfinit(y^2-5);
+? A = alginit(nf, [-1,2*y-1]);
+? [PR,hf] = alghassef(A);
+? PR
+%4 = [[19, [10, 2]~, 1, 1, [-8, 2; 2, -10]], [2, [2, 0]~, 1, 2, 1]]
+? hf
+%5 = Vecsmall([1, 0])
+ at eprog
+
+The library syntax is \fun{GEN}{alghassef}{GEN al}.
+
+\subsec{alghassei$(\var{al})$}\kbdsidx{alghassei}\label{se:alghassei}
+Given a central simple algebra \var{al} output by \tet{alginit}, returns
+a \typ{VECSMALL} $h_i$ of $r_1$ integers modulo the degree $d$ of \var{al},
+where $r_1$ is the number of real places of the center: the local Hasse
+invariants of \var{al} at infinite places.
+\bprog
+? nf = nfinit(y^2-5);
+? A = alginit(nf, [-1,y]);
+? alghassei(A)
+%3 = Vecsmall([1, 0])
+ at eprog
+
+The library syntax is \fun{GEN}{alghassei}{GEN al}.
+
+\subsec{algindex$(\var{al},\{\var{pl}\})$}\kbdsidx{algindex}\label{se:algindex}
+Return the index of the central simple algebra~$A$ over~$K$ (as output by
+alginit), that is the degree~$e$ of the unique central division algebra~$D$
+over $K$ such that~$A$ is isomorphic to some matrix algebra~$M_d(D)$. If
+\var{pl} is set, it should be a prime ideal of~$K$ or an integer between~$1$
+and~$r_1+r_2$, and in that case return the local index at the place \var{pl}
+instead.
+
+\bprog
+? nf = nfinit(y^2-5);
+? A = alginit(nf, [-1,y]);
+? algindex(A, 1)
+%3 = 2
+? algindex(A, 2)
+%4 = 1
+? algindex(A, idealprimedec(nf,2)[1])
+%5 = 2
+? algindex(A, idealprimedec(nf,5)[1])
+%6 = 1
+? algindex(A)
+%7 = 2
+ at eprog
+
+The library syntax is \fun{long}{algindex}{GEN al, GEN pl = NULL}.
+
+\subsec{alginit$(B, C, \{v\}, \{\fl = 1\})$}\kbdsidx{alginit}\label{se:alginit}
+Initialize the central simple algebra defined by data $B$, $C$ and
+variable $v$, as follows.
+
+\item (multiplication table) $B$ is the base number field $K$ in \tet{nfinit}
+form, $C$ is a ``multiplication table'' over $K$.
+As a $K$-vector space, the algebra is generated by a basis
+$(e_1 = 1,\dots, e_n)$; the table is given as a \typ{VEC} of $n$ matrices in
+$M_n(K)$, giving the left multiplication by the basis elements $e_i$, in the
+given basis.
+Assumes that $e_1= 1$, that the multiplication table is integral, and that
+$K[e_1,\dots,e_n]$ describes a central simple algebra over $K$; $v$ and $\fl$
+are ignored.
+\bprog
+{ m_i = [0,-1,0, 0;
+         1, 0,0, 0;
+         0, 0,0,-1;
+         0, 0,1, 0];
+  m_j = [0, 0,-1,0;
+         0, 0, 0,1;
+         1, 0, 0,0;
+         0,-1, 0,0];
+  m_k = [0, 0, 0, 0;
+         0, 0,-1, 0;
+         0, 1, 0, 0;
+         1, 0, 0,-1];
+  A = alginit(nfinit(y), [matid(4), m_i,m_j,m_k],  0); }
+ at eprog represents (in a complicated way) the quaternion algebra $(-1,-1)_\Q$.
+See below for a simpler solution.
+
+\item (cyclic algebra) $B$ is an \var{rnf} structure associated with a cyclic
+number field extension $L/K$ of degree $d$, $C$ is a \typ{VEC}
+\kbd{[sigma,b]} with 2 components: \kbd{sigma} is a \typ{POLMOD} representing
+an automorphism generating $\text{Gal}(L/K)$, $b$ is an element in $K^*$. This
+represents the cyclic algebra~$(L/K,\sigma,b)$. Currently the element $b$ has
+to be integral.
+\bprog
+ ? Q = nfinit(y); T = polcyclo(5, 'x); F = rnfinit(Q, T);
+ ? A = alginit(F, [Mod(x^2,T), 3]);
+ at eprog defines the cyclic algebra $(L/\Q, \sigma, 3)$, where
+$L = \Q(\zeta_5)$ and $\sigma:\zeta\mapsto\zeta^2$ generates
+$\text{Gal}(L/\Q)$.
+
+\item (quaternion algebra, special case of the above) $B$ is an \var{nf}
+structure associated with a number field $K$, $C = [a,b]$ is a vector
+containing two elements of $K^*$ with $a$ not a square in $K$, returns the quaternion algebra $(a,b)_K$.
+The variable $v$ (\kbd{'x} by default) must have higher priority than the
+variable of $K$\kbd{.pol} and is used to represent elements in the splitting
+field $L = K[x]/(x^2-a)$.
+\bprog
+ ? Q = nfinit(y); A = alginit(Q, [-1,-1]);  \\@com $(-1,-1)_\Q$
+ at eprog
+
+\item (algebra/$K$ defined by local Hasse invariants)
+$B$ is an \var{nf} structure associated with a number field $K$,
+$C = [d, [\kbd{PR},h_f], h_i]$ is a triple
+containing an integer $d > 1$, a pair $[\kbd{PR}, h_f]$ describing the
+Hasse invariants at finite places, and $h_i$ the Hasse invariants
+at archimedean (real) places. A local Hasse invariant belongs to $(1/d)\Z/\Z
+\subset \Q/\Z$, and is given either as a \typ{FRAC} (lift to $(1/d)\Z$),
+a \typ{INT} or \typ{INTMOD} modulo $d$ (lift to $\Z/d\Z$); a whole vector
+of local invariants can also be given as a \typ{VECSMALL}, whose
+entries are handled as \typ{INT}s. \kbd{PR} is a list of prime ideals
+(\var{prid} structures), and $h_f$ is a vector of the same length giving the
+local invariants at those maximal ideals. The invariants at infinite real
+places are indexed by the real roots $K$\kbd{.roots}: if the Archimedean
+place $v$ is associated with the $j$-th root, the value of
+$h_v$ is given by $h_i[j]$, must be $0$ or $1/2$ (or~$d/2$ modulo~$d$), and
+can be nonzero only if~$d$ is even.
+
+By class field theory, provided the local invariants $h_v$ sum to $0$, up
+to Brauer equivalence, there is a unique central simple algebra over $K$
+with given local invariants and trivial invariant elsewhere. In particular,
+up to isomorphism, there is a unique such algebra $A$ of degree $d$.
+
+We realize $A$ as a cyclic algebra through class field theory. The variable $v$
+(\kbd{'x} by default) must have higher priority than the variable of
+$K$\kbd{.pol} and is used to represent elements in the (cyclic) splitting
+field extension $L/K$ for $A$.
+
+\bprog
+ ? nf = nfinit(y^2+1);
+ ? PR = idealprimedec(nf,5); #PR
+ %2 = 2
+ ? hi = [];
+ ? hf = [PR, [1/3,-1/3]];
+ ? A = alginit(nf, [3,hf,hi]);
+ ? algsplittingfield(A).pol
+ %6 = x^3 - 21*x + 7
+ at eprog
+
+\item (matrix algebra, toy example) $B$ is an \var{nf} structure associated
+to a number field $K$, $C = d$ is a positive integer. Returns a cyclic
+algebra isomorphic to the matrix algebra $M_d(K)$.
+
+In all cases, this function computes a maximal order for the algebra by default,
+which may require a lot of time. Setting $\fl = 0$ prevents this computation.
+
+The pari object representing such an algebra $A$ is a \typ{VEC} with the
+following data:
+
+ \item A splitting field $L$ of $A$ of the same degree over $K$ as $A$, in
+\kbd{rnfinit} format, accessed with \kbd{algsplittingfield}.
+
+ \item The same splitting field $L$ in \kbd{nfinit} format.
+
+ \item The Hasse invariants at the real places of $K$, accessed with
+\kbd{alghassei}.
+
+ \item The Hasse invariants of $A$ at the finite primes of $K$ that ramify in
+the natural order of $A$, accessed with \kbd{alghassef}.
+
+ \item A basis of an order ${\cal O}_0$ expressed on the basis of the natural
+order, accessed with \kbd{algord}.
+
+ \item A basis of the natural order expressed on the basis of ${\cal O}_0$,
+accessed with \kbd{alginvord}.
+
+ \item The left multiplication table of ${\cal O}_0$ on the previous basis,
+accessed with \kbd{algmultable}.
+
+ \item The characteristic of $A$ (always $0$), accessed with \kbd{algchar}.
+
+ \item The absolute traces of the elements of the basis of ${\cal O}_0$.
+
+ \item If $A$ was constructed as a cyclic algebra~$(L/K,\sigma,b)$ of degree
+$d$, a \typ{VEC} $[\sigma,\sigma^2,\dots,\sigma^{d-1}]$. The function
+\kbd{algaut} returns $\sigma$.
+
+ \item If $A$ was constructed as a cyclic algebra~$(L/K,\sigma,b)$, the
+element $b$, accessed with \kbd{algb}.
+
+ \item If $A$ was constructed with its multiplication table $mt$ over $K$,
+the \typ{VEC} of \typ{MAT} $mt$, accessed with \kbd{algrelmultable}.
+
+ \item If $A$ was constructed with its multiplication table $mt$ over $K$,
+a \typ{VEC} with three components: a \typ{COL} representing an element of $A$
+generating the splitting field $L$ as a maximal subfield of $A$, a \typ{MAT}
+representing an $L$-basis ${\cal B}$ of $A$ expressed on the $\Z$-basis of
+${\cal O}_0$, and a \typ{MAT} representing the $\Z$-basis of ${\cal O}_0$
+expressed on ${\cal B}$. This data is accessed with \kbd{algsplittingdata}.
+
+The library syntax is \fun{GEN}{alginit}{GEN B, GEN C, long v = -1, long flag }, where \kbd{v} is a variable number.
+
+\subsec{alginv$(\var{al},x)$}\kbdsidx{alginv}\label{se:alginv}
+Given an element $x$ in \var{al}, computes its inverse $x^{-1}$ in the
+algebra \var{al}. Assumes that $x$ is invertible.
+\bprog
+? A = alginit(nfinit(y), [-1,-1]);
+? alginv(A,[1,1,0,0]~)
+%2 = [1/2, 1/2, 0, 0]~
+ at eprog
+
+Also accepts matrices with coefficients in \var{al}.
+
+The library syntax is \fun{GEN}{alginv}{GEN al, GEN x}.
+
+\subsec{alginvbasis$(\var{al})$}\kbdsidx{alginvbasis}\label{se:alginvbasis}
+Given an central simple algebra \var{al} output by \tet{alginit}, returns
+a $\Z$-basis of the natural order in \var{al} with respect to the order~${\cal
+O}_0$ stored in \var{al}.
+\bprog
+A = alginit(nfinit(y), [-1,-1]);
+? alginvbasis(A)
+%2 =
+[1 0 0 -1]
+
+[0 1 0 -1]
+
+[0 0 1 -1]
+
+[0 0 0  2]
+ at eprog
+
+The library syntax is \fun{GEN}{alginvbasis}{GEN al}.
+
+\subsec{algisassociative$(\var{mt},p=0)$}\kbdsidx{algisassociative}\label{se:algisassociative}
+Returns 1 if the multiplication table \kbd{mt} is suitable for
+\kbd{algtableinit(mt,p)}, 0 otherwise. More precisely, \kbd{mt} should be
+a \typ{VEC} of $n$ matrices in $M_n(K)$, giving the left multiplications
+by the basis elements $e_1, \dots, e_n$ (structure constants).
+We check whether the first basis element $e_1$ is $1$ and $e_i(e_je_k) =
+(e_ie_j)e_k$ for all $i,j,k$.
+\bprog
+ ? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
+ ? algisassociative(mt)
+ %2 = 1
+ at eprog
+
+May be used to check a posteriori an algebra: we also allow \kbd{mt} as
+output by \tet{algtableinit} ($p$ is ignored in this case).
+
+The library syntax is \fun{GEN}{algisassociative}{GEN mt, GEN p}.
+
+\subsec{algiscommutative$(\var{al})$}\kbdsidx{algiscommutative}\label{se:algiscommutative}
+\var{al} being a table algebra output by \tet{algtableinit} or a central
+simple algebra output by \tet{alginit}, tests whether the algebra \var{al} is
+commutative.
+\bprog
+? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
+? A = algtableinit(mt);
+? algiscommutative(A)
+%3 = 0
+? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+? A = algtableinit(mt,2);
+? algiscommutative(A)
+%6 = 1
+ at eprog
+
+The library syntax is \fun{GEN}{algiscommutative}{GEN al}.
+
+\subsec{algisdivision$(\var{al},\{\var{pl}\})$}\kbdsidx{algisdivision}\label{se:algisdivision}
+Given a central simple algebra \var{al} output by \tet{alginit}, test
+whether \var{al} is a division algebra. If \var{pl} is set, it should be a
+prime ideal of~$K$ or an integer between~$1$ and~$r_1+r_2$, and in that case
+test whether \var{al} is locally a division algebra at the place \var{pl}
+instead.
+
+\bprog
+? nf = nfinit(y^2-5);
+? A = alginit(nf, [-1,y]);
+? algisdivision(A, 1)
+%3 = 1
+? algisdivision(A, 2)
+%4 = 0
+? algisdivision(A, idealprimedec(nf,2)[1])
+%5 = 1
+? algisdivision(A, idealprimedec(nf,5)[1])
+%6 = 0
+? algisdivision(A)
+%7 = 1
+ at eprog
+
+The library syntax is \fun{GEN}{algisdivision}{GEN al, GEN pl = NULL}.
+
+\subsec{algisinv$(\var{al},x,\{\&\var{ix}\})$}\kbdsidx{algisinv}\label{se:algisinv}
+Given an element $x$ in \var{al}, tests whether $x$ is invertible, and sets
+$ix$ to the inverse of $x$.
+\bprog
+? A = alginit(nfinit(y), [-1,1]);
+? algisinv(A,[-1,1]~)
+%2 = 0
+? algisinv(A,[1,2]~,&ix)
+%3 = 1
+? ix
+%4 = [Mod(Mod(-1/3, y), x^2 + 1), Mod(Mod(2/3, y), x^2 + 1)]~
+ at eprog
+
+Also accepts matrices with coefficients in \var{al}.
+
+The library syntax is \fun{GEN}{algisinv}{GEN al, GEN x, GEN *ix = NULL}.
+
+\subsec{algissemisimple$(\var{al})$}\kbdsidx{algissemisimple}\label{se:algissemisimple}
+\var{al} being a table algebra output by \tet{algtableinit} or a central
+simple algebra output by \tet{alginit}, tests whether the algebra \var{al} is
+semisimple.
+\bprog
+? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
+? A = algtableinit(mt);
+? algissemisimple(A)
+%3 = 0
+? m_i=[0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0]; \\quaternion algebra (-1,-1)
+? m_j=[0,0,-1,0;0,0,0,1;1,0,0,0;0,-1,0,0];
+? m_k=[0,0,0,-1;0,0,-1,0;0,1,0,0;1,0,0,0];
+? mt = [matid(4), m_i, m_j, m_k];
+? A = algtableinit(mt);
+? algissemisimple(A)
+%9 = 1
+ at eprog
+
+The library syntax is \fun{GEN}{algissemisimple}{GEN al}.
+
+\subsec{algissimple$(\var{al}, \{\var{ss} = 0\})$}\kbdsidx{algissimple}\label{se:algissimple}
+\var{al} being a table algebra output by \tet{algtableinit} or a central
+simple algebra output by \tet{alginit}, tests whether the algebra \var{al} is
+simple. If $\var{ss}=1$, assumes that the algebra~\var{al} is semisimple
+without testing it.
+\bprog
+? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
+? A = algtableinit(mt); \\ matrices [*,*; 0,*]
+? algissimple(A)
+%3 = 0
+? algissimple(A,1) \\ incorrectly assume that A is semisimple
+%4 = 1
+? m_i=[0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0];
+? m_j=[0,0,-1,0;0,0,0,1;1,0,0,0;0,-1,0,0];
+? m_k=[0,0,0,-1;0,0,b,0;0,1,0,0;1,0,0,0];
+? mt = [matid(4), m_i, m_j, m_k];
+? A = algtableinit(mt); \\ quaternion algebra (-1,-1)
+? algissimple(A)
+%10 = 1
+? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+? A = algtableinit(mt,2); \\ direct sum F_4+F_2
+? algissimple(A)
+%13 = 0
+ at eprog
+
+The library syntax is \fun{GEN}{algissimple}{GEN al, long ss }.
+
+\subsec{algmul$(\var{al},x,y)$}\kbdsidx{algmul}\label{se:algmul}
+Given two elements $x$ and $y$ in \var{al}, computes their product $x*y$
+in the algebra~\var{al}.
+\bprog
+? A = alginit(nfinit(y), [-1,-1]);
+? algmul(A,[1,1,0,0]~,[0,0,2,1]~)
+%2 = [2, 3, 5, -4]~
+ at eprog
+
+Also accepts matrices with coefficients in \var{al}.
+
+The library syntax is \fun{GEN}{algmul}{GEN al, GEN x, GEN y}.
+
+\subsec{algmultable$(\var{al},x)$}\kbdsidx{algmultable}\label{se:algmultable}
+Given an element \var{x} in \var{al}, computes its left multiplication
+table. If \var{x} is given in basis form, returns its multiplication table on
+the integral basis; if \var{x} is given in algebraic form, returns its
+multiplication table on the basis corresponding to the algebraic form of
+elements of \var{al}. In every case, if \var{x} is a \typ{COL} of length $n$,
+then the output is a $n\times n$ \typ{MAT}.
+Also accepts a square matrix with coefficients in \var{al}.
+
+If \var{x} is not set, returns a multiplication table of \var{al} over its
+prime subfield ($\Q$ or $\F_p$), as a \typ{VEC} of \typ{MAT}: the left
+multiplication tables of basis elements. If \var{al} was output by
+\tet{algtableinit}, returns the multiplication table used to define \var{al}.
+If \var{al} was output by \tet{alginit}, returns the multiplication table of
+the order~${\cal O}_0$ stored in \var{al}.
+\bprog
+? A = alginit(nfinit(y), [-1,-1]);
+? algmultable(A,[0,1,0,0]~)
+%2 =
+[0 -1  1  0]
+
+[1  0  1  1]
+
+[0  0  1  1]
+
+[0  0 -2 -1]
+ at eprog
+
+Another example:
+
+\bprog
+? A = alginit(nfinit(y), [-1,-1]);
+? M = algmultable(A);
+? #M
+%3 = 4
+? M[1]
+%4 =
+[1 0 0 0]
+
+[0 1 0 0]
+
+[0 0 1 0]
+
+[0 0 0 1]
+
+? M[2]
+%5 =
+[0 -1  1  0]
+
+[1  0  1  1]
+
+[0  0  1  1]
+
+[0  0 -2 -1]
+ at eprog
+
+The library syntax is \fun{GEN}{gp_algmultable}{GEN al, GEN x = NULL}.
+
+\subsec{algneg$(\var{al},x)$}\kbdsidx{algneg}\label{se:algneg}
+Given an element $x$ in \var{al}, computes its opposite $-x$ in the
+algebra \var{al}.
+\bprog
+? A = alginit(nfinit(y), [-1,-1]);
+? algneg(A,[1,1,0,0]~)
+%2 = [-1, -1, 0, 0]~
+ at eprog
+
+Also accepts matrices with coefficients in \var{al}.
+
+The library syntax is \fun{GEN}{algneg}{GEN al, GEN x}.
+
+\subsec{algnorm$(\var{al},x)$}\kbdsidx{algnorm}\label{se:algnorm}
+Given an element \var{x} in \var{al}, computes its norm. If \var{al} is
+a table algebra output by \tet{algtableinit}, returns the absolute norm of
+\var{x}, which is an element of $\F_p$ of~$\Q$; if \var{al} is a central
+simple algebra output by \tet{alginit}, returns the reduced norm of \var{x},
+which is an element of the center of \var{al}.
+\bprog
+? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+? A = algtableinit(mt,19);
+? algnorm(A,[0,-2,3]~)
+%3 = 18
+ at eprog
+
+Also accepts a square matrix with coefficients in \var{al}.
+
+The library syntax is \fun{GEN}{algnorm}{GEN al, GEN x}.
+
+\subsec{algpoleval$(\var{al},T,b)$}\kbdsidx{algpoleval}\label{se:algpoleval}
+Given an element $b$ in \var{al} and a polynomial $T$ in $K[X]$,
+computes $T(b)$ in \var{al}.
+
+The library syntax is \fun{GEN}{algpoleval}{GEN al, GEN T, GEN b}.
+
+\subsec{algpow$(\var{al},x,n)$}\kbdsidx{algpow}\label{se:algpow}
+Given an element $x$ in \var{al} and an integer $n$, computes the
+power $x^n$ in the algebra \var{al}.
+\bprog
+? A = alginit(nfinit(y), [-1,-1]);
+? algpow(A,[1,1,0,0]~,7)
+%2 = [8, -8, 0, 0]~
+ at eprog
+
+Also accepts a square matrix with coefficients in \var{al}.
+
+The library syntax is \fun{GEN}{algpow}{GEN al, GEN x, GEN n}.
+
+\subsec{algprimesubalg$(\var{al})$}\kbdsidx{algprimesubalg}\label{se:algprimesubalg}
+\var{al} being the output of \tet{algtableinit} representing a semisimple
+algebra of positive characteristic, returns a basis of the prime subalgebra
+of~\var{al}. The prime subalgebra of~\var{al} is the subalgebra fixed by the
+Frobenius automorphism of the center of \var{al}. It is abstractly isomorphic
+to a product of copies of $\F_p$.
+\bprog
+? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+? A = algtableinit(mt,2);
+? algprimesubalg(A)
+%3 =
+[1 0]
+
+[0 1]
+
+[0 0]
+ at eprog
+
+The library syntax is \fun{GEN}{algprimesubalg}{GEN al}.
+
+\subsec{algquotient$(\var{al},I,\{\fl=0\})$}\kbdsidx{algquotient}\label{se:algquotient}
+\var{al} being a table algebra output by \tet{algtableinit} and \var{I}
+being a basis of a two-sided ideal of \var{al} represented by a matrix,
+returns the quotient $\var{al}/\var{I}$. When $\var{flag}=1$, returns a
+\typ{VEC} $[\var{al}/\var{I},\var{proj},\var{lift}]$ where \var{proj} and
+\var{lift} are matrices respectively representing the projection map and a
+section of it.
+\bprog
+? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+? A = algtableinit(mt,2);
+? AQ = algquotient(A,[0;1;0]);
+? algdim(AQ)
+%4 = 2
+ at eprog
+
+The library syntax is \fun{GEN}{alg_quotient}{GEN al, GEN I, long flag}.
+
+\subsec{algradical$(\var{al})$}\kbdsidx{algradical}\label{se:algradical}
+\var{al} being a table algebra output by \tet{algtableinit}, returns a
+basis of the Jacobson radical of the algebra \var{al} over its prime field
+($\Q$ or $\F_p$).
+
+Here is an example with $A = \Q[x]/(x^2)$, generated by $(1,x)$:
+\bprog
+? mt = [matid(2),[0,0;1,0]];
+? A = algtableinit(mt);
+? algradical(A) \\ = (x)
+%3 =
+[0]
+
+[1]
+ at eprog
+
+Another one with $2\times 2$ upper triangular matrices over $\Q$, generated
+by $I_2$, $a = \kbd{[0,1;0,0]}$ and $b = \kbd{[0,0;0,1]}$, such that $a^2 =
+0$, $ab = a$, $ba = 0$, $b^2 = b$:
+\bprog
+? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
+? A = algtableinit(mt);
+? algradical(A) \\ = (a)
+%6 =
+[0]
+
+[1]
+
+[0]
+ at eprog
+
+The library syntax is \fun{GEN}{algradical}{GEN al}.
+
+\subsec{algrandom$(\var{al},b)$}\kbdsidx{algrandom}\label{se:algrandom}
+Given an algebra \var{al} and an integer \var{b}, returns a random
+element in \var{al} with coefficients in~$[-b,b]$.
+
+The library syntax is \fun{GEN}{algrandom}{GEN al, GEN b}.
+
+\subsec{algrelmultable$(\var{al})$}\kbdsidx{algrelmultable}\label{se:algrelmultable}
+Given a central simple algebra \var{al} output by \tet{alginit} defined by a multiplication table over its center (a number field), returns this multiplication table.
+\bprog
+? nf = nfinit(y^3-5); a = y; b = y^2;
+? {m_i = [0,a,0,0;
+          1,0,0,0;
+          0,0,0,a;
+          0,0,1,0];}
+? {m_j = [0, 0,b, 0;
+          0, 0,0,-b;
+          1, 0,0, 0;
+          0,-1,0, 0];}
+? {m_k = [0, 0,0,-a*b;
+          0, 0,b,   0;
+          0,-a,0,   0;
+          1, 0,0,   0];}
+? mt = [matid(4), m_i, m_j, m_k];
+? A = alginit(nf,mt,'x);
+? M = algrelmultable(A);
+? M[2] == m_i
+%8 = 1
+? M[3] == m_j
+%9 = 1
+? M[4] == m_k
+%10 = 1
+ at eprog
+
+The library syntax is \fun{GEN}{algrelmultable}{GEN al}.
+
+\subsec{algsimpledec$(\var{al},\{\fl=0\})$}\kbdsidx{algsimpledec}\label{se:algsimpledec}
+\var{al} being the output of \tet{algtableinit} representing a semisimple
+algebra, returns a \typ{VEC} $[\var{al}_1,\var{al}_2,\dots,\var{al}_n]$ such
+that~\var{al} is isomorphic to the direct sum of the simple algebras
+$\var{al}_i$. When $\var{flag}=1$, each component is instead a \typ{VEC}
+$[\var{al}_i,\var{proj}_i,\var{lift}_i]$ where $\var{proj}_i$
+and~$\var{lift}_i$ are matrices respectively representing the projection map
+on the $i$-th factor and a section of it.
+
+\misctitle{Warning} The images of the $\var{lift}_i$ are not guaranteed to form a direct sum.
+
+The library syntax is \fun{GEN}{algsimpledec}{GEN al, long flag}.
+
+\subsec{algsplittingdata$(\var{al})$}\kbdsidx{algsplittingdata}\label{se:algsplittingdata}
+Given a central simple algebra \var{al} output by \tet{alginit} defined
+by a multiplication table over its center~$K$ (a number field), returns data
+stored to compute a splitting of \var{al} over an extension. This data is a
+\typ{VEC} \kbd{[t,Lbas,Lbasinv]} with $3$ components:
+
+ \item an element $t$ of \var{al} such that $L=K(t)$ is a maximal subfield
+of \var{al};
+
+ \item a matrix \kbd{Lbas} expressing a $L$-basis of \var{al} (given an
+$L$-vector space structure by multiplication on the right) on the integral
+basis of \var{al};
+
+ \item a matrix \kbd{Lbasinv} expressing the integral basis of \var{al} on
+the previous $L$-basis.
+
+\bprog
+? nf = nfinit(y^3-5); a = y; b = y^2;
+? {m_i = [0,a,0,0;
+          1,0,0,0;
+          0,0,0,a;
+          0,0,1,0];}
+? {m_j = [0, 0,b, 0;
+          0, 0,0,-b;
+          1, 0,0, 0;
+          0,-1,0, 0];}
+? {m_k = [0, 0,0,-a*b;
+          0, 0,b,   0;
+          0,-a,0,   0;
+          1, 0,0,   0];}
+? mt = [matid(4), m_i, m_j, m_k];
+? A = alginit(nf,mt,'x);
+? [t,Lb,Lbi] = algsplittingdata(A);
+? t
+%8 = [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]~;
+? matsize(Lb)
+%9 = [12, 2]
+? matsize(Lbi)
+%10 = [2, 12]
+ at eprog
+
+The library syntax is \fun{GEN}{algsplittingdata}{GEN al}.
+
+\subsec{algsplittingfield$(\var{al})$}\kbdsidx{algsplittingfield}\label{se:algsplittingfield}
+Given a central simple algebra \var{al} output by \tet{alginit}, returns
+an \var{rnf} structure: the splitting field of \var{al} that is stored in
+\var{al}, as a relative extension of the center.
+\bprog
+nf = nfinit(y^3-5);
+a = y; b = y^2;
+{m_i = [0,a,0,0;
+       1,0,0,0;
+       0,0,0,a;
+       0,0,1,0];}
+{m_j = [0, 0,b, 0;
+       0, 0,0,-b;
+       1, 0,0, 0;
+       0,-1,0, 0];}
+{m_k = [0, 0,0,-a*b;
+       0, 0,b,   0;
+       0,-a,0,   0;
+       1, 0,0,   0];}
+mt = [matid(4), m_i, m_j, m_k];
+A = alginit(nf,mt,'x);
+algsplittingfield(A).pol
+%8 = x^2 - y
+ at eprog
+
+The library syntax is \fun{GEN}{algsplittingfield}{GEN al}.
+
+\subsec{algsplittingmatrix$(\var{al},x)$}\kbdsidx{algsplittingmatrix}\label{se:algsplittingmatrix}
+A central simple algebra \var{al} output by \tet{alginit} contains data
+describing an isomorphism~$\phi : A\otimes_K L \to M_d(L)$, where $d$ is the
+degree of the algebra and $L$ is an extension of $L$ with~$[L:K]=d$. Returns
+the matrix $\phi(x)$.
+\bprog
+? A = alginit(nfinit(y), [-1,-1]);
+? algsplittingmatrix(A,[0,0,0,2]~)
+%2 =
+[Mod(x + 1, x^2 + 1) Mod(Mod(1, y)*x + Mod(-1, y), x^2 + 1)]
+
+[Mod(x + 1, x^2 + 1)                   Mod(-x + 1, x^2 + 1)]
+ at eprog
+
+Also accepts matrices with coefficients in \var{al}.
+
+The library syntax is \fun{GEN}{algsplittingmatrix}{GEN al, GEN x}.
+
+\subsec{algsqr$(\var{al},x)$}\kbdsidx{algsqr}\label{se:algsqr}
+Given an element $x$ in \var{al}, computes its square $x^2$ in the
+algebra \var{al}.
+\bprog
+? A = alginit(nfinit(y), [-1,-1]);
+? algsqr(A,[1,0,2,0]~)
+%2 = [-3, 0, 4, 0]~
+ at eprog
+
+Also accepts a square matrix with coefficients in \var{al}.
+
+The library syntax is \fun{GEN}{algsqr}{GEN al, GEN x}.
+
+\subsec{algsub$(\var{al},x,y)$}\kbdsidx{algsub}\label{se:algsub}
+Given two elements $x$ and $y$ in \var{al}, computes their difference
+$x-y$ in the algebra \var{al}.
+\bprog
+? A = alginit(nfinit(y), [-1,-1]);
+? algsub(A,[1,1,0,0]~,[1,0,1,0]~)
+%2 = [0, 1, -1, 0]~
+ at eprog
+
+Also accepts matrices with coefficients in \var{al}.
+
+The library syntax is \fun{GEN}{algsub}{GEN al, GEN x, GEN y}.
+
+\subsec{algsubalg$(\var{al},B)$}\kbdsidx{algsubalg}\label{se:algsubalg}
+\var{al} being a table algebra output by \tet{algtableinit} and \var{B}
+being a basis of a subalgebra of \var{al} represented by a matrix, returns an
+algebra isomorphic to \var{B}.
+\bprog
+? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+? A = algtableinit(mt,2);
+? B = algsubalg(A,[1,0; 0,0; 0,1]);
+? algdim(A)
+%4 = 3
+? algdim(B)
+%5 = 2
+ at eprog
+
+The library syntax is \fun{GEN}{algsubalg}{GEN al, GEN B}.
+
+\subsec{algtableinit$(\var{mt}, \{p\})$}\kbdsidx{algtableinit}\label{se:algtableinit}
+Initialize the associative algebra over $K = \Q$ (p omitted) or $\F_p$
+defined by the multiplication table \var{mt}.
+As a $K$-vector space, the algebra is generated by a basis
+$(e_1 = 1, e_2, \dots, e_n)$; the table is given as a \typ{VEC} of $n$ matrices in
+$M_n(K)$, giving the left multiplication by the basis elements $e_i$, in the
+given basis.
+Assumes that $e_1=1$, that $K e_1\oplus \dots\oplus K e_n]$ describes an
+associative algebra over $K$, and in the case $K=\Q$ that the multiplication
+table is integral. If the algebra is already known to be central
+and simple, then the case $K = \F_p$ is useless, and one should use
+\tet{alginit} directly.
+
+The point of this function is to input a finite dimensional $K$-algebra, so
+as to later compute its radical, then to split the quotient algebra as a
+product of simple algebras over $K$.
+
+The pari object representing such an algebra $A$ is a \typ{VEC} with the
+following data:
+
+ \item The characteristic of $A$, accessed with \kbd{algchar}.
+
+ \item The multiplication table of $A$, accessed with \kbd{algmultable}.
+
+ \item The traces of the elements of the basis.
+
+A simple example: the $2\times 2$ upper triangular matrices over $\Q$,
+generated by $I_2$, $a = \kbd{[0,1;0,0]}$ and $b = \kbd{[0,0;0,1]}$,
+such that $a^2 = 0$, $ab = a$, $ba = 0$, $b^2 = b$:
+\bprog
+? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
+? A = algtableinit(mt);
+? algradical(A) \\ = (a)
+%6 =
+[0]
+
+[1]
+
+[0]
+? algcenter(A) \\ = (I_2)
+%7 =
+[1]
+
+[0]
+
+[0]
+ at eprog
+
+The library syntax is \fun{GEN}{algtableinit}{GEN mt, GEN p = NULL}.
+
+\subsec{algtensor$(\var{al1},\var{al2},\{\var{maxord}=1\})$}\kbdsidx{algtensor}\label{se:algtensor}
+Given two algebras \var{al1} and \var{al2}, computes their tensor
+product. For table algebras output by \tet{algtableinit}, the flag
+\var{maxord} is ignored. For central simple algebras output by \tet{alginit},
+computes a maximal order by default. Prevent this computation by setting
+$\var{maxord}=0$.
+
+Currently only implemented for cyclic algebras of coprime degree over the same
+center~$K$, and the tensor product is over~$K$.
+
+The library syntax is \fun{GEN}{algtensor}{GEN al1, GEN al2, long maxord}.
+
+\subsec{algtrace$(\var{al},x)$}\kbdsidx{algtrace}\label{se:algtrace}
+Given an element \var{x} in \var{al}, computes its trace. If \var{al} is
+a table algebra output by \tet{algtableinit}, returns the absolute trace of
+\var{x}, which is an element of $\F_p$ or~$\Q$; if \var{al} is the output of
+\tet{alginit}, returns the reduced trace of \var{x}, which is an element of
+the center of \var{al}.
+\bprog
+? A = alginit(nfinit(y), [-1,-1]);
+? algtrace(A,[5,0,0,1]~)
+%2 = 11
+ at eprog
+
+Also accepts a square matrix with coefficients in \var{al}.
+
+The library syntax is \fun{GEN}{algtrace}{GEN al, GEN x}.
+
+\subsec{algtype$(\var{al})$}\kbdsidx{algtype}\label{se:algtype}
+Given an algebra \var{al} output by \tet{alginit} or by \tet{algtableinit}, returns an integer indicating the type of algebra:
+
+\item $0$: not a valid algebra.
+
+\item $1$: table algebra output by \tet{algtableinit}.
+
+\item $2$: central simple algebra output by \tet{alginit} and represented by
+a multiplication table over its center.
+
+\item $3$: central simple algebra output by \tet{alginit} and represented by
+a cyclic algebra.
+\bprog
+? algtype([])
+%1 = 0
+? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+? A = algtableinit(mt,2);
+? algtype(A)
+%4 = 1
+? nf = nfinit(y^3-5);
+?  a = y; b = y^2;
+?  {m_i = [0,a,0,0;
+           1,0,0,0;
+           0,0,0,a;
+           0,0,1,0];}
+?  {m_j = [0, 0,b, 0;
+           0, 0,0,-b;
+           1, 0,0, 0;
+           0,-1,0, 0];}
+?  {m_k = [0, 0,0,-a*b;
+           0, 0,b,   0;
+           0,-a,0,   0;
+           1, 0,0,   0];}
+?  mt = [matid(4), m_i, m_j, m_k];
+?  A = alginit(nf,mt,'x);
+? algtype(A)
+%12 = 2
+? A = alginit(nfinit(y), [-1,-1]);
+? algtype(A)
+%14 = 3
+ at eprog
+
+The library syntax is \fun{long}{algtype}{GEN al}.
+%SECTION: algebras
+
 \section{Polynomials and power series}
 
 We group here all functions which are specific to polynomials or power
@@ -9977,8 +12492,8 @@ A syntax error in the evaluation expression raises an \kbd{e\_SYNTAX}
 exception, which can be trapped as usual:
 \bprog
 ? 1a
- ***   unused characters: 1a
- ***                       ^-
+ ***   syntax error, unexpected variable name, expecting $end or ';': 1a
+ ***                                                                   ^-
 ? E(expr) =
   {
     iferr(eval(expr),
@@ -10113,6 +12628,18 @@ Also available are
 \fun{GEN}{polchebyshev1}{long n, long v} and
 \fun{GEN}{polchebyshev2}{long n, long v} for $T_n$ and $U_n$ respectively.
 
+\subsec{polclass$(D, \{x = 'x\})$}\kbdsidx{polclass}\label{se:polclass}
+Return the Hilbert class polynomial for the $j$ function for the imaginary quadratic
+discriminant $D$ in the variable $x$.
+\bprog
+? polclass(-163)
+%1 = x + 262537412640768000
+? polclass(-51, 'z)
+%2 = z^2 + 5541101568*z + 6262062317568
+ at eprog
+
+The library syntax is \fun{GEN}{polclass}{GEN D, long x  = -1}, where \kbd{x } is a variable number.
+
 \subsec{polcoeff$(x,n,\{v\})$}\kbdsidx{polcoeff}\label{se:polcoeff}
 Coefficient of degree $n$ of the polynomial $x$, with respect to the
 main variable if $v$ is omitted, with respect to $v$ otherwise.  If $n$
@@ -10174,12 +12701,14 @@ The library syntax is \fun{GEN}{polcyclofactors}{GEN f}.
 Degree of the polynomial $x$ in the main variable if $v$ is omitted, in
 the variable $v$ otherwise.
 
-The degree of $0$ is a fixed negative number, whose exact value should not
-be used. The degree of a non-zero scalar is $0$. Finally, when $x$ is a
-non-zero polynomial or rational function, returns the ordinary degree of
-$x$. Raise an error otherwise.
+The degree of $0$ is \kbd{-oo}. The degree of a non-zero scalar is $0$.
+Finally, when $x$ is a non-zero polynomial or rational function, returns the
+ordinary degree of $x$. Raise an error otherwise.
 
-The library syntax is \fun{long}{poldegree}{GEN x, long v = -1}, where \kbd{v} is a variable number.
+The library syntax is \fun{GEN}{gppoldegree}{GEN x, long v = -1}, where \kbd{v} is a variable number.
+Also available is
+\fun{long}{poldegree}{GEN x, long v}, which returns \tet{-LONG_MAX} if $x = 0$
+and the degree as a \kbd{long} integer.
 
 \subsec{poldisc$(\var{pol},\{v\})$}\kbdsidx{poldisc}\label{se:poldisc}
 Discriminant of the polynomial
@@ -10301,6 +12830,32 @@ The library syntax is \fun{GEN}{pollegendre_eval}{long n, GEN a = NULL}.
 To obtain the $n$-th Legendre polynomial in variable $v$,
 use \fun{GEN}{pollegendre}{long n, long v}.
 
+\subsec{polmodular$(L, \{x = 'x\}, \{y = 'y\}, \{\var{compute\_derivs} = 0\})$}\kbdsidx{polmodular}\label{se:polmodular}
+Return the modular polynomial of level $L$ in variables $x$ and $y$ for the
+$j$ function.  If $x$ is given as \kbd{Mod(j, p)} or an element $j$ of a prime
+finite field, then return the modular polynomial of level $L$ evaluated at $j$
+modulo $p$.  If $j$ is from a finite field and \var{compute\_derivs} is
+non-zero, then return a triple where the last two elements are the first and
+second derivatives of the modular polynomial evaluated at $j$.
+\bprog
+? polmodular(3)
+%1 = x^4 + (-y^3 + 2232*y^2 - 1069956*y + 36864000)*x^3 + [...]
+ at eprog
+
+The library syntax is \fun{GEN}{polmodular}{long L, GEN x  = NULL, long y  = -1, long compute_derivs }, where \kbd{y } is a variable number.
+Also available are
+
+\fun{GEN}{modpoly_ZXX}{long L, long xvar, long yvar} which returns a
+bivariate polynomial in variables \kbd{xvar} and \kbd{yvar},
+
+\fun{GEN}{modpoly_ZM}{long L} which returns a matrix of coefficients, and
+
+\fun{GEN}{Fp_modpoly_evalx}{long L, GEN J, GEN P, long v, int
+compute_derivs} which returns the modular polynomial evaluated at $J$ modulo
+$P$ in the variable $v$ (if \kbd{compute\_derivs} is non-zero, returns a
+vector containing the modular polynomial and its first and second
+derivatives, all evaluted at $J$ modulo $P$).
+
 \subsec{polrecip$(\var{pol})$}\kbdsidx{polrecip}\label{se:polrecip}
 Reciprocal polynomial of \var{pol}, i.e.~the coefficients are in
 reverse order. \var{pol} must be a polynomial.
@@ -10392,14 +12947,67 @@ with eact rational coefficients.
 
 The library syntax is \fun{GEN}{rootpadic}{GEN x, GEN p, long r}.
 
-\subsec{polsturm$(\var{pol},\{a\},\{b\})$}\kbdsidx{polsturm}\label{se:polsturm}
-Number of real roots of the real squarefree polynomial \var{pol} in the
-interval $]a,b]$, using Sturm's algorithm. $a$ (resp.~$b$) is taken to be
-$-\infty$ (resp.~$+\infty$) if omitted.
+\subsec{polrootsreal$(T, \{\var{ab}\})$}\kbdsidx{polrootsreal}\label{se:polrootsreal}
+Real roots of the polynomial $T$ with rational coefficients, multiple
+roots being included according to their multiplicity. The roots are given
+to a relative accuracy of \kbd{realprecision}. If argument \var{ab} is
+present, it must be a vector $[a,b]$ with two components (of type
+\typ{INT}, \typ{FRAC} or \typ{INFINITY}) and we restrict to roots belonging
+to that closed interval.
+\bprog
+? \p9
+? polrootsreal(x^2-2)
+%1 = [-1.41421356, 1.41421356]~
+? polrootsreal(x^2-2, [1,+oo])
+%2 = [1.41421356]~
+? polrootsreal(x^2-2, [2,3])
+%3 = []~
+? polrootsreal((x-1)*(x-2), [2,3])
+%4 = [2.00000000]~
+ at eprog\noindent
+The algorithm used is a modification of Uspensky's method (relying on
+Descartes's rule of sign), following Rouillier and Zimmerman ``Efficient
+isolation of a polynomial real roots''
+(\url{http://hal.inria.fr/inria-00072518/}. Barring bugs, it is guaranteed
+to converge and to give the roots to the required accuracy.
+
+\misctitle{Remark} If the polynomial $T$ is of the
+form $Q(x^h)$ for some $h\geq 2$ and \var{ab} is omitted, the routine will
+apply the algorithm to $Q$ (restricting to non-negative roots when $h$ is
+even), then take $h$-th roots. On the other hand, if you want to specify
+\var{ab}, you should apply the routine to $Q$ yourself and a suitable
+interval $[a',b']$ using approximate $h$-th roots adapted to your problem:
+the function will not perform this change of variables if \var{ab} is present.
+
+The library syntax is \fun{GEN}{realroots}{GEN T, GEN ab = NULL, long prec}.
+
+\subsec{polsturm$(T,\{\var{ab}\})$}\kbdsidx{polsturm}\label{se:polsturm}
+Number of real roots of the real squarefree polynomial \var{T}. If
+the argument \var{ab} is present, it must be a vector $[a,b]$ with
+two real components (of type \typ{INT}, \typ{REAL}, \typ{FRAC}
+or  \typ{INFINITY}) and we count roots belonging to that closed interval.
+
+If possible, you should stick to exact inputs, that is avoid \typ{REAL}s in
+$T$ and the bounds $a,b$: the result is then guaranteed and we use a fast
+algorithm (Uspensky's method, relying on Descartes's rule of sign, see
+\tet{polrootsreal}); otherwise, we use Sturm's algorithm and the result
+may be wrong due to round-off errors.
+\bprog
+? T = (x-1)*(x-2)*(x-3);
+? polsturm(T)
+%2 = 3
+? polsturm(T, [-oo,2])
+%3 = 2
+? polsturm(T, [1/2,+oo])
+%4 = 3
+? polsturm(T, [1, Pi])  \\ Pi inexact: not recommended !
+%5 = 3
+ at eprog
+%\syn{NO}
 
-The library syntax is \fun{long}{sturmpart}{GEN pol, GEN a = NULL, GEN b = NULL}.
-Also available is \fun{long}{sturm}{GEN pol} (total number of real
-roots).
+The library syntax is \fun{long}{RgX_sturmpart}{GEN T, GEN ab} or
+\fun{long}{sturm}{GEN T} (for the case \kbd{ab = NULL}). The function
+\fun{long}{sturmpart}{GEN T, GEN a, GEN b} is obsolete and deprecated.
 
 \subsec{polsubcyclo$(n,d,\{v='x\})$}\kbdsidx{polsubcyclo}\label{se:polsubcyclo}
 Gives polynomials (in variable $v$) defining the sub-Abelian extensions
@@ -10462,7 +13070,8 @@ The library syntax is \fun{GEN}{convol}{GEN x, GEN y}.
 
 \subsec{serlaplace$(x)$}\kbdsidx{serlaplace}\label{se:serlaplace}
 $x$ must be a power series with non-negative
-exponents. If $x=\sum (a_k/k!)*X^k$ then the result is $\sum a_k*X^k$.
+exponents or a polynomial. If $x=\sum (a_k/k!)*X^k$ then the result is $\sum
+a_k*X^k$.
 
 The library syntax is \fun{GEN}{laplace}{GEN x}.
 
@@ -10595,7 +13204,7 @@ $P(x,y)=a$ in integers $x$ and $y$, where \var{tnf} was created with
 $\kbd{thueinit}(P)$. If present, \var{sol} must contain the solutions of
 $\Norm(x)=a$ modulo units of positive norm in the number field
 defined by $P$ (as computed by \kbd{bnfisintnorm}). If there are infinitely
-many solutions, an error will be issued.
+many solutions, an error is issued.
 
 It is allowed to input directly the polynomial $P$ instead of a \var{tnf},
 in which case, the function first performs \kbd{thueinit(P,0)}. This is
@@ -10649,17 +13258,59 @@ Note that reducible or non-monic polynomials are allowed:
 The library syntax is \fun{GEN}{thue}{GEN tnf, GEN a, GEN sol = NULL}.
 
 \subsec{thueinit$(P,\{\fl=0\})$}\kbdsidx{thueinit}\label{se:thueinit}
-Initializes the \var{tnf} corresponding to $P$, a univariate polynomial
-with integer coefficients. The result is meant to be used in conjunction with
-\tet{thue} to solve Thue equations $P(X / Y)Y^{\deg P} = a$, where $a$ is an
-integer.
+Initializes the \var{tnf} corresponding to $P$, a non-constant
+univariate polynomial with integer coefficients.
+The result is meant to be used in conjunction with \tet{thue} to solve Thue
+equations $P(X / Y)Y^{\deg P} = a$, where $a$ is an integer. Accordingly,
+$P$ must either have at least two distinct irreducible factors over $\Q$,
+or have one irreducible factor $T$ with degree $>2$ or two conjugate
+complex roots: under these (necessary and sufficient) conditions, the
+equation has finitely many integer solutions.
+\bprog
+? S = thueinit(t^2+1);
+? thue(S, 5)
+%2 = [[-2, -1], [-2, 1], [-1, -2], [-1, 2], [1, -2], [1, 2], [2, -1], [2, 1]]
+? S = thueinit(t+1);
+ ***   at top-level: thueinit(t+1)
+ ***                 ^-------------
+ *** thueinit: domain error in thueinit: P = t + 1
+ at eprog\noindent The hardest case is when $\deg P > 2$ and $P$ is irreducible
+with at least one real root. The routine then uses Bilu-Hanrot's algorithm.
 
 If $\fl$ is non-zero, certify results unconditionally. Otherwise, assume
 \idx{GRH}, this being much faster of course. In the latter case, the result
 may still be unconditionally correct, see \tet{thue}. For instance in most
 cases where $P$ is reducible (not a pure power of an irreducible), \emph{or}
 conditional computed class groups are trivial \emph{or} the right hand side
-is $\pm1$, then results are always unconditional.
+is $\pm1$, then results are unconditional.
+
+\misctitle{Note} The general philosophy is to disprove the existence of large
+solutions then to enumerate bounded solutions naively. The implementation
+will overflow when there exist huge solutions and the equation has degree
+$> 2$ (the quadratic imaginary case is special, since we can use
+\kbd{bnfisintnorm}):
+\bprog
+? thue(t^3+2, 10^30)
+ ***   at top-level: L=thue(t^3+2,10^30)
+ ***                   ^-----------------
+ *** thue: overflow in thue (SmallSols): y <= 80665203789619036028928.
+? thue(x^2+2, 10^30)  \\ quadratic case much easier
+%1 = [[-1000000000000000, 0], [1000000000000000, 0]]
+ at eprog
+
+\misctitle{Note} It is sometimes possible to circumvent the above, and in any
+case obtain an important speed-up, if you can write $P = Q(x^d)$ for some $d >
+1$ and $Q$ still satisfying the \kbd{thueinit} hypotheses. You can then solve
+the equation associated to $Q$ then eliminate all solutions $(x,y)$ such that
+either $x$ or $y$ is not a $d$-th power.
+\bprog
+? thue(x^4+1, 10^40); \\ stopped after 10 hours
+? filter(L,d) =
+    my(x,y); [[x,y] | v<-L, ispower(v[1],d,&x)&&ispower(v[2],d,&y)];
+? L = thue(x^2+1, 10^40);
+? filter(L, 2)
+%4 = [[0, 10000000000], [10000000000, 0]]
+ at eprog\noindent The last 2 commands use less than 20ms.
 
 The library syntax is \fun{GEN}{thueinit}{GEN P, long flag, long prec}.
 %SECTION: polynomials
@@ -11525,21 +14176,13 @@ Also available are \fun{GEN}{ker}{GEN x} ($\fl=0$),
 
 \subsec{matkerint$(x,\{\fl=0\})$}\kbdsidx{matkerint}\label{se:matkerint}
 Gives an \idx{LLL}-reduced $\Z$-basis
-for the lattice equal to the kernel of the matrix $x$ as columns of the
-matrix $x$ with integer entries (rational entries are not permitted).
-
-If $\fl=0$, uses an integer LLL algorithm.
+for the lattice equal to the kernel of the matrix $x$ with rational entries.
 
-If $\fl=1$, uses $\kbd{matrixqz}(x,-2)$. Many orders of magnitude slower
-than the default: never use this.
+\fl is deprecated, kept for backward compatibility.
 
 The library syntax is \fun{GEN}{matkerint0}{GEN x, long flag}.
-See also \fun{GEN}{kerint}{GEN x} ($\fl=0$), which is a trivial
-wrapper around
-\bprog
-ZM_lll(ZM_lll(x, 0.99, LLL_KER), 0.99, LLL_INPLACE);
- at eprog\noindent Remove the outermost \kbd{ZM\_lll} if LLL-reduction is not
-desired (saves time).
+Use directly \fun{GEN}{kerint}{GEN x} if $x$ is known to have
+integer entries, and \tet{Q_primpart} first otherwise.
 
 \subsec{matmuldiagonal$(x,d)$}\kbdsidx{matmuldiagonal}\label{se:matmuldiagonal}
 Product of the matrix $x$ by the diagonal
@@ -11574,8 +14217,8 @@ More precisely, if
 \bprog
   [Q,R] = matqr(M);
   [q,r] = matqr(M, 1);
- at eprog\noindent then $r = R$ and \kbd{mathouseholder}$(q, M)$ is $R$;
-furthermore
+ at eprog\noindent then $r = R$ and \kbd{mathouseholder}$(q, M)$ is
+(close to) $R$; furthermore
 \bprog
   mathouseholder(q, matid(#M)) == Q~
 @eprog\noindent the inverse of $Q$. This function raises an error if the
@@ -12165,6 +14808,33 @@ time = 2,793 ms.
 
 The library syntax is \fun{GEN}{qfnorm}{GEN x, GEN q = NULL}.
 
+\subsec{qfparam$(G, \var{sol}, \{\fl = 0\})$}\kbdsidx{qfparam}\label{se:qfparam}
+Coefficients of binary quadratic forms that parametrize the
+solutions of the ternary quadratic form $G$, using the particular
+solution~\var{sol}.
+\fl is optional and can be 1, 2, or 3, in which case the \fl-th form is
+reduced. The default is \fl=0 (no reduction).
+\bprog
+? G = [1,0,0;0,1,0;0,0,-34];
+? M = qfparam(G, qfsolve(G))
+%2 =
+[ 3 -10 -3]
+
+[-5  -6  5]
+
+[ 1   0  1]
+ at eprog
+Indeed, the solutions can be parametrized as
+$$(3x^2 - 10xy - 3y^2)^2  + (-5x^2 - 6xy + 5y^2)^2 -34(x^2 + y^2)^2 = 0.$$
+\bprog
+? v = y^2 * M*[1,x/y,(x/y)^2]~
+%3 = [3*x^2 - 10*y*x - 3*y^2, -5*x^2 - 6*y*x + 5*y^2, -x^2 - y^2]~
+? v~*G*v
+%4 = 0
+ at eprog
+
+The library syntax is \fun{GEN}{qfparam}{GEN G, GEN sol, long flag }.
+
 \subsec{qfperfection$(G)$}\kbdsidx{qfperfection}\label{se:qfperfection}
 $G$ being a square and symmetric matrix with
 integer entries representing a positive definite quadratic form, outputs the
@@ -12209,6 +14879,30 @@ reduction.
 
 The library syntax is \fun{GEN}{qfsign}{GEN x}.
 
+\subsec{qfsolve$(G)$}\kbdsidx{qfsolve}\label{se:qfsolve}
+Given a square symmetric matrix $G$ of dimension $n \geq 1$, solve over
+$\Q$ the quadratic equation $X^tGX = 0$. The matrix $G$ must have rational
+coefficients. The solution might be a single non-zero vector (vectorv) or a
+matrix (whose columns generate a totally isotropic subspace).
+
+If no solution exists, returns an integer, that can be a prime $p$ such that
+there is no local solution at $p$, or $-1$ if there is no real solution,
+or $-2$ if $n = 2$ and $-\det G$ is positive but not a square (which implies
+there is a real solution, but no local solution at some $p$ dividing $\det G$).
+\bprog
+? G = [1,0,0;0,1,0;0,0,-34];
+? qfsolve(G)
+%1 = [-3, -5, 1]~
+? qfsolve([1,0; 0,2])
+%2 = -1   \\ no real solution
+? qfsolve([1,0,0;0,3,0; 0,0,-2])
+%3 = 3    \\ no solution in Q_3
+? qfsolve([1,0; 0,-2])
+%4 = -2   \\ no solution, n = 2
+ at eprog
+
+The library syntax is \fun{GEN}{qfsolve}{GEN G}.
+
 \subsec{seralgdep$(s,p,r)$}\kbdsidx{seralgdep}\label{se:seralgdep}
 \sidx{algebraic dependence} finds a linear relation between powers $(1,s,
 \dots, s^p)$ of the series $s$, with polynomial coefficients of degree
@@ -12398,9 +15092,9 @@ the (positive) index where $x$ was found, or $0$ if it does not belong to
 $v$.
 
 If the comparison function cmpf is omitted, we assume that $v$ is sorted in
-increasing order, according to the standard comparison function $<$, thereby
-restricting the possible types for $x$ and the elements of $v$ (integers,
-fractions or reals).
+increasing order, according to the standard comparison function \kbd{lex},
+thereby restricting the possible types for $x$ and the elements of $v$
+(integers, fractions, reals, and vectors of such).
 
 If \kbd{cmpf} is present, it is understood as a comparison function and we
 assume that $v$ is sorted according to it, see \tet{vecsort} for how to
@@ -12501,7 +15195,14 @@ For example, \kbd{vecextract(x, vecsort(x,,1))} is equivalent to
 The library syntax is \fun{GEN}{vecsort0}{GEN x, GEN cmpf = NULL, long flag}.
 
 \subsec{vecsum$(v)$}\kbdsidx{vecsum}\label{se:vecsum}
-Return the sum of the component of the vector $v$
+Return the sum of the components of the vector $v$. Return $0$ on an
+empty vector.
+\bprog
+? vecsum([1,2,3])
+%1 = 6
+? vecsum([])
+%2 = 0
+ at eprog
 
 The library syntax is \fun{GEN}{vecsum}{GEN v}.
 
@@ -12756,7 +15457,6 @@ $\Gamma(s)^3$ given in \kbd{intmellininv}:
 
 \bprog
 ? \p 105
-? oo = [1]; \\@com for clarity
 ? A = intmellininv(s=2,4, gamma(s)^3);
 time = 2,500 ms. \\@com not too fast because of $\Gamma(s)^3$.
 \\ @com function of real type, decreasing as $\exp(-3\pi/2\cdot |t|)$
@@ -12789,12 +15489,8 @@ there, the situation is simple:
 ? intnum(x = 0,Pi/2, [cos(x), sin(x)])
 %2 = [1.000000000000000000000000000, 1.000000000000000000000000000]
 @eprog\noindent
-An endpoint equal to $\pm\infty$ is coded as the single-component vector
-$[\pm1]$. You are welcome to set, e.g \kbd{oo = [1]} or \kbd{INFINITY = [1]},
-then using \kbd{+oo}, \kbd{-oo}, \kbd{-INFINITY}, etc. will have the expected
-behavior.
+An endpoint equal to $\pm\infty$ is coded as \kbd{+oo} or \kbd{-oo}.
 \bprog
-? oo = [1];  \\@com for clarity
 ? intnum(x = 1,+oo, 1/x^2)
 %2 = 1.000000000000000000000000000
 @eprog\noindent
@@ -12827,9 +15523,9 @@ expensive precomputations.
 
 \misctitle{Specifying the behavior at endpoints}
 This is done as follows. An endpoint $a$ is either given as such (a scalar,
-real or complex, or $[\pm1]$ for $\pm\infty$), or as a two component vector
-$[a,\alpha]$, to indicate the behavior of the integrand in a neighborhood
-of $a$.
+real or complex, \kbd{oo} or \kbd{-oo} for $\pm\infty$), or as a two
+component vector $[a,\alpha]$, to indicate the behavior of the integrand in a
+neighborhood of $a$.
 
 If $a$ is finite, the code $[a,\alpha]$ means the function has a
 singularity of the form $(x-a)^{\alpha}$, up to logarithms. (If $\alpha \ge
@@ -12845,18 +15541,17 @@ number of decimals:
 %3 = 1.999999999999999999999946438 \\@com using a wrong exponent is bad
 @eprog
 
-If $a$ is $\pm\infty$, which is coded as $[\pm 1]$, the situation is more
-complicated, and $[[\pm1],\alpha]$ means:
+If $a$ is $\pm\infty$, which is coded as \kbd{+oo} or \kbd{-oo},
+the situation is more complicated, and $[\pm\kbd{oo},\alpha]$ means:
 
-\item $\alpha=0$ (or no $\alpha$ at all, i.e. simply $[\pm1]$) assumes that the
-integrand tends to zero, but not exponentially fast, and not
-oscillating such as $\sin(x)/x$.
+\item $\alpha=0$ (or no $\alpha$ at all, i.e. simply $\pm\kbd{oo}$)
+assumes that the integrand tends to zero, but not exponentially fast, and
+not oscillating such as $\sin(x)/x$.
 
 \item $\alpha>0$ assumes that the function tends to zero exponentially fast
 approximately as $\exp(-\alpha x)$. This includes oscillating but quickly
 decreasing functions such as $\exp(-x)\sin(x)$.
 \bprog
-? oo = [1];
 ? intnum(x=0, +oo, exp(-2*x))
   ***   at top-level: intnum(x=0,+oo,exp(-
   ***                 ^--------------------
@@ -12891,9 +15586,11 @@ $\cos(kx+a)$.
 
 \misctitle{Note} If $f(x)=\cos(kx)g(x)$ where $g(x)$ tends to zero
 exponentially fast as $\exp(-\alpha x)$, it is up to the user to choose
-between $[[\pm1],\alpha]$ and $[[\pm1],k* I]$, but a good rule of thumb is that
+between $[\pm\kbd{oo},\alpha]$ and $[\pm\kbd{oo},k* I]$, but a good rule of
+thumb is that
 if the oscillations are much weaker than the exponential decrease, choose
-$[[\pm1],\alpha]$, otherwise choose $[[\pm1],k* I]$, although the latter can
+$[\pm\kbd{oo},\alpha]$, otherwise choose $[\pm\kbd{oo},k*I]$, although the
+latter can
 reasonably be used in all cases, while the former cannot. To take a specific
 example, in the inverse Mellin transform, the integrand is almost always a
 product of an exponentially decreasing and an oscillating factor. If we
@@ -12912,7 +15609,6 @@ parameters achieve. All examples below assume precision is set to $105$
 decimal digits. We first type
 \bprog
 ? \p 105
-? oo = [1]  \\@com for clarity
 @eprog
 
 \misctitle{Apparent singularities} Even if the function $f(x)$ represented
@@ -14432,10 +17128,6 @@ case, we list in order the components of \var{E}, accessed via
  \var{E} has three component, 1 (\typ{STR}): the function $s$,
  2: the argument $x$, 3: the argument $x$.
 
- \item \kbd{"e\_NEGVAL"}. An argument of function $s$ is a power series with
- negative valuation, which does not make sense. (As in \kbd{cos(1/x)}.)
- \var{E} has one component, 1 (\typ{STR}): the function name $s$.
-
  \item \kbd{"e\_PRIME"}. Function $s$ expected a prime number,
  and did receive $p$, which was not. (As in \kbd{idealprimedec(nf, 4)}.)
  \var{E} has two component, 1 (\typ{STR}): the function name $s$,
@@ -14462,6 +17154,14 @@ Returns from current subroutine, with
 result $x$. If $x$ is omitted, return the \kbd{(void)} value (return no
 result, like \kbd{print}).
 
+\subsec{self$()$}\kbdsidx{self}\label{se:self}
+Return the calling function or closure as a \typ{CLOSURE} object.
+This is useful for defining anonymous recursive functions.
+\bprog
+? (n->if(n==0,1,n*self()(n-1)))(5)
+%1 = 120
+ at eprog
+
 \subsec{until$(a,\var{seq})$}\kbdsidx{until}\label{se:until}
 Evaluates \var{seq} until $a$ is not
 equal to 0 (i.e.~until $a$ is true). If $a$ is initially not equal to 0,
@@ -14567,6 +17267,8 @@ it right away.
 \misctitle{Caveat} It is not possible to set a new alarm \emph{within}
 another \kbd{alarm} code: the new timer erases the parent one.
 
+The library syntax is \fun{GEN}{gp_alarm}{long s , GEN code = NULL}.
+
 \subsec{alias$(\var{newsym},\var{sym})$}\kbdsidx{alias}\label{se:alias}
 Defines the symbol \var{newsym} as an alias for the the symbol \var{sym}:
 \bprog
@@ -14631,12 +17333,64 @@ of at least $x$ bytes is allocated. We may allocate more than $x$ bytes if
 $x$ is way too small, or for alignment reasons: the current formula is
 $\max(16*\ceil{x/16}, 500032)$ bytes.
 
-If $x=0$, the size of the new stack is twice the size of the old one. The
-old stack is discarded.
-
-\misctitle{Warning} This function should be typed at the \kbd{gp} prompt in
+If $x=0$, the size of the new stack is twice the size of the old one.
+
+This command is much more useful if \tet{parisizemax} is non-zero, and we
+describe this case first. With \kbd{parisizemax} enabled, there are three
+sizes of interest:
+
+\item a virtual stack size, \tet{parisizemax}, which is an absolute upper
+limit for the stack size; this is set by \kbd{default(parisizemax, ...)}.
+
+\item the desired typical stack size, \tet{parisize}, that will grow as
+needed, up to \tet{parisizemax}; this is set by \kbd{default(parisize, ...)}.
+
+\item the current stack size, which is less that \kbd{parisizemax},
+typically equal to \kbd{parisize} but possibly larger and increasing
+dynamically as needed; \kbd{allocatemem} allows to change that one
+explicitly.
+
+The \kbd{allocatemem} command forces stack
+usage to increase temporarily (up to \kbd{parisizemax} of course); for
+instance if you notice using \kbd{\bs gm2} that we seem to collect garbage a
+lot, e.g.
+\bprog
+? \gm2
+  debugmem = 2
+? default(parisize,"32M")
+ ***   Warning: new stack size = 32000000 (30.518 Mbytes).
+? bnfinit('x^2+10^30-1)
+ *** bnfinit: collecting garbage in hnffinal, i = 1.
+ *** bnfinit: collecting garbage in hnffinal, i = 2.
+ *** bnfinit: collecting garbage in hnffinal, i = 3.
+ at eprog\noindent and so on for hundred of lines. Then, provided the
+\tet{breakloop} default is set, you can interrupt the computation, type
+\kbd{allocatemem(100*10\pow6)} at the break loop prompt, then let the
+computation go on by typing \kbd{<Enter>}. Back at the \kbd{gp} prompt,
+the desired stack size of \kbd{parisize} is restored. Note that changing either
+\kbd{parisize} or \kbd{parisizemax} at the break loop prompt would interrupt
+the computation, contrary to the above.
+
+In most cases, \kbd{parisize} will increase automatically (up to
+\kbd{parisizemax}) and there is no need to perform the above maneuvers.
+But that the garbage collector is sufficiently efficient that
+a given computation can still run without increasing the stack size,
+albeit very slowly due to the frequent garbage collections.
+
+\misctitle{Deprecated: when \kbd{parisizemax} is unset}
+This is currently still the default behavior in order not to break backward
+compatibility. The rest of this section documents the
+behavior of \kbd{allocatemem} in that (deprecated) situation: it becomes a
+synonym for \kbd{default(parisize,...)}. In that case, there is no
+notion of a virtual stack, and the stack size is always equal to
+\kbd{parisize}. If more memory is needed, the PARI stack overflows, aborting
+the computation.
+
+Thus, increasing \kbd{parisize} via \kbd{allocatemem} or
+\kbd{default(parisize,...)} before a big computation is important.
+Unfortunately, either must be typed at the \kbd{gp} prompt in
 interactive usage, or left by itself at the start of batch files.
-It cannot be used meaningfully in loop-like constructs, or as part of a
+They cannot be used meaningfully in loop-like constructs, or as part of a
 larger expression sequence, e.g
 \bprog
    allocatemem(); x = 1;   \\@com This will not set \kbd{x}!
@@ -14644,7 +17398,7 @@ larger expression sequence, e.g
 In fact, all loops are immediately exited, user functions terminated, and
 the rest of the sequence following \kbd{allocatemem()} is silently
 discarded, as well as all pending sequences of instructions. We just go on
-reading the next instruction sequence from the file we're in (or from the
+reading the next instruction sequence from the file we are in (or from the
 user). In particular, we have the following possibly unexpected behavior: in
 \bprog
    read("file.gp"); x = 1
@@ -14652,21 +17406,14 @@ user). In particular, we have the following possibly unexpected behavior: in
 the \kbd{x = 1} is never executed, since all pending instructions in the
 current sequence are discarded.
 
-The technical reason is that this routine moves the stack, so temporary
-objects created during the current expression evaluation are not correct
-anymore. (In particular byte-compiled expressions, which are allocated on
-the stack.) To avoid accessing obsolete pointers to the old stack, this
-routine ends by a \kbd{longjmp}.
+The reason for these unfortunate side-effects is that, with
+\kbd{parisizemax} disabled, increasing the stack size physically
+moves the stack, so temporary objects created during the current expression
+evaluation are not correct anymore. (In particular byte-compiled expressions,
+which are allocated on the stack.) To avoid accessing obsolete pointers to
+the old stack, this routine ends by a \kbd{longjmp}.
 
-\misctitle{Remark} If the operating system cannot allocate the desired
-$x$ bytes, a loop halves the allocation size until it succeeds:
-\bprog
-? allocatemem(5*10^10)
- ***   Warning: not enough memory, new stack 50000000000.
- ***   Warning: not enough memory, new stack 25000000000.
- ***   Warning: not enough memory, new stack 12500000000.
- ***   Warning: new stack size = 6250000000 (5960.464 Mbytes).
- at eprog
+The library syntax is \fun{void}{gp_allocatemem}{GEN s = NULL}.
 
 \subsec{apply$(f, A)$}\kbdsidx{apply}\label{se:apply}
 Apply the \typ{CLOSURE} \kbd{f} to the entries of \kbd{A}. If \kbd{A}
@@ -14748,20 +17495,42 @@ The string \var{str} is the name of an external command (i.e.~one you
 would type from your UNIX shell prompt). This command is immediately run and
 its output fed into \kbd{gp}, just as if read from a file.
 
+The library syntax is \fun{GEN}{gpextern}{const char *str}.
+
 \subsec{externstr$(\var{str})$}\kbdsidx{externstr}\label{se:externstr}
 The string \var{str} is the name of an external command (i.e.~one you
 would type from your UNIX shell prompt). This command is immediately run and
 its output is returned as a vector of GP strings, one component per output
 line.
 
+The library syntax is \fun{GEN}{externstr}{const char *str}.
+
+\subsec{fold$(f, A)$}\kbdsidx{fold}\label{se:fold}
+Apply the \typ{CLOSURE} \kbd{f} of arity $2$ to the entries of \kbd{A}
+to return \kbd{f(\dots f(f(A[1],A[2]),A[3])\dots ,A[\#A])}.
+\bprog
+? fold((x,y)->x*y, [1,2,3,4])
+%1 = 24
+? fold((x,y)->[x,y], [1,2,3,4])
+%2 = [[[1, 2], 3], 4]
+? fold((x,f)->f(x), [2,sqr,sqr,sqr])
+%3 = 256
+? fold((x,y)->(x+y)/(1-x*y),[1..5])
+%4 = -9/19
+? bestappr(tan(sum(i=1,5,atan(i))))
+%5 = -9/19
+ at eprog
+\synt{genfold}{void *E, GEN (*fun)(void*,GEN, GEN), GEN A}.
+
 \subsec{getabstime$()$}\kbdsidx{getabstime}\label{se:getabstime}
-Returns the time (in milliseconds) elapsed since \kbd{gp} startup. This
-provides a reentrant version of \kbd{gettime}:
+Returns the CPU time (in milliseconds) elapsed since \kbd{gp} startup.
+This provides a reentrant version of \kbd{gettime}:
 \bprog
 my (t = getabstime());
 ...
 print("Time: ", getabstime() - t);
 @eprog
+For a version giving wall-clock time, see \tet{getwalltime}.
 
 The library syntax is \fun{long}{getabstime}{}.
 
@@ -14793,14 +17562,27 @@ bytes used up to now on the stack. Useful mainly for debugging purposes.
 The library syntax is \fun{long}{getstack}{}.
 
 \subsec{gettime$()$}\kbdsidx{gettime}\label{se:gettime}
-Returns the time (in milliseconds) elapsed since either the last call to
+Returns the CPU time (in milliseconds) used since either the last call to
 \kbd{gettime}, or to the beginning of the containing GP instruction (if
 inside \kbd{gp}), whichever came last.
 
 For a reentrant version, see \tet{getabstime}.
 
+For a version giving wall-clock time, see \tet{getwalltime}.
+
 The library syntax is \fun{long}{gettime}{}.
 
+\subsec{getwalltime$()$}\kbdsidx{getwalltime}\label{se:getwalltime}
+Returns the time (in milliseconds) elapsed since the UNIX Epoch
+(1970-01-01 00:00:00 (UTC)).
+\bprog
+my (t = getwalltime());
+...
+print("Time: ", getwalltime() - t);
+ at eprog
+
+The library syntax is \fun{GEN}{getwalltime}{}.
+
 \subsec{global$(\var{list} \var{of} \var{variables})$}\kbdsidx{global}\label{se:global}
 Obsolete. Scheduled for deletion.
 % \syn{NO}
@@ -14823,6 +17605,8 @@ present version 2.19 of \kbd{pari.el}, when using \kbd{gp} under GNU Emacs (see
 which ends with the same prompt as any of the previous ones (a \kbd{"? "}
 will do for instance).
 
+The library syntax is \fun{GEN}{gp_input}{}.
+
 \subsec{install$(\var{name},\var{code},\{\var{gpname}\},\{\var{lib}\})$}\kbdsidx{install}\label{se:install}
 Loads from dynamic library \var{lib} the function \var{name}. Assigns to it
 the name \var{gpname} in this \kbd{gp} session, with \emph{prototype}
@@ -14940,6 +17724,54 @@ functions.
 
 The library syntax is \fun{void}{kill0}{const char *sym}.
 
+\subsec{localprec$(p)$}\kbdsidx{localprec}\label{se:localprec}
+Set the real precision to $p$ in the dynamic scope. All computations
+are performed as if \tet{realprecision} was $p$:
+transcendental constants (e.g.~\kbd{Pi}) and
+conversions from exact to floating point inexact data use $p$ decimal
+digits, as well as iterative routines implicitly using a floating point
+accuracy as a termination criterion (e.g.~\tet{solve} or \tet{intnum}).
+But \kbd{realprecision} itself is unaffected
+and is ``unmasked'' when we exit the dynamic (\emph{not} lexical) scope.
+In effect, this is similar to
+\bprog
+my(prec = default(realprecision));
+default(realprecision,p);
+...
+default(realprecision, prec);
+ at eprog\noindent but is both less cumbersome, cleaner (no need to manipulate
+a global variable, which in fact never changes and is only temporarily masked)
+and more robust: if the above computation is interrupted or an exception
+occurs, \kbd{realprecision} will not be restored as intended.
+
+Such \kbd{localprec} statements can be nested, the innermost one taking
+precedence as expected. Beware that \kbd{localprec} follows the semantic of
+\tet{local}, not \tet{my}: a subroutine called from \kbd{localprec} scope
+uses the local accuracy:
+\bprog
+? f()=precision(1.);
+? f()
+%2 = 38
+? localprec(19); f()
+%3 = 19
+ at eprog\noindent
+\misctitle{Warning} Changing \kbd{realprecision} itself in programs is
+now deprecated in favor of \kbd{localprec}. Think about the
+\kbd{realprecision} default as an interactive command for the \kbd{gp}
+interpreter, best left out of GP programs. Indeed, the above rules
+imply that mixing both constructs yields surprising results:
+\bprog
+? \p38
+? localprec(19); default(realprecision,100);  Pi
+%1 = 3.141592653589793239
+? \p
+    realprecision = 115 significant digits (100 digits displayed)
+ at eprog\noindent Indeed, \kbd{realprecision} itself is ignored within
+\kbd{localprec} scope, so \kbd{Pi} is computed to a low accuracy. And when
+we leave \kbd{localprec} scope, \kbd{realprecision} only regains precedence,
+it is not ``restored'' to the original value.
+%\syn{NO}
+
 \subsec{print$(\{\var{str}\}*)$}\kbdsidx{print}\label{se:print}
 Outputs its (string) arguments in raw format, ending with a newline.
 %\syn{NO}
@@ -15187,11 +18019,15 @@ In case the file you read in contains an \tet{allocatemem} statement (to be
 generally avoided), you should leave \kbd{read} instructions by themselves,
 and not part of larger instruction sequences.
 
+The library syntax is \fun{GEN}{gp_read_file}{const char *filename}.
+
 \subsec{readstr$(\{\var{filename}\})$}\kbdsidx{readstr}\label{se:readstr}
 Reads in the file \var{filename} and return a vector of GP strings,
 each component containing one line from the file. If \var{filename} is
 omitted, re-reads the last file that was fed into \kbd{gp}.
 
+The library syntax is \fun{GEN}{readstr}{const char *filename}.
+
 \subsec{readvec$(\{\var{filename}\})$}\kbdsidx{readvec}\label{se:readvec}
 Reads in the file
 \var{filename} (subject to string expansion). If \var{filename} is
@@ -15299,6 +18135,8 @@ executed, its output written to the standard output (this won't get into your
 logfile), and control returns to the PARI system. This simply calls the C
 \kbd{system} command.
 
+The library syntax is \fun{void}{gpsystem}{const char *str}.
+
 \subsec{trap$(\{e\}, \{\var{rec}\}, \var{seq})$}\kbdsidx{trap}\label{se:trap}
 THIS FUNCTION IS OBSOLETE: use \tet{iferr}, which has a nicer and much
 more powerful interface. For compatibility's sake we now describe the
@@ -15582,7 +18420,8 @@ computes the class numbers in parallel.
 %SECTION: programming/parallel
 
 \section{GP defaults}
-\label{se:gp_defaults} This section documents the GP defaults
+\label{se:gp_defaults} This section documents the GP defaults, be sure to
+check out \tet{parisize} and \tet{parisizemax} !
 
 
 \subsec{TeXstyle}\kbdsidx{TeXstyle}\label{se:def,TeXstyle}
@@ -15654,45 +18493,7 @@ documentation.
 The default value is \kbd{""} (no colors).
 
 \subsec{compatible}\kbdsidx{compatible}\label{se:def,compatible}
-The GP function names and syntax
-have changed tremendously between versions 1.xx and 2.00. To help you cope
-with this we provide some kind of backward compatibility, depending on the
-value of this default:
-
-\quad \kbd{compatible} = 0: no backward compatibility. In this mode, a very
-handy function, to be described in \secref{se:whatnow}, is \kbd{whatnow},
-which tells you what has become of your favorite functions, which \kbd{gp}
-suddenly can't seem to remember.
-
-\quad \kbd{compatible} = 1: warn when using obsolete functions, but
-otherwise accept them. The output uses the new conventions though, and
-there may be subtle incompatibilities between the behavior of former and
-current functions, even when they share the same name (the current function
-is used in such cases, of course!). We thought of this one as a transitory
-help for \kbd{gp} old-timers. Thus, to encourage switching to \kbd{compatible}=0,
-it is not possible to disable the warning.
-
-\quad \kbd{compatible} = 2: use only the old function naming scheme (as
-used up to version 1.39.15), but \emph{taking case into account}. Thus
-\kbd{I} (${}=\sqrt{-1}$) is not the same as \kbd{i} (user variable, unbound
-by default), and you won't get an error message using \kbd{i} as a loop
-index as used to be the case.
-
-\quad \kbd{compatible} = 3: try to mimic exactly the former behavior. This
-is not always possible when functions have changed in a fundamental way.
-But these differences are usually for the better (they were meant to,
-anyway), and will probably not be discovered by the casual user.
-
-One adverse side effect is that any user functions and aliases that have
-been defined \emph{before} changing \kbd{compatible} will get erased if this
-change modifies the function list, i.e.~if you move between groups
-$\{0,1\}$ and $\{2,3\}$ (variables are unaffected). We of course strongly
-encourage you to try and get used to the setting \kbd{compatible}=0.
-
-Note that the default \tet{new_galois_format} is another compatibility setting,
-which is completely independent of \kbd{compatible}.
-
-The default value is \kbd{0}.
+OBSOLETE. This default is now a no-op.
 
 \subsec{datadir}\kbdsidx{datadir}\label{se:def,datadir}
 The name of directory containing the optional data files. For now,
@@ -15940,17 +18741,33 @@ The default value is \kbd{1} (\var{prettymatrix}).
 
 \subsec{parisize}\kbdsidx{parisize}\label{se:def,parisize}
 \kbd{gp}, and in fact any program using the PARI
-library, needs a \tev{stack} in which to do its computations. \kbd{parisize}
-is the stack size, in bytes. It is strongly recommended you increase this
-default (using the \kbd{-s} command-line switch, or a \tet{gprc}) if you can
-afford it. Don't increase it beyond the actual amount of RAM installed on
-your computer or \kbd{gp} will spend most of its time paging.
-
-In case of emergency, you can use the \tet{allocatemem} function to
-increase \kbd{parisize}, once the session is started.
+library, needs a \tev{stack} in which to do its computations; \kbd{parisize}
+is the stack size, in bytes. It is recommended to increase this
+default using a \tet{gprc}, to the value you believe PARI should be happy
+with, given your typical computation. We strongly recommend to also
+set \tet{parisizemax} to a much larger value, about what you believe your
+machine can stand: PARI will then try to fit its computations within about
+\kbd{parisize} bytes, but will increase the stack size if needed (up to
+\kbd{parisizemax}). Once the memory intensive computation is over, PARI
+will restore the stack size to the originally requested \kbd{parisize}.
 
 The default value is 4M, resp.~8M on a 32-bit, resp.~64-bit machine.
 
+\subsec{parisizemax}\kbdsidx{parisizemax}\label{se:def,parisizemax}
+\kbd{gp}, and in fact any program using the PARI library, needs a
+\tev{stack} in which to do its computations.  If non-zero,  \kbd{parisizemax}
+is the maximum size the stack can grow to, in bytes.  If zero, the stack will
+not automatically grow, and will be limited to the value of \kbd{parisize}.
+
+We strongly recommend to set \tet{parisizemax} to a non-zero value, about
+what you believe your machine can stand: PARI will then try to fit its
+computations within about \kbd{parisize} bytes, but will increase the stack
+size if needed (up to \kbd{parisizemax}). Once the memory intensive
+computation is over, PARI will restore the stack size to the originally
+requested \kbd{parisize}.
+
+The default value is $0$.
+
 \subsec{path}\kbdsidx{path}\label{se:def,path}
 This is a list of directories, separated by colons ':'
 (semicolons ';' in the DOS world, since colons are preempted for drive names).
@@ -16156,14 +18973,7 @@ does not affect the behavior of previously defined functions.
 The default value is \kbd{0}.
 
 \subsec{strictmatch}\kbdsidx{strictmatch}\label{se:def,strictmatch}
-This toggle is either 1 (on) or 0 (off). If on, unused characters after a
-sequence has been
-processed will produce an error. Otherwise just a warning is printed. This
-can be useful when you are unsure how many parentheses you have to close
-after complicated nested loops. Please do not use this; find a decent
-text-editor instead.
-
-The default value is \kbd{1}.
+OBSOLETE. This toggle is now a no-op.
 
 \subsec{threadsize}\kbdsidx{threadsize}\label{se:def,threadsize}
 In parallel mode, each thread needs its own private \tev{stack} in which
@@ -16175,6 +18985,17 @@ If set to $0$, the value used is the same as \kbd{parisize}.
 
 The default value is $0$.
 
+\subsec{threadsizemax}\kbdsidx{threadsizemax}\label{se:def,threadsizemax}
+In parallel mode, each threads needs its own private \tev{stack} in which
+to do its computations, see \kbd{parisize}. This value determines the maximal
+size in bytes of the stacks of each thread, so the total memory allocated will
+be between $\kbd{parisize}+\kbd{nbthreads}\times\kbd{threadsize}$. and
+$\kbd{parisize}+\kbd{nbthreads}\times\kbd{threadsizemax}$.
+
+If set to $0$, the value used is the same as \kbd{threadsize}.
+
+The default value is $0$.
+
 \subsec{timer}\kbdsidx{timer}\label{se:def,timer}
 This toggle is either 1 (on) or 0 (off). Every instruction sequence
 in the gp calculator (anything ended by a newline in your input) is timed,
diff --git a/doc/usersch4.tex b/doc/usersch4.tex
index 907adb0..c2014dc 100644
--- a/doc/usersch4.tex
+++ b/doc/usersch4.tex
@@ -705,22 +705,25 @@ the initial copy (on the other hand, it is less cache friendly).
 A most important usage is ``random'' garbage collection during loops
 whose size requirements we cannot (or do not bother to) control in advance:
 \bprog
-  pari_sp ltop = avma, limit = stack_lim(avma, 1);
+  pari_sp av = avma;
   GEN x, y;
   while (...)
   {
     garbage(); x = anything();
     garbage(); y = anything(); garbage();
-    if (avma < limit) /*@Ccom memory is running low (half spent since entry) */
-      gerepileall(ltop, 2, &x, &y);
+    if (gc_needed(av,1)) /*@Ccom memory is running low (half spent since entry) */
+      gerepileall(av, 2, &x, &y);
   }
 @eprog
 \noindent Here we assume that only \kbd{x} and \kbd{y} are needed from one
 iteration to the next. As it would be costly to call gerepile once for each
-iteration, we only do it when it seems to have become necessary. The macro
-\tet{stack_lim}\kbd{(avma,$n$)} denotes an address where $2^{n-1} /
-(2^{n-1}+1)$ of the remaining stack space is exhausted ($1/2$ for $n=1$,
-$2/3$ for $n=2$).
+iteration, we only do it when it seems to have become necessary.
+
+More precisely, the macro \tet{stack_lim}\kbd{(av,$n$)} denotes an address
+where $2^{n-1} / (2^{n-1}+1)$ of the remaining stack space since reference
+point \kbd{av} is exhausted ($1/2$ for $n=1$, $2/3$ for $n=2$). The test
+\tet{gc_needed}\kbd{(av,$n$)} becomes true whenever \kbd{avma} drops below
+that address.
 
 \subsec{Comments}
 
@@ -835,9 +838,7 @@ there are four \tet{varargs} functions:
 
 \fun{GEN}{mkintn}{long n, ...}
 returns the non-negative \typ{INT} whose development in base $2^{32}$
-is given by the following $n$ words (\kbd{unsigned long}). It is assumed that
-all such arguments are less than $2^{32}$ (the actual \kbd{sizeof(long)} is
-irrelevant, the behavior is also as above on $64$-bit machines).
+is given by the following $n$ 32bit-words (\kbd{unsigned int}).
 \bprog
   mkintn(3, a2, a1, a0);
 @eprog
@@ -1427,7 +1428,12 @@ The coefficients \kbd{z[2]}, \kbd{z[3]},\dots \kbd{z[lg(z)-1]} point to
 the coefficients of \kbd{z} in ascending order. As for polynomials
 (see remark there), the sign of a \typ{SER} is $0$ if and only all
 its coefficients are equal to $0$. (The leading coefficient cannot be an
-integer $0$.)
+integer $0$.) A series whose coefficients are integers equal to zero
+is represented as $O(x^n)$ (\kbd{zeroser}$(\var{vx},n)$).
+A series whose coefficients are exact zeroes, but not all of
+them integers  (e.g. an \typ{INTMOD} such as \kbd{Mod(0,2)}) is
+represented as $z*x^{n-1} +O(x^n)$, where $z$ is the $0$ of the
+base ring, as per \tet{RgX_get_0}.
 
 Note that the exponent of a power series can be negative, i.e.~we are
 then dealing with a Laurent series (with a finite number of negative
@@ -1487,6 +1493,21 @@ functions to create or to evaluate \typ{CLOSURE}s are documented in
 
 \fun{long}{closure_arity}{GEN C} returns the arity of the \typ{CLOSURE}.
 
+\fun{long}{closure_is_variadic}{GEN C} returns $1$ if the closure \kbd{C} is
+variadic, $0$ else.
+
+\subsec{Type \typ{INFINITY} (infinity)}\kbdsidx{t_INFINITY}\sidx{infinity}
+
+This type has a single \typ{INT} component, which is either $1$ or $-1$,
+corresponding to $+\infty$ and $-\infty$ respectively.
+
+\fun{GEN}{mkmoo}{} returns $-\infty$
+
+\fun{GEN}{mkoo}{} returns $\infty$
+
+\fun{long}{inf_get_sign}{GEN x} returns $1$ if $x$ is $+\infty$, and $-1$
+if $x$ is $-\infty$.
+
 \subsec{Type \typ{LIST} (list)}\kbdsidx{t_LIST}\sidx{list}
 this type was introduced for specific \kbd{gp} use and is rather inefficient
 compared to a straightforward linked list implementation (it requires more
@@ -1552,17 +1573,27 @@ situation.
 Some initializations are needed before you can use a given integer $v$ as a
 variable number.
 
-Initially, this is done for $0$ (the variable \kbd{x} under \kbd{gp}), and
-\tet{MAXVARN}, which is there to address the need for a ``temporary'' new
-variable in library mode and cannot be input under \kbd{gp}. No documented
-library function can create from scratch an object involving \tet{MAXVARN}
-(of course, if the operands originally involve \kbd{MAXVARN}, the function
-abides). We call the latter type a ``temporary variable''. The regular
-variables meant to be used in regular objects, are called ``user
-variables\sidx{variable (user)}''.
+Initially, this is done for $0$ and $1$ (the variables \kbd{x} and
+\kbd{y} under \kbd{gp}), and $2,\dots,9$ (printed as \kbd{t2}, \dots
+\kbd{t9}), with decreasing priority.
 
 \subsubsec{User variables}\sidx{variable (user)} When the program starts,
-\kbd{x} is the only user variable (number~$0$). To define new ones, use
+\kbd{x} (number~$0$) and \kbd{y} (number~$1$) are the only available
+variables, numbers $2$ to $9$ (decreasing priority) are reserved for building
+polynomials with predictable priorities.
+
+To define further ones, you may use
+
+\fun{GEN}{varhigher}{const char *s}
+
+\fun{GEN}{varlower}{const char *s}
+
+to recover a monomial of degree $1$ in a new variable, which is guaranteed
+to have higer (resp.~lower) priority than all existing ones at the
+time of the function call. The variable is printed as $s$, but is not part
+of GP's interpreter: it is not a symbol bound to a value.
+
+On the other hand
 
 \fun{long}{fetch_user_var}{char *s}: inspects the user variable whose name is
 the string pointed to by \kbd{s}, creating it if needed, and returns its
@@ -1572,7 +1603,9 @@ long v = fetch_user_var("y");
 GEN gy = pol_x(v);
 @eprog\noindent
 The function raises an exception if the name is already in use for an
-\tet{install}ed or built-in function, or an alias.
+\tet{install}ed or built-in function, or an alias. This function
+is mostly useless since it returns a variable with unpredictable priority.
+Don't use it to create new variables.
 
 \misctitle{Caveat} You can use \tet{gp_read_str}
 (see~\secref{se:gp_read_str}) to execute a GP command and create GP
@@ -1597,24 +1630,22 @@ that this may not be the same as \kbd{pol\_x(v)} if assignments have been
 performed in the interpreter.
 
 \subsubsec{Temporary variables}\sidx{variable (temporary)}
-\kbd{MAXVARN} is available, but is better left to PARI internal functions
-(some of which do not check that \kbd{MAXVARN} is free for them to use,
-which can be considered a bug). You can create more temporary variables
-using
+You can create temporary variables using
+
+\fun{long}{fetch_var}{}
+returns a new variable with \emph{lower} priority than any variable currently
+in use.
 
-\fun{long}{fetch_var}{}\label{se:fetch_var}
+\fun{long}{fetch_var_higher}{}
+returns a new variable with \emph{higher} priority than any variable
+currently in use.
 
 \noindent
-This returns a variable number which is guaranteed to be unused by the
-library at the time you get it and as long as you do not delete it (we will
-see how to do that shortly). This has \emph{higher} priority than any
-temporary variable produced so far (\kbd{MAXVARN} is assumed to be the first
-such). After the statement \kbd{v = fetch\_var()}, you can use
+After the statement \kbd{v = fetch\_var()}, you can use
 \kbd{pol\_1(v)} and \kbd{pol\_x(v)}. The variables created in this way have no
 identifier assigned to them though, and are printed as
-\kbd{\#<\text{number}>}, except for \kbd{MAXVARN} which is printed
-as~\kbd{\#}. You can assign a name to a temporary variable, after creating
-it, by calling the function
+\kbd{t\text{number}}. You can assign a name to a temporary variable, after
+creating it, by calling the function
 
 \fun{void}{name_var}{long n, char *s}
 
@@ -1622,8 +1653,9 @@ it, by calling the function
 represent the variable number~\kbd{n}. The GP parser will \emph{not}
 recognize it by that name, however, and calling this on a variable known
 to~\kbd{gp} raises an error. Temporary variables are meant to be used as free
-variables, and you should never assign values or functions to them as you
-would do with variables under~\kbd{gp}. For that, you need a user variable.
+variables to build polynomials and power series, and you should never assign
+values or functions to them as you would do with variables under~\kbd{gp}.
+For that, you need a user variable.
 
 All objects created by \kbd{fetch\_var} are on the heap and not on the stack,
 thus they are not subject to standard garbage collecting (they are not
@@ -1633,8 +1665,8 @@ not need a variable number anymore, you can delete it using
 \fun{long}{delete_var}{}
 
 \noindent which deletes the \emph{latest} temporary variable created and
-returns the variable number of the previous one (or simply returns 0 if you
-try, in vain, to delete \kbd{MAXVARN}). Of course you should make sure that
+returns the variable number of the previous one (or simply returns 0 if none
+remain). Of course you should make sure that
 the deleted variable does not appear anywhere in the objects you use later
 on. Here is an example:
 
@@ -1651,8 +1683,7 @@ The (dangerous) statement
 \bprog
   while (delete_var()) /*@Ccom empty */;
 @eprog\noindent
-removes all temporary variables in use, except \kbd{MAXVARN} which cannot be
-deleted.
+removes all temporary variables in use.
 
 \section{Input and output}
 
@@ -1665,14 +1696,13 @@ library mode: input and output of PARI objects.
 \noindent
 For \idx{input}, PARI provides a powerful high level function
 which enables you to input your objects as if you were under \kbd{gp}. In fact,
-it \emph{is} essentially the GP syntactical parser, hence you can use it not
-only for input but for (most) computations that you can do under \kbd{gp}.
+it \emph{is} essentially the GP syntactical parser.
 It has the following syntax:\label{se:gp_read_str}
 
 \fun{GEN}{gp_read_str}{const char *s}
 
 \noindent
-Note that \kbd{gp}'s metacommands are not recognized.
+Note that \kbd{gp}'s metacommands \emph{are} recognized.
 
 \misctitle{Note} The obsolete form
 
@@ -2221,7 +2251,7 @@ details.
 collection, hence memory use is quadratic in the size of the inputs instead
 of linear. Here is a better version of that loop:
 \bprog
-  pari_sp av = avma, lim = stack_lim(av,1);
+  pari_sp av = avma;
   ...
   while (!gequal0(b))
   {
@@ -2229,7 +2259,7 @@ of linear. Here is a better version of that loop:
 
     vx = subii(ux, mulii(q, vx));
     ux = v; a = b; b = r;
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
       gerepileall(av, 4, &a, &b, &ux, &vx);
   }
 @eprog
diff --git a/doc/usersch5.tex b/doc/usersch5.tex
index 34b4acb..aedc078 100644
--- a/doc/usersch5.tex
+++ b/doc/usersch5.tex
@@ -166,19 +166,9 @@ it adds to the default set via the calls
   pari_add_module(functions_highlevel);
 @eprog
 
-\fun{void}{pari_add_oldmodule}{entree *mod} adds all the routines in module
-\kbd{mod} to the table of symbols in the interpreter when running in
-"PARI 1.xx compatible" mode (see \kbd{default(compatible)}) . It assumes
-that
-\kbd{pari\_init} has been called.
-
 A GP \kbd{default} is likewise associated to a helper routine, that is run
 when the value is consulted, or changed by \tet{default0} or \tet{setdefault}.
-Such routines are grouped into modules: \tet{functions_default} containing all
-defaults that make sense in libpari context, \tet{functions_gp_rl_default}
-containing defaults that are \kbd{gp}-specific and do not make sense unless
-we use \kbd{libreadline}, and \tet{functions_gp_default} containing all other
-\kbd{gp}-specific defaults.
+Such routines are grouped in the module \tet{functions_default}.
 
 \fun{void}{pari_add_defaults_module}{entree *mod} adds all the defaults in
 module \kbd{mod} to the interpreter. It assumes that \kbd{pari\_init} has
@@ -194,25 +184,64 @@ break loop handler) to the following callbacks, and so can you:
 initialized to \kbd{NULL}. Called with argument $s$ whenever PARI wants
 confirmation for action $s$, for instance in \tet{secure} mode.
 
-\doc{cb_pari_handle_exception}{extern int (*cb_pari_handle_exception)(long)}
+\doc{cb_pari_init_histfile}{void (*cb_pari_init_histfile)(void)}
+initialized to \kbd{NULL}. Called when the \kbd{histfile} default
+is changed. The intent is for that callback to read the file content, append
+it to history in memory, then dump the expanded history to the new
+\kbd{histfile}.
+
+\doc{cb_pari_is_interactive}{int (*cb_pari_is_interactive)(void)};
+initialized to \kbd{NULL}.
+
+\doc{cb_pari_quit}{void (*cb_pari_quit)(long)}
+initialized to a no-op. Called when \kbd{gp} must evaluate the \kbd{quit}
+command.
+
+\doc{cb_pari_start_output}{void (*cb_pari_start_output)(void)}
+initialized to \kbd{NULL}.
+
+\doc{cb_pari_handle_exception}{int (*cb_pari_handle_exception)(long)}
 initialized to \kbd{NULL}. If not \kbd{NULL}, this routine is called with
 argument $-1$ on \kbd{SIGINT}, and argument \kbd{err} on error \kbd{err}. If
 it returns a non-zero value, the error or signal handler returns, in effect
 further ignoring the error or signal, otherwise it raises a fatal error.
+A possible simple-minded handler, used by the \kbd{gp} interpreter, is
+
+\fun{int}{gp_handle_exception}{long err} if the \kbd{breakloop}
+default is enabled and \tet{cb_pari_break_loop} is not \kbd{NULL}, we call it
+with \kbd{err} argument and return the result.
+
+\doc{cb_pari_err_handle}{int (*cb_pari_err_handle)(GEN)}
+If not \kbd{NULL}, this routine is called with a \typ{ERROR} argument
+from \kbd{pari\_err}. If it returns a non-zero value, the error returns, in
+effect further ignoring the error, otherwise it raises a fatal error.
+
+The default behaviour is to print a descriptive error
+message (display the error), then return 0, thereby raising a fatal error.
+This differs from \tet{cb_pari_handle_exception} in that the
+function is not called on \kbd{SIGINT} (which do not generate a \typ{ERROR}),
+only from \kbd{pari\_err}. Use \tet{cb_pari_sigint} if you need to handle
+\kbd{SIGINT} as well.
+
+\doc{cb_pari_break_loop}{int (*cb_pari_break_loop)(int)}
+initialized to \kbd{NULL}.
 
 \doc{cb_pari_sigint}{void (*cb_pari_sigint)(void)}.
 Function called when we receive \kbd{SIGINT}. By default, raises
 \bprog
   pari_err(e_MISC, "user interrupt");
- at eprog
+ at eprog\noindent A possible simple-minded variant, used by the
+\kbd{gp} interpreter, is
+
+\fun{void}{gp_sigint_fun}{void}
 
-\doc{cb_pari_pre_recover}{extern void (*cb_pari_err_recover)(long)}
+\doc{cb_pari_pre_recover}{void (*cb_pari_err_recover)(long)}
 initialized to \kbd{NULL}. If not \kbd{NULL}, this routine is called just
 before PARI cleans up from an error. It is not required to return.  The error
 number is passed as argument, unless the PARI stack has been destroyed
 (\kbd{allocatemem}), in which case $-1$ is passed.
 
-\doc{cb_pari_err_recover}{extern void (*cb_pari_err_recover)(long)}
+\doc{cb_pari_err_recover}{void (*cb_pari_err_recover)(long)}
 initialized to \kbd{pari\_exit()}. This callback must not return.
 It is called after PARI has cleaned-up from an error. The error number is
 passed as argument, unless the PARI stack has been destroyed, in which case
@@ -235,7 +264,7 @@ non-$0$ result otherwise. May print a help message.
 It is used by the function \tet{gpinstall} to locate the PARI library when
 searching for symbols.  This should only be useful on Windows.
 
-\misctitle{Utility function}
+\subsec{Utility functions}
 
 \fun{void}{pari_ask_confirm}{const char *s} raise an error if the
 callback \tet{cb_pari_ask_confirm} is \kbd{NULL}. Otherwise
@@ -243,6 +272,65 @@ calls
 \bprog
   cb_pari_ask_confirm(s);
 @eprog
+
+\fun{char*}{gp_filter}{const char *s} pre-processor for the GP
+parser: filter out whitespace and GP comments from $s$.
+
+\fun{GEN}{pari_compile_str}{const char *s} low-level form of
+\tet{compile_str}: assumes that $s$ does not contain spaces or GP comments and
+returns the closure associated to the GP expression $s$. Note
+that GP metacommands are not recognized.
+
+\fun{int}{gp_meta}{const char *s, int ismain} low-level component of
+\tet{gp_read_str}: assumes that $s$ does not contain spaces or GP comments and
+try to interpret $s$ as a GP metacommand (e.g. starting by \kbd{\bs} or
+\kbd{?}). If successful, execute the metacommand and return $1$; otherwise
+return $0$. The \kbd{ismain} parameter modifies the way \kbd{\bs r} commands
+are handled: if non-zero, act as if the file contents were entered via
+standard input (i.e. call \tet{switchin} and divert \tet{pari_infile});
+otherwise, simply call \tet{gp_read_file}.
+
+\fun{void}{pari_hit_return}{void} wait for the use to enter \kbd{\bs n}
+via standard input.
+
+\fun{void}{gp_load_gprc}{void} read and execute the user's \kbd{GPRC} file.
+
+\fun{void}{pari_center}{const char *s} print $s$, centered.
+
+\fun{void}{pari_print_version}{void} print verbose version information.
+
+\fun{const char*}{gp_format_time}{long t} format a delay of $t$ ms
+suitable for \kbd{gp} output, with \kbd{timer} set.
+
+\fun{const char*}{gp_format_prompt}{const char *p} format a prompt $p$
+suitable for \kbd{gp} prompting (includes colors and protecting ANSI escape
+sequences for readline).
+
+\fun{void}{pari_alarm}{long s} set an alarm after $s$ seconds (raise an
+\tet{e_ALARM} exception).
+
+\fun{void}{gp_help}{const char *s, long flag} print help for $s$, depending
+on the value of \fl:
+
+\item \tet{h_REGULAR}, basic help (\kbd{?});
+
+\item \tet{h_LONG}, extended help (\kbd{??});
+
+\item \tet{h_APROPOS}, a propos help (\kbd{??}).
+
+\fun{void}{gp_echo_and_log}{const char *p, const char *s} given a prompt
+$p$ and associated input command $s$, update logfile and possibly
+print on standard output if \tet{echo} is set and we are not in interactive
+mode. The callback \tet{cb_pari_is_interactive} must be set to a sensible
+value.
+
+\fun{void}{gp_alarm_handler}{int sig} the \kbd{SIGALRM} handler
+set by the \kbd{gp} interpreter.
+
+\fun{void}{print_fun_list}{char **list, long n}
+print all elements of \kbd{list} in columns, pausing (hit return)
+every $n$ lines. \kbd{list} is \kbd{NULL} terminated.
+
 \subsec{Saving and restoring the GP context}
 
 \fun{void}{gp_context_save}{struct gp_context* rec} save the current GP
@@ -761,7 +849,7 @@ These are \kbd{double} approximations to useful constants:
 
 \noindent \tet{LOG2_10}: $\log 10 / \log 2$.
 
-\noindent \tet{PI}: $\pi$.
+\noindent \tet{M_PI}: $\pi$.
 
 \section{Iterating over small primes, low-level interface}
 \label{se:primetable}
@@ -1232,17 +1320,24 @@ and \kbd{nvar+1}--\kbd{max\_avail-1} (pool of free variable numbers).
 variable counters \kbd{nvar} and \kbd{max\_avail}, notwithstanding existing
 variables! In effect, this even deletes \kbd{x}. Don't use it.
 
+\fun{void}{pari_var_close}{void} associated destructor, called by
+\kbd{pari\_close}.
+
 \fun{long}{pari_var_next}{}: returns \kbd{nvar}, the number of the next user
 variable we can create.
 
 \fun{long}{pari_var_next_temp}{} returns \kbd{max\_avail}, the number of the
 next temp variable we can create.
 
-\fun{void}{pari_var_create}{entree *ep} low-level initialization of an
-\kbd{EpVAR}.
+\fun{long}{pari_var_create}{entree *ep} low-level initialization of an
+\kbd{EpVAR}. Return the associated (new) variable number.
 
-\noindent The obsolete function \fun{long}{manage_var}{long n, entree *ep}
-is kept for backward compatibility only. Don't use it.
+\fun{GEN}{vars_sort_inplace}{GEN z} given a \typ{VECSMALL} $z$ of variable
+numbers, sort $z$ in place according to variable priorities (highest priority
+comes first).
+
+\fun{GEN}{vars_to_RgXV}{GEN h} given a \typ{VECSMALL} $z$ of variable numbers,
+return the \typ{VEC} of \kbd{pol\_x}$(z[i])$.
 
 \subsec{User variables}
 
@@ -1250,11 +1345,6 @@ is kept for backward compatibility only. Don't use it.
 is \kbd{s}, creating it is needed (and using an existing variable otherwise).
 Returns its variable number.
 
-\fun{entree*}{fetch_named_var}{char *s} as \kbd{fetch\_user\_var}, but
-returns an \kbd{entree*} suitable for inclusion in the interpreter hashlists
-of symbols, not a variable number. \kbd{fetch\_user\_var} is a trivial
-wrapper.
-
 \fun{GEN}{fetch_var_value}{long v} returns a shallow copy of the
 current value of the variable numbered $v$. Return \kbd{NULL} for a temporary
 variable.
@@ -1273,8 +1363,7 @@ the number of previous one.
 
 \fun{void}{name_var}{long n, char *s} rename temporary variable number
 \kbd{n} to \kbd{s}; mostly useful for nicer printout. Error when trying to
-rename a user variable: use \kbd{fetch\_named\_var} to get a user variable of
-the right name in the first place.
+rename a user variable.
 
 \section{Adding functions to PARI}
 \subsec{Nota Bene}
@@ -1359,6 +1448,7 @@ char of the code string:
 %
 \+& \kbd{i} & return \kbd{int}\cr
 \+& \kbd{l} & return \kbd{long}\cr
+\+& \kbd{u} & return \kbd{ulong}\cr
 \+& \kbd{v} & return \kbd{void}\cr
 \+& \kbd{m} & return a \kbd{GEN} which is not \kbd{gerepile}-safe.\cr
 
@@ -1372,6 +1462,7 @@ input arguments they describe:
 \+& \kbd{G} & \kbd{GEN}\cr
 \+& \kbd{\&}& \kbd{*GEN}\cr
 \+& \kbd{L} & \kbd{long} (we implicitly typecast \kbd{int} to \kbd{long})\cr
+\+& \kbd{U} & \kbd{ulong} \cr
 \+& \kbd{V} & loop variable\cr
 \+& \kbd{n} & variable, expects a \idx{variable number} (a \kbd{long}, not an
 \kbd{*entree})\cr
@@ -1403,6 +1494,8 @@ do not use the resulting \kbd{long}\cr
 \+& \kbd{p} &  real precision (default \kbd{realprecision})\cr
 \+& \kbd{P} &  series precision (default \kbd{seriesprecision},
  global variable \kbd{precdl} for the library)\cr
+\+& \kbd{C} &  lexical context (internal, for \kbd{eval},
+               see \kbd{localvars\_read\_str})\cr
 
 \noindent\item Syntax requirements, used by functions like
  \kbd{for}, \kbd{sum}, etc.:
@@ -1754,6 +1847,9 @@ representative of $x y$ modulo $m$.
 
 \fun{ulong}{Fl_triple}{ulong x, ulong m} returns $3x$ modulo $m$.
 
+\fun{ulong}{Fl_halve}{ulong x, ulong m} returns $z$ such that $2\*z = x$ modulo
+$m$ assuming such $z$ exists.
+
 \fun{ulong}{Fl_sqr}{ulong x, ulong m} returns the smallest positive
 representative of $x^2$ modulo $m$.
 
@@ -1765,6 +1861,11 @@ mod~$m$, raise an exception.
 positive representative of $x^{-1}$ modulo $m$. If $x$ is not invertible
 mod~$m$, return $0$ (which is ambiguous if $m=1$).
 
+\fun{ulong}{Fl_invgen}{ulong x, ulong m, ulong *pg} set \kbd{*pg} to
+$g = \gcd(x,m)$ and return $u$ (invertible) such that $x u = g$ modulo $m$.
+We have $g = 1$ if and only if $x$ is invertible, and in this case $u$
+is its inverse.
+
 \fun{ulong}{Fl_div}{ulong x, ulong y, ulong m} returns the smallest
 positive representative of $x y^{-1}$ modulo $m$. If $y$ is not invertible
 mod $m$, raise an exception.
@@ -1772,12 +1873,19 @@ mod $m$, raise an exception.
 \fun{ulong}{Fl_powu}{ulong x, ulong n, ulong m} returns the smallest
 positive representative of $x^n$ modulo $m$.
 
+\fun{GEN}{Fl_powers}{ulong x, long n, ulong p} returns
+$[\kbd{x}^0, \dots, \kbd{x}^\kbd{n}]$ modulo $m$, as a \typ{VECSMALL}.
+
 \fun{ulong}{Fl_sqrt}{ulong x, ulong p} returns the square root of \kbd{x}
 modulo \kbd{p} (smallest positive representative). Assumes \kbd{p} to be
 prime, and \kbd{x} to be a square modulo \kbd{p}.
 
+\fun{ulong}{Fl_sqrtl}{ulong x, ulong l, ulong p} returns a $l$-the root of \kbd{x}
+modulo \kbd{p}. Assumes \kbd{p} to be prime and $p \equiv 1 \pmod{l}$, and
+\kbd{x} to be a $l$-th power modulo \kbd{p}.
+
 \fun{ulong}{Fl_order}{ulong a, ulong o, ulong p} returns the order of the
-\typ{Fp} \kbd{a}. It is assumed that \kbd{o} is a multiple of the order of
+\kbd{Fp} \kbd{a}. It is assumed that \kbd{o} is a multiple of the order of
 \kbd{a}, $0$ being allowed (no non-trivial information).
 
 \fun{ulong}{random_Fl}{ulong p} returns a pseudo-random integer uniformly
@@ -1792,6 +1900,50 @@ $p^k$, $k > 1$, assuming $p$ is an odd prime.
 \fun{ulong}{pgener_Fl_local}{ulong p, GEN L}, see \kbd{gener\_Fp\_local},
 \kbd{L} is an \kbd{Flv}.
 
+\subsec{Modular kernel with ``precomputed inverse''}
+
+This is based on an algorithm by T. Grandlund and N. M\"{o}ller in
+``Improved division by invariant integers''
+\url{http://gmplib.org/~tege/division-paper.pdf}.
+
+In the following, we set $B=\B$.
+
+\fun{ulong}{get_Fl_red}{ulong p} returns a pseudo inverse \var{pi} for $p$
+
+\fun{ulong}{divll_pre}{ulong x, ulong p, ulong yi}
+as divll, where $yi$ is the pseudo inverse of $y$.
+
+\fun{ulong}{remll_pre}{ulong u1, ulong u0, ulong p, ulong pi} returns
+the Euclidean remainder of $u_1\*2^B+u_0$ modulo $p$, assuming $pi$ is the
+pseudo inverse of $p$.  This function is faster if $u_1 < p$.
+
+\fun{ulong}{remlll_pre}{ulong u2, ulong u1, ulong u0, ulong p, ulong pi}
+returns the Euclidean remainder of $u_2\*2^{2\*B}+u_1\*2^{B}+u_0$ modulo $p$,
+assuming $pi$ is the pseudo inverse of $p$.
+
+\fun{ulong}{Fl_sqr_pre}{ulong x, ulong p, ulong pi} returns $x^2$ modulo $p$,
+assuming $pi$ is the pseudo inverse of $p$.
+
+\fun{ulong}{Fl_mul_pre}{ulong x, ulong y, ulong p, ulong pi} returns $x\*y$
+modulo $p$, assuming $pi$ is the pseudo inverse of $p$.
+
+\fun{ulong}{Fl_powu_pre}{ulong x, ulong n, ulong p, ulong pi} returns
+$x^n$ modulo $p$, assuming $pi$ is the pseudo inverse of $p$.
+
+\fun{GEN}{Fl_powers_pre}{ulong x, long n, ulong p, ulong pi} returns
+$[\kbd{x}^0, \dots, \kbd{x}^\kbd{n}]$ as a \typ{VECSMALL}, assuming $pi$ is the
+pseudo inverse of $p$.
+
+\fun{ulong}{Fl_sqrt_pre}{ulong x, ulong p, ulong pi} returns a square root
+of $x$ modulo $p$, assuming $pi$ is the pseudo inverse of $p$.
+See \kbd{Fl\_sqrt}.
+
+\fun{ulong}{Fl_sqrtl_pre}{ulong x, ulong l, ulong p, ulong pi}
+returns a $l$-the root of \kbd{x}
+modulo \kbd{p}, assuming $pi$ is the pseudo inverse of $p$,
+$p$ prime and $p \equiv 1 \pmod{l}$, and \kbd{x} to be a $l$-th power modulo
+\kbd{p}.
+
 \subsec{Switching between Fl\_xxx and standard operators}
 
 Even though the \kbd{Fl\_xxx} routines are efficient, they are slower than
@@ -2182,6 +2334,27 @@ shifts the mantissa
 $$f, s[m], s[m+1],\ldots s[M]$$
 right by $n$ bits.
 
+\subsec{From \typ{INT} to bits}
+
+\fun{GEN}{binary_zv}{GEN x} given a \typ{INT} $x$, return a \typ{VECSMALL} of
+bits, from most significant to least significant.
+
+\fun{GEN}{binary_2k}{GEN x, long k} given a \typ{INT} $x$, and
+$k > 0$, return a \typ{VEC} of digits of $x$ in base $2^k$, as \typ{INT}s, from
+most significant to least significant.
+
+\fun{GEN}{binary_2k_zv}{GEN x, long k} given a \typ{INT} $x$, and $0 < k <
+\tet{BITS_IN_LONG}$, return a \typ{VECSMALL} of digits of $x$ in base $2^k$, as
+\typ{ulong}s, from most significant to least significant.
+
+\fun{GEN}{bits_to_int}{GEN x, long l} given a vector $x$ of $l$ bits (as a
+\typ{VECSMALL} or even a pointer to a part of a larger vector, so not a
+proper \kbd{GEN}), return the integer $\sum_{i = 1}^l x[i] 2^{l-i}$, as a
+\typ{INT}.
+
+\fun{ulong}{bits_to_u}{GEN v, long l} same as \tet{bits_to_int}, where
+$l < \tet{BITS_IN_LONG}$, so we can return an \kbd{ulong}.
+
 \subsec{Integer valuation}
 For integers $x$ and $p$, such that $x\neq 0$ and $|p| > 1$, we define
 $v_p(x)$ to be the largest integer exponent $e$ such that $p^e$ divides $x$.
@@ -2739,6 +2912,9 @@ as in the \kbd{div} functions.
 \fun{long}{smodss}{long x, long y} computes the true Euclidean
 remainder of the \kbd{long}~\kbd{x} by a \kbd{long}~\kbd{y}.
 
+\fun{ulong}{umodsu}{long x, ulong y} computes the true Euclidean
+remainder of the \kbd{long}~\kbd{x} by a \kbd{ulong}~\kbd{y}.
+
 \fun{ulong}{umodiu}{GEN x, ulong y} computes the true Euclidean
 remainder of the \typ{INT}~\kbd{x} by the \kbd{ulong}~\kbd{y}.
 
@@ -2771,8 +2947,8 @@ see the technical note in \secref{se:genbinop}.
 \fun{GEN}{powru}{GEN x, ulong n}, assumes $x$ is a \typ{REAL} and returns $x^n$
 (always a \typ{REAL}, even if $n = 0$).
 
-\fun{GEN}{powruvec}{GEN e, ulong n}. Given a \typ{REAL} $e$, return the vector
-of all $e^i$, $1 \leq i \leq n$.
+\fun{GEN}{powersr}{GEN e, long n}. Given a \typ{REAL} $e$, return the vector
+$v$ of all $e^i$, $0 \leq i \leq n$, where $v[i] = e^{i-1}$.
 
 \fun{GEN}{powrshalf}{GEN x, long n}, assumes $x$ is a \typ{REAL} and returns
 $x^{n/2}$ (always a \typ{REAL}, even if $n = 0$).
@@ -2827,10 +3003,17 @@ coefficients such that $\kbd{au} + \kbd{bv} = d$.
 $d$ of \kbd{a} and \kbd{b} and sets \kbd{u}, \kbd{v} to the Bezout coefficients
 such that $\kbd{au} + \kbd{bv} = d$.
 
-\fun{GEN}{ZV_gcdext}{GEN A} given a vector of $n$ integers $A$, returns $[d,
+\fun{GEN}{ZV_extgcd}{GEN A} given a vector of $n$ integers $A$, returns $[d,
 U]$, where $d$ is the GCD of the $A[i]$ and $U$ is a matrix
 in $\text{GL}_n(\Z)$ such that $AU = [0,\dots,0,D]$.
 
+\subsec{Continued fractions and convergents}
+
+\fun{GEN}{ZV_allpnqn}{GEN x} given $x = [a_0, ..., a_n]$ a
+continued fraction from \tet{gboundcf}, $n\geq0$, return all
+convergents as $[P,Q]$, where $P = [p_0,\dots,p_n]$ and $Q =
+[q_0,\dots,q_n]$.
+
 \subsec{Pseudo-random integers}
 These routine return pseudo-random integers uniformly distributed in some
 interval. The all use the same underlying generator which can be seeded and
@@ -2891,6 +3074,9 @@ returns the representative of \kbd{a} in the symmetric residue system.
 \fun{GEN}{Fp_muls}{GEN a, long b, GEN m} returns the product of \kbd{a} by
 \kbd{b} modulo \kbd{m} (smallest non-negative residue).
 
+\fun{GEN}{Fp_halve}{GEN x, GEN m} returns $z$ such that $2\*z = x$ modulo
+$m$ assuming such $z$ exists.
+
 \fun{GEN}{Fp_sqr}{GEN a, GEN m} returns $\kbd{a}^2$ modulo \kbd{m} (smallest
 non-negative residue).
 
@@ -2905,6 +3091,10 @@ allowed Not memory-clean, but suitable for \kbd{gerepileupto}.
 \fun{GEN}{Fp_pow}{GEN x, GEN n, GEN m} returns $\kbd{x}^\kbd{n}$
 modulo \kbd{m} (smallest non-negative residue).
 
+\fun{GEN}{Fp_powers}{GEN x, long n, GEN m} returns
+$[\kbd{x}^0, \dots, \kbd{x}^\kbd{n}]$ modulo \kbd{m} as a \typ{VEC}
+ (smallest non-negative residue).
+
 \fun{GEN}{Fp_inv}{GEN a, GEN m} returns an inverse of \kbd{a} modulo \kbd{m}
 (smallest non-negative residue). Raise an error if \kbd{a} is not invertible.
 
@@ -2931,7 +3121,7 @@ $a^e \equiv g \pmod{p}$. If $e$ does not exist, the result is currently
 undefined.
 
 \fun{GEN}{Fp_order}{GEN a, GEN N, GEN p} returns the order of the
-\typ{Fp} \kbd{a}. If \kbd{N} is non-\kbd{NULL}, it is assumed that \kbd{N}
+\kbd{Fp} \kbd{a}. If \kbd{N} is non-\kbd{NULL}, it is assumed that \kbd{N}
 is a multiple of the order of \kbd{a}, as a \typ{INT} or a
 factorization matrix.
 
@@ -2952,11 +3142,11 @@ $n$-th power modulo \kbd{p}, and $0$ otherwise.
 \typ{INT}s, and \kbd{p} is assumed to be prime. Return \kbd{NULL}
 if \kbd{x} is not a quadratic residue modulo \kbd{p}.
 
-\fun{GEN}{Fp_sqrtn}{GEN x, GEN n, GEN p, GEN *zn} returns an \kbd{n}-th
-root of $\kbd{x}$ modulo \kbd{p} (smallest non-negative residue), where
-\kbd{x}, \kbd{n}, \kbd{p} are \typ{INT}s, and \kbd{p} is assumed to be prime.
-Return \kbd{NULL} if \kbd{x} is not an \kbd{n}-th power residue. Otherwise,
-if \kbd{zn} is non-\kbd{NULL} set it to a primitive \kbd{n}-th root of $1$.
+\fun{GEN}{Fp_sqrtn}{GEN a, GEN n, GEN p, GEN *zn}
+returns \kbd{NULL} if $a$ is not an $n$-th power residue mod $p$.
+Otherwise, returns an $n$-th root of $a$; if \kbd{zn} is non-\kbd{NULL}
+set it to a primitive $m$-th root of 1, $m = \gcd(p-1,n)$ allowing to compute
+all $m$ solutions in $\F_p$ of the equation $x^n = a$.
 
 \fun{GEN}{Zn_sqrt}{GEN x, GEN n} returns one of the square roots of \kbd{x}
 modulo \kbd{n} (possibly not prime), where \kbd{x} is a \typ{INT} and \kbd{n}
@@ -2980,6 +3170,9 @@ of \typ{INT}~x and non-zero \kbd{ulong}~\kbd{y}. As \kbd{krouu} otherwise.
 \fun{long}{krosi}{long x, GEN y} returns the \idx{Kronecker symbol} $(x|y)$
 of \kbd{long}~x and \typ{INT}~\kbd{y}. As \kbd{kross} otherwise.
 
+\fun{long}{kroui}{ulong x, GEN y} returns the \idx{Kronecker symbol} $(x|y)$
+of \kbd{long}~x and \typ{INT}~\kbd{y}. As \kbd{kross} otherwise.
+
 \fun{long}{kronecker}{GEN x, GEN y} returns the \idx{Kronecker symbol} $(x|y)$
 of \typ{INT}s~x and~\kbd{y}. As \kbd{kross} otherwise.
 
@@ -3053,6 +3246,11 @@ where $x_1$, $x_2$ are the two halves of $x$.
 \fun{ulong}{coreu}{ulong n}, unique squarefree integer $d$ dividing $n$ such
 that $n/d$ is a square.
 
+\fun{ulong}{corediscs}{long d, ulong *pt_f}, $d$ (possibly negative)
+being congruent to $0$ or $1$ modulo $4$, return the fundamental
+discriminant $D$ such that $d=D*f^2$ and set \kbd{*pt\_f} to $f$
+(if \kbd{*pt\_f} not \kbd{NULL}).
+
 \fun{ulong}{eulerphiu}{ulong n}, Euler's totient function of $n$.
 
 \fun{ulong}{eulerphiu_fact}{GEN fa}, Euler's totient function of the
@@ -3139,6 +3337,10 @@ the prime field.
 
   \kbd{Z}:  the integers $\Z$, implemented as \typ{INT}s.
 
+  \kbd{Zp}: the $p$-adic integers $\Z_p$, implemented as \typ{INT}s, for arbitrary $p$
+
+  \kbd{Zl}: the $p$-adic integers $\Z_p$, implemented as \typ{INT}s, for $p< 2^{\B}$
+
   \kbd{z}:  the integers $\Z$, implemented using (signed) \kbd{long}s.
 
   \kbd{Q}:  the rational numbers $\Q$, implemented as \typ{INT}s and
@@ -3179,6 +3381,10 @@ the prime field.
   E.g.~an \kbd{FpXQ} belongs to $(\Z/p\Z)[X]/(T(X))$, \kbd{FpXQV} means a
   vector of such elements, etc.
 
+  \kbd{n}: representative (\typ{POL}) of power series modulo $X^n$.
+  E.g.~an \kbd{FpXn} belongs to $(\Z/p\Z)[X]/(X^n)$, \kbd{FpXnV} means a
+  vector of such elements, etc.
+
   \kbd{x}, \kbd{y}, \kbd{m}, \kbd{v}, \kbd{c}, \kbd{q}: as their uppercase
   counterpart, but coefficient arrays are implemented using \typ{VECSMALL}s,
   which coefficient understood as \kbd{ulong}s.
@@ -3316,12 +3522,22 @@ entries are the \kbd{Fp\_center} of the \kbd{gel(z,i)}.
 \fun{GEN}{FpM_center}{GEN z, GEN p, GEN pov2} returns a matrix whose
 entries are the \kbd{Fp\_center} of the \kbd{gcoeff(z,i,j)}.
 
+\fun{void}{FpC_center_inplace}{GEN z, GEN p, GEN pov2}
+in-place version of \kbd{FpC\_center}, using \kbd{affii}.
+
+\fun{void}{FpM_center_inplace}{GEN z, GEN p, GEN pov2}
+in-place version of \kbd{FpM\_center}, using \kbd{affii}.
+
 \fun{GEN}{FpC_add}{GEN x, GEN y, GEN p} adds the \kbd{ZC} $x$ and $y$
 and reduce modulo $p$ to obtain an \kbd{FpC}.
 
 \fun{GEN}{FpV_add}{GEN x, GEN y, GEN p} same as \kbd{FpC\_add}, returning and
 \kbd{FpV}.
 
+\fun{GEN}{FpM_add}{GEN x, GEN y, GEN p} adds the two \kbd{ZM}s~\kbd{x}
+and \kbd{y} (assumed to have compatible dimensions), and reduce modulo
+\kbd{p} to obtain an \kbd{FpM}.
+
 \fun{GEN}{FpC_sub}{GEN x, GEN y, GEN p} subtracts the \kbd{ZC} $y$ to
 the \kbd{ZC} $x$ and reduce modulo $p$ to obtain an \kbd{FpC}.
 
@@ -3332,6 +3548,10 @@ the \kbd{ZC} $x$ and reduce modulo $p$ to obtain an \kbd{FpC}.
 (seen as a column vector) by the \typ{INT}~\kbd{y} and reduce modulo \kbd{p} to
 obtain an \kbd{FpC}.
 
+\fun{GEN}{FpM_Fp_mul}{GEN x, GEN y, GEN p} multiplies the \kbd{ZM}~\kbd{x}
+(seen as a column vector) by the \typ{INT}~\kbd{y} and reduce modulo \kbd{p} to
+obtain an \kbd{FpM}.
+
 \fun{GEN}{FpC_FpV_mul}{GEN x, GEN y, GEN p} multiplies the \kbd{ZC}~\kbd{x}
 (seen as a column vector) by the \kbd{ZV}~\kbd{y} (seen as a row vector,
 assumed to have compatible dimensions), and reduce modulo \kbd{p} to obtain
@@ -3384,15 +3604,15 @@ is a \kbd{FpC}.
 
 \fun{GEN}{FpM_intersect}{GEN x, GEN y, GEN p} as \kbd{intersect}
 
-\fun{GEN}{FpM_inv}{GEN x, GEN p} returns the inverse of \kbd{x}, or
-\kbd{NULL} if \kbd{x} is not invertible.
+\fun{GEN}{FpM_inv}{GEN x, GEN p} returns a left inverse of \kbd{x}
+(the inverse if $x$ is square), or \kbd{NULL} if \kbd{x} is not invertible.
 
-\fun{GEN}{FpM_FpC_invimage}{GEN m, GEN v, GEN p}
- given an \kbd{FpM} $x$ and an \kbd{FpC} $y$, returns an $x$ such that $Ax =
+\fun{GEN}{FpM_FpC_invimage}{GEN A, GEN y, GEN p}
+ given an \kbd{FpM} $A$ and an \kbd{FpC} $y$, returns an $x$ such that $Ax =
  y$, or \kbd{NULL} if no such vector exist.
 
-\fun{GEN}{FpM_invimage}{GEN m, GEN v, GEN p}
-given two \kbd{FpM} $x$ and $y$, returns $x$ such that $Ax = y$, or \kbd{NULL}
+\fun{GEN}{FpM_invimage}{GEN A, GEN y, GEN p}
+given two \kbd{FpM} $A$ and $y$, returns $x$ such that $Ax = y$, or \kbd{NULL}
 if no such matrix exist.
 
 \fun{GEN}{FpM_ker}{GEN x, GEN p} as \kbd{ker}
@@ -3470,6 +3690,12 @@ the $n \times n$ identity matrix.
 \fun{GEN}{Flm_Flc_mul}{GEN x, GEN y, ulong p} multiplies  \kbd{x} and \kbd{y}
 (assumed to have compatible dimensions).
 
+\fun{GEN}{Flm_Flc_mul_pre}{GEN x, GEN y, ulong p, ulong pi} multiplies  \kbd{x}
+and \kbd{y} (assumed to have compatible dimensions), assuming $pi$ is the
+pseudo inverse of $p$.
+
+\fun{GEN}{Flm_Fl_mul}{GEN x, ulong y, ulong p} multiplies the \kbd{Flm}
+
 \fun{GEN}{Flm_Fl_mul}{GEN x, ulong y, ulong p} multiplies the \kbd{Flm}
 \kbd{x} by \kbd{y}.
 
@@ -3510,8 +3736,22 @@ $x$ by $x-y$.
 \fun{ulong}{Flv_dotproduct}{GEN x, GEN y, ulong p} returns the scalar product
 of \kbd{x} and \kbd{y}
 
+\fun{ulong}{Flv_dotproduct_pre}{GEN x, GEN y, ulong p} returns the scalar product
+of \kbd{x} and \kbd{y} assuming $pi$ is the pseudo inverse of $p$.
+
 \fun{ulong}{Flv_sum}{GEN x, ulong p} returns the sums of the components of $x$.
 
+\fun{GEN}{Flv_inv}{GEN x, ulong p} returns the vector of inverses of the elements
+of $x$ (as a \kbd{Flv}). Use Montgomery trick.
+
+\fun{void}{Flv_inv_inplace}{GEN x, ulong p} in place variant of \kbd{Flv\_inv}.
+
+\fun{GEN}{Flv_inv_pre}{GEN x, ulong p, ulong pi} as \kbd{Flv\_inv}
+assuming $pi$ is the pseudo inverse of $p$.
+
+\fun{void}{Flv_inv_pre_inplace}{GEN x, ulong p, ulong pi} in place variant of
+\kbd{Flv\_inv}.
+
 \fun{GEN}{zero_Flm}{long m, long n} creates a \kbd{Flm} with \kbd{m} x \kbd{n}
 components set to $0$. Note that the result allocates a
 \emph{single} column, so modifying an entry in one column modifies it in
@@ -3526,6 +3766,9 @@ $0$.
 \fun{GEN}{row_Flm}{GEN A, long x0} return $A[i,]$, the $i$-th row of the
 \kbd{Flm} (or \kbd{zm}) $A$.
 
+\fun{GEN}{Flm_add}{GEN x, GEN y, ulong p} adds \kbd{x} and \kbd{y}
+(assumed to have compatible dimensions).
+
 \fun{GEN}{Flm_mul}{GEN x, GEN y, ulong p} multiplies  \kbd{x} and \kbd{y}
 (assumed to have compatible dimensions).
 
@@ -3553,11 +3796,11 @@ a \kbd{Flc}.
 \fun{GEN}{Flm_inv}{GEN x, ulong p}
 
 \fun{GEN}{Flm_Flc_invimage}{GEN A, GEN y, ulong p} given an \kbd{Flm}
-$x$ and an \kbd{Flc} $y$, returns an $x$ such that $Ax = y$, or \kbd{NULL}
+$A$ and an \kbd{Flc} $y$, returns an $x$ such that $Ax = y$, or \kbd{NULL}
 if no such vector exist.
 
-\fun{GEN}{Flm_invimage}{GEN x, GEN y, ulong p}
-given two \kbd{Flm} $x$ and $y$, returns $x$ such that $Ax = y$, or \kbd{NULL}
+\fun{GEN}{Flm_invimage}{GEN A, GEN y, ulong p}
+given two \kbd{Flm} $A$ and $y$, returns $x$ such that $Ax = y$, or \kbd{NULL}
 if no such matrix exist.
 
 \fun{GEN}{Flm_ker}{GEN x, ulong p}
@@ -3731,14 +3974,6 @@ and \kbd{y}
 
 \fun{GEN}{matid_FlxqM}{long n, GEN T, ulong p}
 
-\subsec{\kbd{Zlm}}
-\fun{GEN}{ZlM_gauss}{GEN a, GEN b, ulong p, long e, GEN C} as \kbd{gauss}
-with the following peculiarities: $a$ and $b$ are \kbd{ZM}, such that $a$ is
-invertible modulo $p$. Optional $C$ is an \kbd{Flm} that is an inverse of
-$a\mod p$ or \kbd{NULL}. Return the matrix $x$ such that $ax=b\mod p^e$ and
-all elements of $x$ are in $[0,p^e-1]$. For efficiency, it is better
-to reduce $a$ and $b$ mod $p^e$ first.
-
 \subsec{\kbd{FpX}} Let \kbd{p} an understood \typ{INT}, to be given in
 the function arguments; in practice \kbd{p} is not assumed to be prime, but
 be wary. Recall than an \kbd{Fp} object is a \typ{INT}, preferably belonging
@@ -3784,6 +4019,9 @@ $\kbd{l} = \kbd{lg(x)}$, in place.
 
 \fun{GEN}{FpX_sub}{GEN x,GEN y,GEN p} returns $x-y$.
 
+\fun{GEN}{FpX_halve}{GEN x, GEN m} returns $z$ such that $2\*z = x$ modulo
+$m$ assuming such $z$ exists.
+
 \fun{GEN}{FpX_mul}{GEN x,GEN y,GEN p} returns $x\*y$.
 
 \fun{GEN}{FpX_mulspec}{GEN a, GEN b, GEN p, long na, long nb}
@@ -3791,6 +4029,8 @@ see \kbd{ZX\_mulspec}
 
 \fun{GEN}{FpX_sqr}{GEN x,GEN p} returns $\kbd{x}^2$.
 
+\fun{GEN}{FpX_powu}{GEN x, ulong n, GEN p} returns $x^n$.
+
 \fun{GEN}{FpX_divrem}{GEN x, GEN y, GEN p, GEN *pr} returns the quotient
 of \kbd{x} by \kbd{y}, and sets \kbd{pr} to the remainder.
 
@@ -3815,6 +4055,13 @@ of~\kbd{x}.
 This function is not memory-clean, but nevertheless suitable for
 \kbd{gerepileupto}.
 
+\fun{GEN}{FpX_digits}{GEN x, GEN B, GEN p} returns a vector of \kbd{FpX}
+$[c_0,\ldots,c_n]$ of degree less than the degree of $B$ and such that
+$x=\sum_{i=0}^{n}{c_i\*B^i}$.
+
+\fun{GEN}{FpX_fromdigits}{GEN v, GEN B, GEN p} where $v=[c_0,\ldots,c_n]$
+is a vector of \kbd{FpX}, returns $\sum_{i=0}^{n}{c_i\*B^i}$.
+
 \fun{GEN}{FpX_translate}{GEN P, GEN c, GEN p} let $c$ be an \kbd{Fp} and let
 $P$ be an \kbd{FpX}; returns the translated \kbd{FpX} of $P(X+c)$.
 
@@ -3835,6 +4082,10 @@ This is useful when computing the inverse of $y$ modulo $x$.
 coefficient belong to the symmetric residue system. Assumes the coefficients
 already belong to $[0,\kbd{p}-1]$) and \kbd{pov2} is \kbd{shifti(p,-1)}.
 
+\fun{GEN}{FpX_Frobenius}{GEN T, GEN p} returns $X^{p}\pmod{T(X)}$.
+
+\fun{GEN}{FpX_matFrobenius}{GEN T, GEN p} returns the matrix of the
+Frobenius automorphism $x\mapsto x^p$ over the power basis of $\F_p[X]/(T)$.
 
 \subsubsec{Mixed operations}
 The following functions implement arithmetic operations between \kbd{FpX}
@@ -3945,6 +4196,9 @@ Assumes that \kbd{p} is prime.
 the \kbd{FpX}~\kbd{f} (without multiplicity, as a vector of \kbd{Fp}s).
 Assumes that \kbd{p} is prime.
 
+\fun{GEN}{FpX_split_part}{GEN f, GEN p} returns the largest totally split
+squarefree factor of $f$.
+
 \fun{GEN}{random_FpX}{long d, long v, GEN p} returns a random \kbd{FpX}
 in variable \kbd{v}, of degree less than~\kbd{d}.
 
@@ -4001,9 +4255,12 @@ a \kbd{FpX} to an extended modulus for the corresponding \kbd{Flx}.
 which can be mapped to $\F_p[X]/(T)$: anything for which \kbd{Rg\_is\_Fp} return
 $1$, a \typ{POL} for which \kbd{RgX\_to\_FpX} return $1$, a \typ{POLMOD}
 whose modulus is equal to \kbd{*T} if \kbd{*T} is not \kbd{NULL} (once mapped
-to a \kbd{FpX}).
+to a \kbd{FpX}), or a \typ{FFELT} $z$ such that $z^0$ is equal to \kbd{*T}
+if \kbd{*T} is not \kbd{NULL}.
+
 If an integer modulus is found it is put in \kbd{*p}, else \kbd{*p} is left
-unchanged. If a polynomial modulus is found it is put in \kbd{*T}, else
+unchanged. If a polynomial modulus is found it is put in \kbd{*T},
+if a \typ{FFELT} $z$ is found, $z^0$ is put in \kbd{*T}, else
 \kbd{*T} is left unchanged.
 
 \fun{int}{RgX_is_FpXQX}{GEN z, GEN *T, GEN *p}, \kbd{z} a \typ{POL},
@@ -4020,9 +4277,13 @@ whose modulus is divisible by $T$ (once mapped to a \kbd{FpX}), a suitable
 \kbd{FpXQ} obtained by applying \kbd{Rg\_to\_FpXQ} coefficientwise.
 
 \fun{GEN}{RgX_to_FqX}{GEN z, GEN T, GEN p}: let \kbd{z} be a \typ{POL};
-returns the \kbd{FpXQ} obtained by applying \kbd{Rg\_to\_FpXQ}
+returns the \kbd{FqX} obtained by applying \kbd{Rg\_to\_FpXQ}
 coefficientwise and simplifying scalars to \typ{INT}s.
 
+\fun{GEN}{Fq_to_FpXQ}{GEN z, GEN T, GEN p /*unused*/}
+if $z$ is a \typ{INT}, convert it to a constant polynomial in the variable of
+$T$, otherwise return $z$ (shallow function).
+
 \fun{GEN}{Fq_red}{GEN x, GEN T, GEN p}, \kbd{x} a \kbd{ZX} or \typ{INT},
 reduce it to an \kbd{Fq} ($\kbd{T} = \kbd{NULL}$ is allowed iff \kbd{x} is a
 \typ{INT}).
@@ -4055,8 +4316,6 @@ whose coefficients are \typ{INT}s, reduce them to \kbd{FpXQ}s.
 \fun{GEN}{FpXQ_invsafe}{GEN x,GEN T,GEN p}, as \kbd{FpXQ\_inv}, returning
 \kbd{NULL} if \kbd{x} is not invertible.
 
-\fun{GEN}{FpXQX_renormalize}{GEN x, long lx}
-
 \fun{GEN}{FpXQ_pow}{GEN x, GEN n, GEN T, GEN p} computes $\kbd{x}^\kbd{n}$.
 
 \fun{GEN}{FpXQ_powu}{GEN x, ulong n, GEN T, GEN p} computes $\kbd{x}^\kbd{n}$
@@ -4071,7 +4330,7 @@ that \kbd{T} is irreducible mod \kbd{p}.
 \kbd{FpXQ\_log}, \kbd{a} being a \kbd{Fp}.
 
 \fun{GEN}{FpXQ_order}{GEN a, GEN ord, GEN T, GEN p} returns the order of the
-\typ{FpXQ} \kbd{a}. If \kbd{o} is non-\kbd{NULL}, it is assumed that \kbd{o}
+\kbd{FpXQ} \kbd{a}. If \kbd{o} is non-\kbd{NULL}, it is assumed that \kbd{o}
 is a multiple of the order of \kbd{a}, either as a \typ{INT} or a
 factorization matrix. Assumes that \kbd{T} is irreducible mod \kbd{p}.
 
@@ -4081,11 +4340,12 @@ and $0$ otherwise. Assumes that \kbd{T} is irreducible mod \kbd{p}.
 \fun{GEN}{FpXQ_sqrt}{GEN x, GEN T, GEN p} returns a square root of \kbd{x}.
 Return \kbd{NULL} if \kbd{x} is not a square.
 
-\fun{GEN}{FpXQ_sqrtn}{GEN x, GEN n, GEN T, GEN p, GEN *zn} returns an
-\kbd{n}-th root of $\kbd{x}$.  Return \kbd{NULL} if \kbd{x} is not an
-\kbd{n}-th power residue. Otherwise, if \kbd{zn} is non-\kbd{NULL} set it to
-a primitive \kbd{n}-th root of the unity. Assumes that \kbd{T} is irreducible
-mod \kbd{p}.
+\fun{GEN}{FpXQ_sqrtn}{GEN x, GEN n, GEN T, GEN p, GEN *zn}
+Let $T$be irreducible mod $p$ and $q = p^{\deg T}$; returns \kbd{NULL} if $a$
+is not an $n$-th power residue mod $p$. Otherwise, returns an $n$-th root of
+$a$; if \kbd{zn} is non-\kbd{NULL} set it to a primitive $m$-th root of $1$
+in $\F_q$, $m = \gcd(q-1,n)$ allowing to compute all $m$ solutions in $\F_q$
+of the equation $x^n = a$.
 
 \subsec{\kbd{Fq}}
 
@@ -4101,6 +4361,9 @@ by the \typ{INT} $y$.
 \fun{GEN}{Fq_mulu}{GEN x, ulong y, GEN T, GEN p} multiplies the \kbd{Fq} $x$
 by the scalar $y$.
 
+\fun{GEN}{Fq_halve}{GEN x, GEN T, GEN p} returns $z$ such that $2\*z = x$
+assuming such $z$ exists.
+
 \fun{GEN}{Fq_sqr}{GEN x, GEN T, GEN p}
 
 \fun{GEN}{Fq_neg}{GEN x, GEN T, GEN p}
@@ -4115,7 +4378,7 @@ error if \kbd{x} is not invertible.
 
 \fun{GEN}{Fq_div}{GEN x, GEN y, GEN T, GEN p}
 
-\fun{GEN}{FqV_inv}{GEN x, GEN T, GEN p} $x$ being a vector of \typ{Fq}s,
+\fun{GEN}{FqV_inv}{GEN x, GEN T, GEN p} $x$ being a vector of \kbd{Fq}s,
 return the vector of inverses of the $x[i]$. The routine uses Montgomery's
 trick, and involves a single inversion, plus $3(N-1)$ multiplications for
 $N$ entries. The routine is not stack-clean: $2N$ \kbd{FpXQ} are left on
@@ -4126,6 +4389,12 @@ stack, besides the $N$ in the result.
 \fun{GEN}{Fq_powu}{GEN x, ulong n, GEN pol, GEN p} returns $\kbd{x}^\kbd{n}$
 for small $n$.
 
+\fun{GEN}{Fq_log}{GEN a, GEN g, GEN ord, GEN T, GEN p}
+Let \kbd{g} be of order \kbd{ord} in the finite field $\F_p[X]/(T)$, return $e$
+such that $a^e=g$. If $e$ does not exists, the result is currently undefined.
+Allow $T = \kbd{NULL}$ (discrete log over $\F_p$), otherwise
+assume that \kbd{T} is irreducible mod \kbd{p}.
+
 \fun{int}{Fq_issquare}{GEN x, GEN T, GEN p} returns $1$ if $x$ is a square
 and $0$ otherwise. Assumes that \kbd{T} is irreducible mod \kbd{p}. $T =
 \kbd{NULL}$ is forbidden unless $x$ is an \kbd{Fp}.
@@ -4133,11 +4402,8 @@ and $0$ otherwise. Assumes that \kbd{T} is irreducible mod \kbd{p}. $T =
 \fun{GEN}{Fq_sqrt}{GEN x, GEN T, GEN p} returns a square root of \kbd{x}.
 Return \kbd{NULL} if \kbd{x} is not a square.
 
-\fun{GEN}{Fq_sqrtn}{GEN x, GEN n, GEN T, GEN p, GEN *zn} returns an
-\kbd{n}-th root of $\kbd{x}$.  Return \kbd{NULL} if \kbd{x} is not an
-\kbd{n}-th power residue. Otherwise, if \kbd{zn} is non-\kbd{NULL} set it to
-a primitive \kbd{n}-th root of the unity. Assumes that \kbd{T} is irreducible
-mod \kbd{p}.
+\fun{GEN}{Fq_sqrtn}{GEN a, GEN n, GEN T, GEN p, GEN *zn}
+as \tet{FpXQ_sqrtn}.
 
 \fun{GEN}{FpXQ_charpoly}{GEN x, GEN T, GEN p} returns the characteristic
 polynomial of \kbd{x}
@@ -4165,6 +4431,11 @@ which is a generator of the $\ell$-Sylow of $G$ for every $\ell$ in
 $\ell=2$, since 2 is treated separately in any case, i.e. the generator
 obtained is never a square if $p$ is odd.
 
+\fun{GEN}{gener_Fq_local}{GEN T, GEN p, GEN L} as
+\tet{pgener_Fp_local} (if $T$ is \kbd{NULL})
+or \tet{gener_FpXQ_local} (otherwise).
+
+
 \fun{GEN}{FpXQ_powers}{GEN x, long n, GEN T, GEN p} returns $[\kbd{x}^0,
 \dots, \kbd{x}^\kbd{n}]$ as a \typ{VEC} of \kbd{FpXQ}s.
 
@@ -4184,16 +4455,28 @@ where $b=a[2]$.
 \fun{GEN}{FpXQ_autpowers}{GEN S, long n, GEN T, GEN p} returns
 $[x,S(x),S(S(x)),\dots,S^{(n)}(x)]$ as a \typ{VEC} of \kbd{FpXQ}s.
 
-\fun{GEN}{FpX_FpXQ_eval}{GEN f,GEN x,GEN T,GEN p} returns
+\fun{GEN}{FpXQM_autsum}{GEN a, long n, GEN T, GEN p}
+$\sigma$ being the automorphism defined by $\sigma(X)=a[1]\pmod{T(X)}$,
+returns the vector $[\sigma^n(X),b\sigma(b)\ldots\sigma^{n-1}(b)]$
+where $b=a[2]$ is a square matrix.
+
+\fun{GEN}{FpX_FpXQ_eval}{GEN f, GEN x, GEN T, GEN p} returns
 $\kbd{f}(\kbd{x})$.
 
-\fun{GEN}{FpX_FpXQV_eval}{GEN f,GEN V,GEN T,GEN p} returns
+\fun{GEN}{FpX_FpXQV_eval}{GEN f, GEN V, GEN T, GEN p} returns
 $\kbd{f}(\kbd{x})$, assuming that \kbd{V} was computed by
 $\kbd{FpXQ\_powers}(\kbd{x}, n, \kbd{T}, \kbd{p})$.
 
+\fun{GEN}{FpXC_FpXQV_eval}{GEN C, GEN V,GEN T,GEN p} applies
+\kbd{FpX\_FpXQV\_eval} to all elements of the vector $C$
+and returns a \typ{COL}.
+
+\fun{GEN}{FpXM_FpXQV_eval}{GEN M, GEN V,GEN T,GEN p} applies
+\kbd{FpX\_FpXQV\_eval} to all elements of the matrix $M$.
+
 \subsec{\kbd{FpXX}, \kbd{FpXY}}
 Contrary to what the name implies, an \kbd{FpXX} is a \typ{POL} whose
-coefficients are either \typ{INT}s or \typ{FpX}s. This reduces memory
+coefficients are either \typ{INT}s or \kbd{FpX}s. This reduces memory
 overhead at the expense of consistency. The prefix \kbd{FpXY} is an
 alias for \kbd{FpXX} when variables matters.
 
@@ -4234,10 +4517,15 @@ is the variable number of $X$.
 and $y$ being an \kbd{Fq}, returns the \kbd{FqX} $Q(X,y)$, where $X$ is the
 second variable of $Q$, and \kbd{vx} is the variable number of $X$.
 
-\fun{GEN}{FpXY_FpXQ_evalx}{GEN x, GEN Y, ulong p} $Q$ an \kbd{FpXY} and
-$y$ being an \kbd{FpXQ}, returns the \kbd{FpXQX} $Q(x,Y)$, where $Y$ is the
+\fun{GEN}{FpXY_FpXQ_evalx}{GEN Q, GEN x, ulong p} $Q$ an \kbd{FpXY} and
+$x$ being an \kbd{FpXQ}, returns the \kbd{FpXQX} $Q(x,Y)$, where $Y$ is the
 first variable of $Q$.
 
+\fun{GEN}{FpXY_FpXQV_evalx}{GEN Q, GEN V, ulong p} $Q$ an \kbd{FpXY} and
+$x$ being an \kbd{FpXQ}, returns the \kbd{FpXQX} $Q(x,Y)$, where $Y$ is the
+first variable of $Q$, assuming that \kbd{V} was computed by
+$\kbd{FpXQ\_powers}(\kbd{x}, n, \kbd{T}, \kbd{p})$.
+
 \fun{GEN}{FpXYQQ_pow}{GEN x, GEN n, GEN S, GEN T, GEN p}, \kbd{x} being a
 \kbd{FpXY}, \kbd{T} being a \kbd{FpX} and \kbd{S} being a \kbd{FpY},
 return $x^n \pmod{S,T,p}$.
@@ -4280,10 +4568,14 @@ by its leading term. The leading coefficient becomes $1$ as a \typ{INT}.
 
 \fun{GEN}{FqX_sqr}{GEN x, GEN T, GEN p}
 
+\fun{GEN}{FqX_powu}{GEN x, ulong n, GEN T, GEN p}
+
 \fun{GEN}{FqX_divrem}{GEN x, GEN y, GEN T, GEN p, GEN *z}
 
 \fun{GEN}{FqX_div}{GEN x, GEN y, GEN T, GEN p}
 
+\fun{GEN}{FqX_div_by_X_x}{GEN a, GEN x, GEN T, GEN p, GEN *r}
+
 \fun{GEN}{FqX_rem}{GEN x, GEN y, GEN T, GEN p}
 
 \fun{GEN}{FqX_deriv}{GEN x, GEN T, GEN p} returns the derivative of \kbd{x}.
@@ -4311,6 +4603,8 @@ element of $\F_q[X][Y]$. Returns the \kbd{Fq} $Q(x,y)$.
 \fun{GEN}{FqXY_evalx}{GEN Q, GEN x, GEN T, GEN p} $Q$ being an \kbd{FqXY},
 returns the \kbd{FqX} $Q(x,Y)$, where $Y$ is the main variable of $Q$.
 
+\fun{GEN}{FpXQX_renormalize}{GEN x, long lx}
+
 \fun{GEN}{FpXQX_red}{GEN z, GEN T, GEN p} \kbd{z} a \typ{POL} whose
 coefficients are \kbd{ZX}s or \typ{INT}s, reduce them to \kbd{FpXQ}s.
 
@@ -4332,8 +4626,16 @@ Not stack-clean. Note that $t$ need not be the same variable as $Y$!
 
 \fun{GEN}{FpXQX_div}{GEN x, GEN y, GEN T, GEN p}
 
+\fun{GEN}{FpXQX_div_by_X_x}{GEN a, GEN x, GEN T, GEN p, GEN *r}
+
 \fun{GEN}{FpXQX_rem}{GEN x, GEN y, GEN T, GEN p}
 
+\fun{GEN}{FpXQX_powu}{GEN x, ulong n, GEN T, GEN p} returns $x^n$.
+
+\fun{GEN}{FpXQX_digits}{GEN x, GEN B, GEN T, GEN p}
+
+\fun{GEN}{FpXQX_fromdigits}{GEN v, GEN B, GEN T, GEN p}
+
 \fun{GEN}{FpXQX_invBarrett}{GEN y, GEN T, GEN p} returns the Barrett inverse of
 the \kbd{FpXQX} $y$, namely a lift of $1/\kbd{polrecip}(y)+O(x^{\deg(y)-1})$.
 
@@ -4580,6 +4882,8 @@ assuming the result is monic of the same degree as $y$ (in particular $x\neq
 
 \fun{GEN}{Flx_sqr}{GEN x, ulong p}
 
+\fun{GEN}{Flx_powu}{GEN x, ulong n, ulong p} returns $x^n$.
+
 \fun{GEN}{Flx_divrem}{GEN x, GEN y, ulong p, GEN *pr}
 
 \fun{GEN}{Flx_div}{GEN x, GEN y, ulong p}
@@ -4588,6 +4892,10 @@ assuming the result is monic of the same degree as $y$ (in particular $x\neq
 
 \fun{GEN}{Flx_deriv}{GEN z, ulong p}
 
+\fun{GEN}{Flx_Frobenius}{GEN T, ulong p}
+
+\fun{GEN}{Flx_matFrobenius}{GEN T, ulong p}
+
 \fun{GEN}{Flx_gcd}{GEN a, GEN b, ulong p} returns a (not necessarily monic)
 greatest common divisor of $x$  and $y$.
 
@@ -4597,8 +4905,6 @@ has the property that $\deg a \geq {\deg x \over 2} > \deg b$.
 
 \fun{GEN}{Flx_extgcd}{GEN a, GEN b, ulong p, GEN *ptu, GEN *ptv}
 
-\fun{GEN}{Flx_pow}{GEN x, long n, ulong p}
-
 \fun{GEN}{Flx_roots}{GEN f, ulong p} returns the vector of roots
 of $f$ (without multiplicity, as a \typ{VECSMALL}). Assumes that $p$ is
 prime.
@@ -4607,6 +4913,9 @@ prime.
 the \kbd{Flx}~\kbd{f} in \kbd{\Z/p\Z}. Return $p$ if no root exists. Assumes
 that \kbd{p} is prime.
 
+\fun{ulong}{Flx_oneroot_split}{GEN f, ulong p} as \kbd{Flx\_oneroot} but
+assume $f$ is totally split.
+
 \fun{GEN}{Flx_roots_naive}{GEN f, ulong p} returns the vector of roots
 of $f$ as a \typ{VECSMALL} (multiple roots are not repeated), found
 by an exhaustive search. Efficient for very small $p$ !
@@ -4638,6 +4947,9 @@ $(X^n - 1, p)$. Shallow function.
 
 \fun{GEN}{Flx_normalize}{GEN z, ulong p}, as \kbd{FpX\_normalize}.
 
+\fun{GEN}{Flx_rescale}{GEN P, ulong h, ulong p} returns $h^{\deg(P)} P(x/h)$,
+\kbd{P} is a \kbd{Flx} and \kbd{h} is a non-zero integer.
+
 \fun{GEN}{random_Flx}{long d, long sv, ulong p} returns a random \kbd{Flx}
 in variable \kbd{v}, of degree less than~\kbd{d}.
 
@@ -4674,6 +4986,16 @@ Euclidean quotient of the \kbd{Flx}~\kbd{A} by $X - \kbd{a}$, and sets
 
 \fun{ulong}{Flx_eval}{GEN x, ulong y, ulong p}, as \kbd{FpX\_eval}.
 
+\fun{ulong}{Flx_eval_pre}{GEN x, ulong y, ulong p, ulong pi}, as \kbd{Flx\_eval},
+assuming $pi$ is the pseudo inverse of $p$.
+
+\fun{ulong}{Flx_eval_powers_pre}{GEN P, GEN y, ulong p, ulong pi}, $y$ being
+the vector $[1,a,\dots,a^n]$, where $n$ is the degree of $P$, return $P(a)$,
+assuming $pi$ is the pseudo inverse of $p$.
+
+\fun{ulong}{Flx_Flv_multieval}{GEN P, GEN v, ulong y, ulong p} returns the vector
+$[P(v[1]),\ldots,P(v[n])]$ as a \kbd{Flv}.
+
 \fun{GEN}{Flx_deflate}{GEN P, long d} assuming $P$ is a polynomial of the
 form $Q(X^d)$, return $Q$.
 
@@ -4707,6 +5029,10 @@ as \kbd{FpX\_ffintersect}
 \fun{GEN}{Flv_polint}{GEN x, GEN y, ulong p, long sv} as \kbd{FpV\_polint},
 returning an \kbd{Flx} in variable $v$.
 
+\fun{GEN}{Flv_FlvV_polint}{GEN x, GEN V, ulong p, long sv} equivalent (but
+faster) to applying \kbd{Flv\_polint(x,$\ldots$)} to all the elements of the
+vector $V$ (thus, returns a \kbd{FlxV}).
+
 \fun{GEN}{Flv_roots_to_pol}{GEN a, ulong p, long sv} as
 \kbd{FpV\_roots\_to\_pol} returning an \kbd{Flx} in variable $v$.
 
@@ -4779,11 +5105,8 @@ order \kbd{ord} in the field $F_p[X]/(T)$. Return $e$ such that $a^e=g$. If
 $e$ does not exists, the result is currently undefined. Assumes that \kbd{T}
 is irreducible mod \kbd{p}.
 
-\fun{GEN}{Flxq_sqrtn}{GEN x, GEN n, GEN T, ulong p, GEN *zn} returns an
-\kbd{n}-th root of $\kbd{x}$.  Return \kbd{NULL} if \kbd{x} is not an
-\kbd{n}-th power residue. Otherwise, if \kbd{zn} is non-\kbd{NULL} set it to
-a primitive \kbd{n}-th root of $1$. Assumes that \kbd{T} is irreducible mod
-\kbd{p}.
+\fun{GEN}{Flxq_sqrtn}{GEN x, GEN n, GEN T, ulong p, GEN *zn} as
+\tet{FpXQ_sqrtn}.
 
 \fun{GEN}{Flxq_sqrt}{GEN x, GEN T, ulong p} returns a square root of \kbd{x}.
 Return \kbd{NULL} if \kbd{x} is not a square.
@@ -4841,9 +5164,22 @@ degree~1~\typ{POL} with \kbd{Flx} coefficients in the variable $x$.
 \fun{GEN}{FlxY_Flx_div}{GEN x, GEN y, ulong p} divides the coefficients of $x$
 by $y$ using \kbd{Flx\_div}.
 
-\fun{GEN}{FlxY_evalx}{GEN x, ulong y, ulong p}
+\fun{GEN}{FlxY_evalx}{GEN P, ulong z, ulong p} $Q$ being an \kbd{FlxY}, returns
+the \kbd{Flx} $P(z,Y)$, where $Y$ is the main variable of $P$.
+
+\fun{ulong}{FlxY_evalx_powers_pre}{GEN P, GEN xp, ulong p, ulong pi}, \kbd{xp}
+being the vector $[1,x,\dots,x^n]$, where $n$ is larger or equal to the degree
+of $P$ in $X$, return $P(x,Y)$, where $Y$ is the main variable of $Q$, assuming
+$pi$ is the pseudo inverse of $p$.
 
-\fun{GEN}{FlxY_Flxq_evalx}{GEN x, GEN y, ulong p}
+\fun{ulong}{FlxY_eval_powers_pre}{GEN P, GEN xp, GEN yp, ulong p, ulong pi},
+\kbd{xp} being the vector $[1,x,\dots,x^n]$, where $n$ is larger or equal to the degree
+of $P$ in $X$ and \kbd{yp} being the vector $[1,y,\dots,y^m]$, where $m$ is larger or equal to the degree of $P$ in $Y$ return $P(x,y)$, assuming
+$pi$ is the pseudo inverse of $p$.
+
+\fun{GEN}{FlxY_Flxq_evalx}{GEN x, GEN y, ulong p} as \kbd{FpXY\_FpXQ\_evalx}.
+
+\fun{GEN}{FlxY_FlxqV_evalx}{GEN x, GEN y, ulong p} as \kbd{FpXY\_FpXQV\_evalx}.
 
 \fun{GEN}{FlxX_renormalize}{GEN x, long l}, as \kbd{normalizepol}, where
 $\kbd{l} = \kbd{lg(x)}$, in place.
@@ -5203,6 +5539,52 @@ solution. Otherwise, return \kbd{NULL} if it has no solution.
 
 \medskip
 
+\fun{GEN}{ZV_producttree}{GEN x} where $x$ are vectors of integer (or
+\typ{VECSMALL}s) of length $n\ge 1$, return the vector of \typ{VEC}s
+$[f(x),f^2(x),\ldots,f^k(x)]$ where $f$ is the transformation
+$[a_1,a_2,\ldots,a_m] \mapsto [a_1\*a_2,a_3\*a_4,\ldots,a_{m-1}\*a_m]$ if $m$
+is even and $[a_1\*a_2,a_3\*a4,\ldots,a_{m-2}\*a_{m-1},a_m]$ if $m$ is odd,
+and $k$ is chosen so that $f^k(x)$ is of length $1$ (This is the vector
+$[a_1\*a_2\*ldots\*a_m]$).
+
+\fun{GEN}{ZV_chinese}{GEN A, GEN P, GEN *pt_mod}
+where $A$ and $P$ are vectors of integer (or \typ{VECSMALL}s) of the same
+length $n\ge 1$, the elements of $P$ being pairwise coprime, and $M$ being the
+product of the elements of $P$, returns the integer in $[0, M[$ congruent to
+$A[i]$ mod $P[i]$ for all $1\leq i\leq n$.  If \kbd{pt\_mod} is not \kbd{NULL},
+set \kbd{*pt\_mod} to $M$
+
+\fun{GEN}{ZV_chinese_tree}{GEN A, GEN P, GEN T, GEN *pt_mod}
+as \kbd{ZV\_chinese}, where $T$ is assumed to be the tree created by
+\kbd{ZV\_producttree(P)}.
+
+\fun{GEN}{nmV_chinese}{GEN A, GEN P, GEN *pt_mod}
+where $A$ is a vector of \kbd{MATSMALL}s (seen as matrices of unsigned integers)
+ and $P$ a \typ{VECSMALL} of the same length $n\ge 1$, the elements of $P$
+being pairwise coprime, and $M$ being the product of the elements of $P$,
+returns the matrix whose entries are integers in $[0, M[$ congruent to $A[i]$
+mod $P[i]$ for all $1\leq i\leq n$.
+If \kbd{pt\_mod} is not \kbd{NULL}, set \kbd{*pt\_mod} to $M$
+
+\fun{GEN}{Z_ZV_mod}{GEN A, GEN P}
+$P$ being a vector of integers of length $n\ge 1$, the elements of $P$ being
+pairwise coprime, return a vector $B$ of the same length such that
+$B[i]=A\pmod{P[i]}$ and $0\leq B[i] < P[i]$ for all $1\leq i\leq n$.
+
+\fun{GEN}{Z_nv_mod}{GEN A, GEN P}
+$P$ being a \typ{VECSMALL} of length $n\ge 1$, the elements of $P$ being
+pairwise coprime, return a \typ{VECSMALL} $B$ of the same length such that
+$B[i]=A\pmod{P[i]}$ and $0\leq B[i] < P[i]$ for all $1\leq i\leq n$.
+The entries of $P$ and $B$ are treated as \kbd{ulong}s.
+
+\fun{GEN}{ZX_nv_mod_tree}{GEN A, GEN P, GEN T} $A$ being a \kbd{ZX}
+and $P$ a \typ{VECSMALL} of length $n\ge 1$, the elements of $P$ being
+pairwise coprime, return the vector of \kbd{Flx}
+$[A \pmod{P[1]},\ldots,A \pmod{P[n]}]$,
+where $T$ is assumed to be the tree created by \kbd{ZV\_producttree(P)}.
+
+\medskip
+
 The following pair of functions is used in homomorphic imaging schemes,
 when reconstructing an integer from its images modulo pairwise coprime
 integers. The idea is as follows: we want to discover an integer $H$ which
@@ -5294,7 +5676,10 @@ The functions is not stack clean if one coefficients of $M$ is negative
 \fun{GEN}{FpC_ratlift}{GEN P, GEN m, GEN amax, GEN bmax, GEN denom} as
 \kbd{FpM\_ratlift}, where $P$ is an \kbd{FpC}.
 
-\subsec{Hensel lifts}
+\subsec{Zp}
+
+\fun{GEN}{Zp_sqrt}{GEN b, GEN p, long e} $b$ and $p$ being \typ{INT}s, with $p$
+a odd prime, returns a \typ{INT} $a$ such that $a^2 \equiv b \mod p^e$.
 
 \fun{GEN}{Zp_sqrtlift}{GEN b, GEN a, GEN p, long e} let
 $a,b,p$ be \typ{INT}s, with $p > 1$ odd, such that $a^2\equiv b\mod p$.
@@ -5312,25 +5697,11 @@ $1$ congruent to $x$ modulo $p$, modulo $p^e$. For convenience, $p = 2$ is
 also allowed and we return $1$ ($x$ is $1$ mod $4$) or $2^e - 1$ ($x$ is $3$
 mod $4$).
 
-\fun{GEN}{ZpXQ_invlift}{GEN b, GEN a, GEN T, GEN p, long e} let
-$p$ be a prime \typ{INT} and $a,b$ be \kbd{FpXQ}s (modulo $T$) such that $a\*b
-\equiv 1 \mod (p,T)$.  Returns an \kbd{FpXQ} $A$ such that
-$A\*b \equiv 1 \mod (p^e, T)$.  Special case of \tet{ZpXQ_liftroot}.
-
-\fun{GEN}{ZpXQ_inv}{GEN b, GEN T, GEN p, long e} let
-$p$ be a prime \typ{INT} and $b$ be a \kbd{FpXQ} (modulo $T, p^e$).
-Returns an \kbd{FpXQ} $A$ such that $A\*b \equiv 1 \mod (p^e, T)$.
-
-\fun{GEN}{ZpXQ_sqrtnlift}{GEN b, GEN n, GEN a, GEN T, GEN p, long e} let
-$n,p$ be \typ{INT}s, with $n,p > 1$ and $p$ coprime to $n$, and $a,b$
-be \kbd{FpXQ}s (modulo $T$) such that $a^n \equiv b \mod (p,T)$.
-Returns an \kbd{Fq} $A$ such that $A^n \equiv b \mod (p^e, T)$.
-Special case of \tet{ZpXQ_liftroot}.
+\subsec{ZpX}
 
-\fun{GEN}{rootpadicfast}{GEN f, GEN p, long e} $f$ a \kbd{ZX} with leading
+\fun{GEN}{ZpX_roots}{GEN f, GEN p, long e} $f$ a \kbd{ZX} with leading
 term prime to $p$, and without multiple roots mod $p$. Return a vector
-of \typ{INT}s which are the roots of $f$ mod $p^e$. This is a very important
-special case of \kbd{rootpadic}.
+of \typ{INT}s which are the roots of $f$ mod $p^e$.
 
 \fun{GEN}{ZpX_liftroot}{GEN f, GEN a, GEN p, long e} $f$ a \kbd{ZX} with
 leading term prime to $p$, and $a$ a root mod $p$ such that
@@ -5347,16 +5718,6 @@ leading term prime to $p$, and $S$ a vector of simple roots mod $p$. Return a
 vector of \typ{INT}s which are the root of $f$ mod $p^e$ congruent to the
 $S[i]$ mod $p$.
 
-\fun{GEN}{ZpXQX_liftroot}{GEN f, GEN a, GEN T, GEN p, long e} as
-\tet{ZpX_liftroot}, but $f$ is now a polynomial in $\Z[X,Y]$ and we find
-a root in the unramified extension of $\Q_p$ with residue field $\F_p[Y]/(T)$,
-assuming $v_p(f(a))>0$ and $v_p(f'(a))=0$.
-
-\fun{GEN}{ZpXQX_liftroot_vald}{GEN f, GEN a, long v, GEN T, GEN p, long e}
-returns the foots of $f$ as \tet{ZpXQX_liftroot}, where $v$ is the valuation
-of the content of $f'$ and it is required that $v_p(f(a))>v$ and
-$v_p(f'(a))=v$.
-
 \fun{GEN}{ZpX_liftfact}{GEN A, GEN B, GEN T, GEN p, long e, GEN pe} is
 the routine underlying \tet{polhensellift}. Here, $p$ is prime, $T(Y)$
 defines a finite field $\F_q$, either $\F_q = \F_p$ ($T$ is \kbd{NULL})
@@ -5367,57 +5728,8 @@ is non-zero in $\F_q$. $B$ is a vector of monic \kbd{FpX} ($T$ \kbd{NULL}) or
 $A/\text{lc}(A)$ in $\F_q[X]$. Lifts the elements of $B$ mod $\kbd{pe} =
 p^e$, such that the congruence now holds mod $(T,p^e)$.
 
-The following technical function returns an optimal sequence of $p$-adic
-accuracies, for a given target accuracy:
-
-\fun{ulong}{quadratic_prec_mask}{long n} we want to reach accuracy
-$n\geq 1$, starting from accuracy 1, using a quadratically convergent,
-self-correcting, algorithm; in other words, from inputs correct to accuracy
-$l$ one iteration outputs a result correct to accuracy $2l$.
-For instance, to reach $n = 9$, we want to use accuracies
-$[1,2,3,5,9]$ instead of $[1,2,4,8,9]$. The idea is to essentially double
-the accuracy at each step, and not overshoot in the end.
-
-Let $a_0$ = 1, $a_1 = 2, \ldots, a_k = n$, be the desired sequence of
-accuracies. To obtain it, we work backwards and set
-$$ a_k = n,\quad a_{i-1} = (a_i + 1)\,\bs\, 2.$$
-This is in essence what the function returns.
-But we do not want to store the $a_i$ explicitly, even as a \typ{VECSMALL},
-since this would leave an object on the stack. Instead, we store $a_i$
-implicitly in a bitmask \kbd{MASK}: let $a_0 = 1$, if the $i$-th bit of the
-mask is set, set $a_{i+1} = 2a_i - 1$, and $2a_i$ otherwise; in short the
-bits indicate the places where we do something special and do not quite
-double the accuracy (which would be the straightforward thing to do).
-
-In fact, to avoid returning separately the mask and the sequence length
-$k+1$, the function returns $\kbd{MASK} + 2^{k+1}$, so the highest bit of
-the mask indicates the length of the sequence, and the following ones give
-an algorithm to obtain the accuracies. This is much simpler than it sounds,
-here is what it looks like in practice:
-\bprog
-  ulong mask = quadratic_prec_mask(n);
-  long l = 1;
-  while (mask > 1) {            /* here, the result is known to accuracy l */
-    l = 2*l; if (mask & 1) l--; /* new accuracy l for the iteration */
-    mask >>= 1;                 /* pop low order bit */
-    /* ... lift to the new accuracy ... */
-  }
-  /* we are done. At this point l = n */
- at eprog\noindent We just pop the bits in \kbd{mask} starting from the low
-order bits, stop when \kbd{mask} is $1$ (that last bit corresponds to the
-$2^{k+1}$ that we added to the mask proper). Note that there is nothing
-specific to Hensel lifts in that function: it would work equally well for
-an Archimedean Newton iteration.
-
-Note that in practice, we rather use an infinite loop, and insert an
-\bprog
-  if (mask == 1) break;
- at eprog\noindent in the middle of the loop: the loop body usually includes
-preparations for the next iterations (e.g. lifting Bezout coefficients
-in a quadratic Hensel lift), which are costly and useless in the \emph{last}
-iteration.
-
-\subsec{Other $p$-adic functions}
+\fun{GEN}{ZpX_Frobenius}{GEN T, GEN p, ulong e} returns the $p$-adic lift
+of the Frobenius automorphism of $\F_p[X]/(T)$ to precision $e$.
 
 \fun{long}{ZpX_disc_val}{GEN f, GEN p} returns the valuation at $p$ of the
 discriminant of $f$. Assume that $f$ is a monic \emph{separable} \kbd{ZX}
@@ -5455,39 +5767,149 @@ computes resultants for a sequence of increasing $p$-adic accuracies
 result. It is very inefficient when the resultant is $0$, but otherwise
 usually more efficient than computations using a priori bounds.
 
-\fun{GEN}{ZpM_echelon}{GEN M, long early_abort, GEN p, GEN pm} given a
-\kbd{ZM} $M$, a prime $p$ and $\kbd{pm} = p^m$, returns an echelon form
-$E$ for $M$ mod $p^m$. I.e. there exist a square integral matrix $U$ with
-$\det U$ coprime to $p$ such that $E = MU$ modulo $p^m$. I
-\kbd{early\_abort} is non-zero, return NULL as soon as one pivot in
-the echelon form is divisible by $p^m$. The echelon form is an upper
-triangular HNF, we do not waste time to reduce it to Gauss-Jordan form.
+\subsec{ZpXQ}
 
-\fun{GEN}{zlm_echelon}{GEN M, long early_abort, ulong p, ulong pm}
-variant of \kbd{ZpM\_echelon}, for a \kbd{Zlm} $M$.
+\fun{GEN}{ZpXQ_invlift}{GEN b, GEN a, GEN T, GEN p, long e} let
+$p$ be a prime \typ{INT} and $a,b$ be \kbd{FpXQ}s (modulo $T$) such that $a\*b
+\equiv 1 \mod (p,T)$.  Returns an \kbd{FpXQ} $A$ such that
+$A\*b \equiv 1 \mod (p^e, T)$.  Special case of \tet{ZpXQ_liftroot}.
+
+\fun{GEN}{ZpXQ_inv}{GEN b, GEN T, GEN p, long e} let
+$p$ be a prime \typ{INT} and $b$ be a \kbd{FpXQ} (modulo $T, p^e$).
+Returns an \kbd{FpXQ} $A$ such that $A\*b \equiv 1 \mod (p^e, T)$.
+
+\fun{GEN}{ZpXQ_sqrtnlift}{GEN b, GEN n, GEN a, GEN T, GEN p, long e} let
+$n,p$ be \typ{INT}s, with $n,p > 1$ and $p$ coprime to $n$, and $a,b$
+be \kbd{FpXQ}s (modulo $T$) such that $a^n \equiv b \mod (p,T)$.
+Returns an \kbd{Fq} $A$ such that $A^n \equiv b \mod (p^e, T)$.
+Special case of \tet{ZpXQ_liftroot}.
+
+\fun{GEN}{ZpXQ_sqrt}{GEN b, GEN T, GEN p, long e} let
+$p$ being a odd prime and $b$ be a \kbd{FpXQ} (modulo $T, p^e$),
+returns $a$ such that $a^2 \equiv b \mod (p^e, T)$.
+
+\fun{GEN}{ZpX_ZpXQ_liftroot}{GEN f, GEN a, GEN T, GEN p, long e}
+as \tet{ZpXQX_liftroot}, but $f$ is a polynomial in $\Z[X]$.
+
+\fun{GEN}{ZpX_ZpXQ_liftroot_ea}{GEN f, GEN a, GEN T, GEN p, long e,
+                     void *E, int early(void *E, GEN x, GEN q)}
+as \tet{ZpX_ZpXQ_liftroot} with early abort: the function \kbd{early(E,x,q)}
+will be called with $x$ is a root of $f$ modulo $q=p^n$ for some $n$. If early
+return a non-zero value, the function will return $x$ immediately.
 
 \fun{GEN}{ZpXQ_log}{GEN a, GEN T, GEN p, long e} $T$ being a \kbd{ZpX}
 irreducible modulo $p$, return the logarithm of $a$ in $\Z_p[X]/(T)$ to
 precision $e$, assuming that $a\equiv 1 \pmod{p\Z_p[X]}$ if $p$ odd or
 $a\equiv 1 \pmod{4\Z_2[X]}$ if $p=2$.
 
-\fun{GEN}{padic_to_Q}{GEN x} truncate the \typ{PADIC} to a \typ{INT} or
-\typ{FRAC}.
-
-\fun{GEN}{padic_to_Q_shallow}{GEN x} shallow version of \tet{padic_to_Q}
+\subsec{ZpXQM}
 
-\fun{GEN}{QpV_to_QV}{GEN v} apply \tet{padic_to_Q_shallow}
+\fun{GEN}{ZpXQM_prodFrobenius}{GEN M, GEN T, GEN p, long e}
+returns the product of matrices $M\*\sigma(M)\*\sigma^2(M)\ldots\sigma^{n-1}(M)$
+to precision $e$ where $\sigma$ is the lift of the Frobenius automorphism
+over $\Z_p[X]/(T)$ and $n$ is the degree of $T$.
 
-\fun{long}{padicprec}{GEN x, GEN p} returns the absolute $p$-adic precision of
-the object $x$, by definition the minimum precision of the components of $x$.
-For a non-zero \typ{PADIC}, this returns \kbd{valp(x) + precp(x)}.
+\subsec{ZpXQX}
 
-\fun{long}{padicprec_relative}{GEN x} returns the relative $p$-adic
-precision of the \typ{INT}, \typ{FRAC}, or \typ{PADIC} $x$ (minimum precision
-of the components of $x$ for \typ{POL} or vector/matrices).
-For a \typ{PADIC}, this returns \kbd{precp(x)} if $x\neq0$, and $0$ for $x=0$.
+\fun{GEN}{ZpXQX_liftroot}{GEN f, GEN a, GEN T, GEN p, long e} as
+\tet{ZpX_liftroot}, but $f$ is now a polynomial in $\Z[X,Y]$ and lift the
+root $a$ in the unramified extension of $\Q_p$ with residue field $\F_p[Y]/(T)$,
+assuming $v_p(f(a))>0$ and $v_p(f'(a))=0$.
 
-\subsec{Conversions involving single precision objects}
+\fun{GEN}{ZpXQX_liftroot_vald}{GEN f, GEN a, long v, GEN T, GEN p, long e}
+returns the foots of $f$ as \tet{ZpXQX_liftroot}, where $v$ is the valuation
+of the content of $f'$ and it is required that $v_p(f(a))>v$ and
+$v_p(f'(a))=v$.
+
+\subsec{Other $p$-adic functions}
+
+\fun{GEN}{ZpM_echelon}{GEN M, long early_abort, GEN p, GEN pm} given a
+\kbd{ZM} $M$, a prime $p$ and $\kbd{pm} = p^m$, returns an echelon form
+$E$ for $M$ mod $p^m$. I.e. there exist a square integral matrix $U$ with
+$\det U$ coprime to $p$ such that $E = MU$ modulo $p^m$. I
+\kbd{early\_abort} is non-zero, return NULL as soon as one pivot in
+the echelon form is divisible by $p^m$. The echelon form is an upper
+triangular HNF, we do not waste time to reduce it to Gauss-Jordan form.
+
+\fun{GEN}{zlm_echelon}{GEN M, long early_abort, ulong p, ulong pm}
+variant of \kbd{ZpM\_echelon}, for a \kbd{Zlm} $M$.
+
+\fun{GEN}{ZlM_gauss}{GEN a, GEN b, ulong p, long e, GEN C} as \kbd{gauss}
+with the following peculiarities: $a$ and $b$ are \kbd{ZM}, such that $a$ is
+invertible modulo $p$. Optional $C$ is an \kbd{Flm} that is an inverse of
+$a\mod p$ or \kbd{NULL}. Return the matrix $x$ such that $ax=b\mod p^e$ and
+all elements of $x$ are in $[0,p^e-1]$. For efficiency, it is better
+to reduce $a$ and $b$ mod $p^e$ first.
+
+\fun{GEN}{padic_to_Q}{GEN x} truncate the \typ{PADIC} to a \typ{INT} or
+\typ{FRAC}.
+
+\fun{GEN}{padic_to_Q_shallow}{GEN x} shallow version of \tet{padic_to_Q}
+
+\fun{GEN}{QpV_to_QV}{GEN v} apply \tet{padic_to_Q_shallow}
+
+\fun{long}{padicprec}{GEN x, GEN p} returns the absolute $p$-adic precision of
+the object $x$, by definition the minimum precision of the components of $x$.
+For a non-zero \typ{PADIC}, this returns \kbd{valp(x) + precp(x)}.
+
+\fun{long}{padicprec_relative}{GEN x} returns the relative $p$-adic
+precision of the \typ{INT}, \typ{FRAC}, or \typ{PADIC} $x$ (minimum precision
+of the components of $x$ for \typ{POL} or vector/matrices).
+For a \typ{PADIC}, this returns \kbd{precp(x)} if $x\neq0$, and $0$ for $x=0$.
+
+\subsubsec{low-level}
+
+The following technical function returns an optimal sequence of $p$-adic
+accuracies, for a given target accuracy:
+
+\fun{ulong}{quadratic_prec_mask}{long n} we want to reach accuracy
+$n\geq 1$, starting from accuracy 1, using a quadratically convergent,
+self-correcting, algorithm; in other words, from inputs correct to accuracy
+$l$ one iteration outputs a result correct to accuracy $2l$.
+For instance, to reach $n = 9$, we want to use accuracies
+$[1,2,3,5,9]$ instead of $[1,2,4,8,9]$. The idea is to essentially double
+the accuracy at each step, and not overshoot in the end.
+
+Let $a_0$ = 1, $a_1 = 2, \ldots, a_k = n$, be the desired sequence of
+accuracies. To obtain it, we work backwards and set
+$$ a_k = n,\quad a_{i-1} = (a_i + 1)\,\bs\, 2.$$
+This is in essence what the function returns.
+But we do not want to store the $a_i$ explicitly, even as a \typ{VECSMALL},
+since this would leave an object on the stack. Instead, we store $a_i$
+implicitly in a bitmask \kbd{MASK}: let $a_0 = 1$, if the $i$-th bit of the
+mask is set, set $a_{i+1} = 2a_i - 1$, and $2a_i$ otherwise; in short the
+bits indicate the places where we do something special and do not quite
+double the accuracy (which would be the straightforward thing to do).
+
+In fact, to avoid returning separately the mask and the sequence length
+$k+1$, the function returns $\kbd{MASK} + 2^{k+1}$, so the highest bit of
+the mask indicates the length of the sequence, and the following ones give
+an algorithm to obtain the accuracies. This is much simpler than it sounds,
+here is what it looks like in practice:
+\bprog
+  ulong mask = quadratic_prec_mask(n);
+  long l = 1;
+  while (mask > 1) {            /* here, the result is known to accuracy l */
+    l = 2*l; if (mask & 1) l--; /* new accuracy l for the iteration */
+    mask >>= 1;                 /* pop low order bit */
+    /* ... lift to the new accuracy ... */
+  }
+  /* we are done. At this point l = n */
+ at eprog\noindent We just pop the bits in \kbd{mask} starting from the low
+order bits, stop when \kbd{mask} is $1$ (that last bit corresponds to the
+$2^{k+1}$ that we added to the mask proper). Note that there is nothing
+specific to Hensel lifts in that function: it would work equally well for
+an Archimedean Newton iteration.
+
+Note that in practice, we rather use an infinite loop, and insert an
+\bprog
+  if (mask == 1) break;
+ at eprog\noindent in the middle of the loop: the loop body usually includes
+preparations for the next iterations (e.g. lifting Bezout coefficients
+in a quadratic Hensel lift), which are costly and useless in the \emph{last}
+iteration.
+
+\subsec{Conversions involving single precision objects}
 
 \subsubsec{To single precision}
 
@@ -5536,6 +5958,9 @@ called on the tree leaves.
 \fun{GEN}{ZXX_to_FlxX}{GEN B, ulong p, long v}, as \kbd{ZX\_to\_Flx},
 repeatedly called on the polynomial's coefficients.
 
+\fun{GEN}{zxX_to_FlxX}{GEN z, ulong p} as \kbd{zx\_to\_Flx},
+repeatedly called on the polynomial's coefficients.
+
 \fun{GEN}{ZXXV_to_FlxXV}{GEN V, ulong p, long v}, as \kbd{ZXX\_to\_FlxX},
 repeatedly called on the vector's coefficients.
 
@@ -5593,7 +6018,10 @@ vector of polynomials with \typ{INT} coefficients (repeated calls to
 polynomials with \typ{INT} coefficients (repeated calls to \kbd{Flx\_to\_ZX}).
 
 \fun{GEN}{zx_to_ZX}{GEN z}, as \kbd{Flx\_to\_ZX}, without assuming
-coefficients are non-negative.
+the coefficients to be non-negative.
+
+\fun{GEN}{zx_to_Flx}{GEN z, ulong p} as \kbd{Flx\_red} without assuming
+the coefficients to be non-negative.
 
 \fun{GEN}{Flc_to_ZC}{GEN z}, converts to \kbd{ZC} (\typ{COL} of non-negative
 \typ{INT}s in this case)
@@ -5630,6 +6058,8 @@ Multiply a multiprecision object by a single-precision one.
 
 \fun{GEN}{ZM_zc_mul}{GEN x, GEN y}
 
+\fun{GEN}{ZV_zc_mul}{GEN x, GEN y}
+
 \fun{GEN}{ZM_zm_mul}{GEN x, GEN y}
 
 \fun{GEN}{ZC_z_mul}{GEN x, long y}
@@ -5893,6 +6323,13 @@ are all non-zero.
 integer $n$, return the factorization of $|n|$, i.e.~remove $-1$ from the
 factorization. Shallow function.
 
+\fun{GEN}{fuse_Z_factor}{GEN f, GEN B} assuming $f$ is the
+factorization of an integer $n$, return \kbd{boundfact(n, B)}, i.e.
+return a factorization where all primary factors for $|p| \leq B$
+are preserved, and all others are ``fused'' into a single composite
+integer; if that remainder is trivial, i.e.~equal to 1, it is of course
+not included. Shallow function.
+
 In the following two routines, $f$ is the name of an arithmetic function,
 and $n$ a supplied argument. They all raise exceptions if $n$ does not
 correspond to an integer or an integer factorization of the expected shape.
@@ -6164,7 +6601,7 @@ assumed to have compatible dimensions).
 \fun{GEN}{ZV_content}{GEN x} returns the GCD of all the components
 of~\kbd{x}.
 
-\fun{GEN}{ZV_gcdext}{GEN A} given a vector of $n$ integers $A$, returns $[d,
+\fun{GEN}{ZV_extgcd}{GEN A} given a vector of $n$ integers $A$, returns $[d,
 U]$, where $d$ is the content of $A$ and $U$ is a matrix
 in $\text{GL}_n(\Z)$ such that $AU = [D,0, \dots,0]$.
 
@@ -6224,6 +6661,8 @@ not be corrupted. (We use \tet{togglesign_safe}.)
 \fun{GEN}{ZM_mul}{GEN x, GEN y} multiplies \kbd{x} and \kbd{y} (assumed to
 have compatible dimensions).
 
+\fun{GEN}{ZM_sqr}{GEN x} returns $x^2$, where $x$ is a square \kbd{ZM}.
+
 \fun{GEN}{ZM_Z_mul}{GEN x, GEN y} multiplies the \kbd{ZM}~\kbd{x}
 by the \typ{INT}~\kbd{y}.
 
@@ -6235,6 +6674,8 @@ dimensions).
 
 \fun{GEN}{ZM_transmultosym}{GEN x, GEN y}
 
+\fun{GEN}{ZM_transmul}{GEN x, GEN y}
+
 \fun{GEN}{ZMrow_ZC_mul}{GEN x, GEN y, long i} multiplies the $i$-th row
 of \kbd{ZM}~\kbd{x} by the \kbd{ZC}~\kbd{y} (seen as a column vector, assumed
 to have compatible dimensions). Assumes that $x$ is non-empty and
@@ -6246,6 +6687,9 @@ by the \kbd{ZM}~\kbd{y}. Returns a \typ{VEC}.
 \fun{GEN}{ZM_Z_divexact}{GEN x, GEN y} returns $x/y$ assuming all divisions
 are exact.
 
+\fun{GEN}{ZM_Z_div}{GEN x, GEN y} returns $x/y$, where the resulting matrix
+has rational entries.
+
 \fun{GEN}{ZM_pow}{GEN x, GEN n} returns $\kbd{x}^\kbd{n}$, assuming \kbd{x}
 is a square \kbd{ZM} and $\kbd{n}\geq 0$.
 
@@ -6264,6 +6708,10 @@ underlying \tet{detint}.
 \fun{GEN}{ZM_charpoly}{GEN M} returns the characteristic polynomial (in
 variable $0$) of the \kbd{ZM} $M$.
 
+\fun{GEN}{QM_charpoly_ZX}{GEN M} returns the characteristic polynomial
+(in variable $0$) of the \kbd{QM} $M$, assuming that the result has integer
+coefficients.
+
 \fun{GEN}{ZM_imagecompl}{GEN x} returns \kbd{matimagecompl(x)}.
 
 \fun{long}{ZM_rank}{GEN x} returns \kbd{matrank(x)}.
@@ -6286,13 +6734,34 @@ still assume that $M'$ has integer coefficients.
 \fun{GEN}{ZM_det_triangular}{GEN x} returns the product of the diagonal
 entries of $x$ (its determinant if it is indeed triangular).
 
-\fun{int}{ZM_isidentity}{GEN x} return 1 is the \typ{ZM} $x$ is the
+\fun{int}{ZM_isidentity}{GEN x} return 1 is the \kbd{ZM} $x$ is the
 identity matrix, and 0 otherwise.
 
+\fun{long}{ZC_is_ei}{GEN x} return $i$ if the \kbd{ZC} $x$ has $0$ entries,
+but for a $1$ at position $i$.
+
 \fun{int}{ZM_ishnf}{GEN x} return $1$ if $x$ is in HNF form, i.e. is upper
 triangular with positive diagonal coefficients, and  for $j>i$,
 $x_{i,i}>x_{i,j} \ge 0$.
 
+\fun{GEN}{Qevproj_init}{GEN M} let $M$ be a  $n\times d$ \kbd{ZM} of
+maximal rank $d \leq n$, representing the basis of a $\Q$-subspace
+$V$ of $\Q^n$. Return a projector on $V$, to be used by \tet{Qevproj_apply}.
+The interface details may change in the future, but this function currently
+returns $[M, B,D,p]$, where $p$ is a \typ{VECSMALL} with $d$ entries
+such that the submatrix $A = \kbd{rowpermute}(M,p)$ is invertible, $B$ is a
+\kbd{ZM} and $d$ a \typ{INT} such that $A B = D \Id_d$.
+
+\fun{GEN}{Qevproj_apply}{GEN T, GEN pro} let $T$ be an $n\times n$
+\kbd{QM}, stabilizing a $\Q$-subspace $V\subset \Q^n$ of dimension $d$, and
+let \kbd{pro} be a projector on that subspace initialized by
+\tet{Qevproj_init}$(M)$. Return the $d\times d$ matrix representing $T_{|V}$
+on the basis given by the columns of $M$.
+
+\fun{GEN}{Qevproj_apply_vecei}{GEN T, GEN pro, long k} as
+\tet{Qevproj_apply}, return only the image of the $k$-th basis vector $M[k]$
+(still on the basis given by the columns of $M$).
+
 \subsec{\kbd{zv}, \kbd{zm}}
 
 \fun{GEN}{zv_neg}{GEN x} return $-x$. No check for overflow is done, which
@@ -6358,6 +6827,8 @@ or \typ{COL} return $1$ if its components are \kbd{ZM}, and $0$ otherwise.
 
 \fun{GEN}{zmV_to_ZMV}{GEN z}
 
+\fun{GEN}{ZMV_to_FlmV}{GEN z, ulong m}
+
 \subsec{\kbd{RgC} / \kbd{RgV}, \kbd{RgM}}
 
 \kbd{RgC} and \kbd{RgV} routines assume the inputs are \kbd{VEC} or \kbd{COL}
@@ -6466,6 +6937,9 @@ a column matrix $n\times 1$, error otherwise.
 v[n]$ (assumes that \kbd{lg}$(v) > n$ and $m > 0$). Returns \kbd{gen\_0}
 when $m > n$.
 
+\fun{GEN}{RgM_sumcol}{GEN v} returns a \typ{COL}, sum of the columns of the
+\typ{MAT} $v$.
+
 \fun{GEN}{RgV_dotproduct}{GEN x,GEN y} returns the scalar product of $x$ and $y$
 
 \fun{GEN}{RgV_dotsquare}{GEN x} returns the scalar product of $x$ with itself.
@@ -6505,6 +6979,9 @@ identity matrix, and 0 otherwise.
 \fun{int}{RgM_isdiagonal}{GEN x} return 1 is the \typ{MAT} $x$ is a
 diagonal matrix, and 0 otherwise.
 
+\fun{long}{RgC_is_ei}{GEN x} return $i$ if the \typ{COL} $x$ has $0$ entries,
+but for a $1$ at position $i$.
+
 \fun{int}{RgM_is_ZM}{GEN x} return 1 is the \typ{MAT}~$x$ has only
 \typ{INT} coefficients, and 0 otherwise.
 
@@ -6587,7 +7064,7 @@ entries of $x$ (its determinant if it is indeed triangular).
 
 \fun{GEN}{Frobeniusform}{GEN V, long n} given the vector $V$ of elementary
 divisors for $M - x\text{Id}$, where $M$ is an $n\times n$ square matrix.
-Returns the Frobenius form of $M$. Used by \kbd{matfrobenius}.
+Returns the Frobenius form of $M$.
 
 \fun{int}{RgM_QR_init}{GEN x, GEN *pB, GEN *pQ, GEN *pL, long prec}
 QR-decomposition of a square invertible \typ{MAT} $x$ with real coefficients.
@@ -6614,6 +7091,55 @@ invertible \typ{MAT} with \typ{INT} or \typ{REAL} coefficients, returns
 matrix from the $QR$ decomposition of $x$, renormalized to accomodate
 \kbd{qfgaussred} conventions. Not memory clean.
 
+\subsec{\kbd{ZG}}
+
+Let $G$ be a multiplicative group with neutral element $1_G$ whose
+multiplication is supported by \kbd{gmul} and where equality test is
+performed using \tet{gidentical}, e.g. a matrix group. The following
+routines implement basic computations in the group algebra $\Z[G]$. All of
+them are shallow for efficiency reasons. A \kbd{ZG} is either
+
+\item a \typ{INT} $n$, representing $n[1_G]$
+
+\item or a ``factorization matrix'' with two columns $[g,e]$: the first one
+contains group elements, sorted according to \tet{cmp_universal}, and the
+second one contains integer ``exponents'', representing $\sum e_i [g_i]$.
+
+Note that \tet{to_famat} and \tet{to_famat_shallow}$(g,e)$ allow to build
+the \kbd{ZG} $e[g]$ from $e\in \Z$ and $g\in G$.
+
+\fun{GEN}{ZG_normalize}{GEN x} given a \typ{INT} $x$ or a factorization
+matrix \emph{without} assuming that the first column is properly sorted.
+Return a valid (sorted) \kbd{ZG}. Shallow function.
+
+\fun{GEN}{ZG_add}{GEN x, GEN y} return $x+y$; shallow function.
+
+\fun{GEN}{ZG_neg}{GEN x} return $-x$; shallow function.
+
+\fun{GEN}{ZG_sub}{GEN x, GEN y} return $x-y$; shallow function.
+
+\fun{GEN}{ZG_mul}{GEN x, GEN y} return $xy$; shallow function.
+
+\fun{GEN}{ZG_G_mul}{GEN x, GEN y} given a \kbd{ZG} $x$ and $y\in G$,
+ return $xy$; shallow function.
+
+\fun{GEN}{G_ZG_mul}{GEN x, GEN y} given a \kbd{ZG} $y$ and $x\in G$,
+ return $xy$; shallow function.
+
+\fun{GEN}{ZG_Z_mul}{GEN x, GEN n} given a \kbd{ZG} $x$ and $y\in \Z$,
+ return $xy$; shallow function.
+
+\fun{GEN}{ZGC_G_mul}{GEN v, GEN x} given $v$ a vector of \kbd{ZG} and $x\in
+G$ return the vector (with the same type as $v$ with entries $v[i]\cdot x$.
+Shallow function.
+
+\fun{GEN}{ZGC_Z_mul}{GEN v, GEN n} given $v$ a vector of \kbd{ZG} and $n\in
+Z$ return the vector (with the same type as $v$ with entries $n \cdot v[i]$.
+Shallow function.
+
+\fun{GEN}{G_ZGC_mul}{GEN x, GEN v} given $v$ a vector of \kbd{ZG} and $x\in
+G$ return the vector of $x \cdot v[i]$. Shallow function.
+
 \subsec{Blackbox linear algebra}
 
 A sparse column \kbd{zCs} $v$ is a \typ{COL} with two components $C$ and $E$
@@ -6788,6 +7314,9 @@ $y$ is monic.
 \fun{GEN}{ZX_mod_Xnm1}{GEN T, ulong n} return $T$ modulo $X^n - 1)$. Shallow
 function.
 
+\fun{GEN}{ZX_div_by_X_1}{GEN T, GEN *r} return the quotient of $T$ by $X-1$.
+If $r$ is not \kbd{NULL} set it to $T(1)$.
+
 \fun{GEN}{ZX_gcd}{GEN x,GEN y} returns a gcd of the \kbd{ZX} $x$ and $y$.
 Not memory-clean, but suitable for \kbd{gerepileupto}.
 
@@ -6831,6 +7360,10 @@ smaller coefficients.
 \kbd{P} is a \kbd{ZX} and \kbd{h} is a non-zero integer. Neither memory-clean
 nor suitable for \kbd{gerepileupto}.
 
+\fun{GEN}{ZX_rescale2n}{GEN P, long n} returns $2^{n\deg(P)} P(x>>n)$ where
+\kbd{P} is a \kbd{ZX}. Neither memory-clean nor suitable for
+\kbd{gerepileupto}.
+
 \fun{GEN}{ZX_rescale_lt}{GEN P} returns the monic integral polynomial
 $h^{\deg(P)-1} P(x/h)$, where \kbd{P} is a non-zero \kbd{ZX} and \kbd{h} is
 its leading coefficient. Neither memory-clean nor suitable for
@@ -6842,6 +7375,9 @@ integer. Returns $P(X + c)$ (optimized for $c = \pm 1$).
 \fun{GEN}{ZX_unscale}{GEN P, GEN h} given a \kbd{ZX} $P$ and a \typ{INT} $h$,
 returns $P(hx)$. Not memory clean.
 
+\fun{GEN}{ZX_unscale2n}{GEN P, long n} given a \kbd{ZX} $P$, returns
+$P(x<<n)$. Not memory clean.
+
 \fun{GEN}{ZX_unscale_div}{GEN P, GEN h} given a \kbd{ZX} $P$ and a \typ{INT} $h$
 such that $h \mid P(0)$, returns $P(hx)/h$. Not memory clean.
 
@@ -6872,6 +7408,38 @@ with the $e_1 < e_2 < \cdots$ all distinct and the $T_i$ pairwise coprime.
 Return the vector of the $T_i$, and set \kbd{*E} to the vector of the $e_i$,
 as a \typ{VECSMALL}.
 
+\fun{GEN}{ZX_uspensky}{GEN P, GEN ab, long flag, long bitprec} let \kbd{P} be a
+primitive \kbd{ZX} polynomial whose real roots are simple and \kbd{bitprec} is
+the relative precision in bits.
+
+\item If \kbd{flag} is 0 returns a list of intervals that isolate the real
+roots of \kbd{P}. The return value is a column of elements which are either
+vectors \kbd{[a,b]} meaning that there is a single root in the open interval
+\kbd{(a,b)} or elements \kbd{x0} such that \kbd{x0} is a root of \kbd{P}.
+There is no guarantee that all rational roots are found (at most those with
+denominator a power of $2$ can be found and even those are not guaranteed).
+Beware that the limits of the open intervals can be roots of the polynomial.
+
+\item If \kbd{flag} is 1 returns an approximation of the real roots of \kbd{P}.
+
+\item If \kbd{flag} is 2 returns the number of roots.
+
+The argument \kbd{ab} specify the interval in which the roots
+are searched. The default interval is $(-\infty,\infty)$. If \kbd{ab} is an
+integer or fraction $a$ then the interval is $[a,\infty)$. If \kbd{ab} is
+a vector $[a,b]$, where \typ{INT}, \typ{FRAC} or \typ{INFINITY} are allowed
+for $a$ and $b$, the interval is $[a,b]$.
+
+\fun{long}{ZX_sturm}{GEN P} number of real roots of the non-constant
+squarefree \kbd{ZX} $P$. For efficiency, it is advised to make $P$ primitive
+first.
+
+\fun{long}{ZX_sturmpart}{GEN P, GEN ab} number of real roots of the
+non-constant squarefree \kbd{ZX} $P$ in the interval specified by \kbd{ab}:
+either \kbd{NULL} (no restriction) or a \typ{VEC} $[a,b]$ with two real
+components (of type \typ{INT}, \typ{FRAC} or \typ{INFINITY}). For efficiency,
+it is advised to make $P$ primitive first.
+
 \subsec{\kbd{ZXQ}}
 
 \fun{GEN}{ZXQ_mul}{GEN x,GEN y,GEN T} returns $x*y$ mod $T$, assuming
@@ -6935,6 +7503,10 @@ $\kbd{l} = \kbd{lg(x)}$, in place.
 \fun{long}{ZXX_max_lg}{GEN x} returns the effective length of the longest
 component in $x$; assume all coefficients are \typ{INT} or \kbd{ZX}s.
 
+\fun{GEN}{ZXX_Z_mul}{GEN x, GEN y} returns $x\*y$.
+
+\fun{GEN}{ZXX_Z_add_shallow}{GEN x, GEN y} returns $x+y$. Shallow function.
+
 \fun{GEN}{ZXX_Z_divexact}{GEN x, GEN y} returns $x/y$ assuming all integer
 divisions are exact.
 
@@ -6948,13 +7520,17 @@ $\sum_{i = 0}^{\kbd{lQ} - 1} Q[i] x^i$. To be used when splitting
 the coefficients of genuine polynomials into blocks. Shallow function.
 
 \fun{GEN}{Kronecker_to_ZXX}{GEN z, long n, long v} recover $P(X,Y)$
-from its Kronecker form $P(X,X^{2*n-1})$, $v$ is the variable number
+from its Kronecker form $P(X,X^{2\*n-1})$, $v$ is the variable number
 corresponding to $Y$. Shallow function.
 
 \fun{GEN}{ZXX_mul_Kronecker}{GEN P, GEN Q, long n} return \tet{ZX_mul}
-applied to the Kronecker forms $P(X,X^{2n-1})$ and $Q(X,X^{2n-1}$
+applied to the Kronecker forms $P(X,X^{2\*n-1})$ and $Q(X,X^{2\*n-1})$
 of $P$ and $Q$. Not memory clean.
 
+\fun{GEN}{ZXX_sqr_Kronecker}{GEN P, long n} return \tet{ZX_sqr}
+applied to the Kronecker forms $P(X,X^{2\*n-1})$
+of $P$. Not memory clean.
+
 \subsec{\kbd{QX}}
 
 \fun{void}{RgX_check_QX}{GEN x, const char *s} Assuming \kbd{x} is a \typ{POL}
@@ -7058,6 +7634,8 @@ multiplied by $\kbd{x}^n$, assuming $n\geq 0$.
 
 \subsec{\kbd{RgX}}
 
+\subsubsec{Coefficient ring}
+
 \fun{long}{RgX_type}{GEN x, GEN *ptp, GEN *ptpol, long *ptprec} returns
 the ``natural'' base ring over which the polynomial $x$ is defined. Raise an
 error if it detects consistency problems in modular objects: incompatible rings
@@ -7124,24 +7702,122 @@ is defined, to the proper accuracy (e.g. \kbd{0}, \kbd{Mod(0,3)},
 \fun{GEN}{RgX_get_1}{GEN x} returns $1$ in the base ring over which $x$
 is defined, to the proper accuracy (e.g. \kbd{0}, \kbd{Mod(0,3)},
 
+\subsubsec{Tests}
+
+\fun{long}{RgX_degree}{GEN x, long v} $x$ being a \typ{POL} and $v \geq 0$,
+returns the degree in $v$ of $x$. Error if $x$ is not a polynomial in $v$.
+
 \fun{int}{RgX_isscalar}{GEN x} return 1 if $x$ all the coefficients of
 $x$ of degree $> 0$ are $0$ (as per \kbd{gequal0}).
 
+\fun{int}{RgX_is_rational}{GEN P} return 1 is the \kbd{RgX}~$P$ has only
+rational coefficients (\typ{INT} and \typ{FRAC}), and 0 otherwise.
+
+\fun{int}{RgX_is_QX}{GEN P} return 1 is the \kbd{RgX}~$P$ has only
+\typ{INT} and \typ{FRAC} coefficients, and 0 otherwise.
+
+\fun{int}{RgX_is_ZX}{GEN P} return 1 is the \kbd{RgX}~$P$ has only
+\typ{INT} coefficients, and 0 otherwise.
+
+\fun{int}{RgX_is_monomial}{GEN x} returns 1 (true) if \kbd{x} is a non-zero
+monomial in its main variable, 0~otherwise.
+
+\fun{long}{RgX_equal}{GEN x, GEN y} returns $1$ if the \typ{POL}s $x$ and $y$
+have the same \kbd{degpol} and their coefficients are equal (as per
+\tet{gequal}). Variable numbers are not checked. Note that this is more
+stringent than \kbd{gequal(x,y)}, which only checks whether $x - y$ satisfies
+\kbd{gequal0}; in particular, they may have different apparent degrees provided
+the extra leading terms are $0$.
+
+\fun{long}{RgX_equal_var}{GEN x, GEN y} returns $1$ if $x$ and $y$
+have the same variable number and \kbd{RgX\_equal(x,y)} is $1$.
+
+\subsubsec{Coefficients, blocks}
+
+\fun{GEN}{RgX_coeff}{GEN P, long n} return the coefficient of $x^n$ in $P$,
+defined as \kbd{gen\_0} if $n < 0$ or $n > \kbd{degpol}(P)$. Shallow
+function.
+
 \fun{int}{RgX_blocks}{GEN P, long n, long m} writes
 $P(X)=a_0(X)+X^n*a_1(X)*X^n+\ldots+X^{n*(m-1)}\*a_{m-1}(X)$,
 where the $a_i$ are polynomial of degree at most $n-1$
 (except possibly for the last one) and returns
-$[a_0(X),a_1(X),\ldots,a_{m-1}(X)]$.  This is a shallow function.
+$[a_0(X),a_1(X),\ldots,a_{m-1}(X)]$.  Shallow function.
 
 \fun{void}{RgX_even_odd}{GEN p, GEN *pe, GEN *po} write $p(X) = E(X^2) +
-X O(X^2)$ and set \kbd{*pe = E}, \kbd{*po = O}.
+X O(X^2)$ and set \kbd{*pe = E}, \kbd{*po = O}.  Shallow function.
 
 \fun{GEN}{RgX_splitting}{GEN P, long k} write
 $P(X)=a_0(X^k)+X\*a_1(X^k)+\ldots+X^{k-1}\*a_{k-1}(X^k)$ and return
-$[a_0(X),a_1(X),\ldots,a_{k-1}(X)]$.  This is a shallow function.
+$[a_0(X),a_1(X),\ldots,a_{k-1}(X)]$.  Shallow function.
 
 \fun{GEN}{RgX_copy}{GEN x} returns (a deep copy of) $\kbd{x}$.
 
+\fun{GEN}{RgX_renormalize}{GEN x} remove leading terms in \kbd{x} which are
+equal to (necessarily inexact) zeros.
+
+\fun{GEN}{RgX_renormalize_lg}{GEN x, long lx} as \kbd{setlg(x, lx)}
+followed by \kbd{RgX\_renormalize(x)}. Assumes that $\kbd{lx} \leq
+\kbd{lg(x)}$.
+
+\fun{GEN}{RgX_recip}{GEN P} returns the reverse of the polynomial
+$P$, i.e. $X^{\deg P} P(1/X)$.
+
+\fun{GEN}{RgX_recip_shallow}{GEN P} shallow function of \tet{RgX_recip}.
+
+\fun{GEN}{RgX_deflate}{GEN P, long d} assuming $P$ is a polynomial of the
+form $Q(X^d)$, return $Q$. Shallow function, not suitable for
+\kbd{gerepileupto}.
+
+\fun{long}{RgX_deflate_max}{GEN P, long *d} sets \kbd{d} to the largest exponent
+such that $P$ is of the form $P(x^d)$ (use \kbd{gequal0} to check
+whether coefficients are 0), $0$ if $P$ is the zero polynomial. Returns
+\kbd{RgX\_deflate(P,d)}. Shallow function.
+
+\fun{GEN}{RgX_inflate}{GEN P, long d} return $P(X^d)$. Shallow function, not
+suitable for \kbd{gerepileupto}.
+
+\subsubsec{Shifts, valuations}
+
+\fun{GEN}{RgX_shift}{GEN x, long n} returns $\kbd{x} * t^n$ if $n\geq 0$,
+and $\kbd{x} \bs t^{-n}$ otherwise.
+
+\fun{GEN}{RgX_shift_shallow}{GEN x, long n} as \kbd{RgX\_shift}, but
+shallow (coefficients are not copied).
+
+\fun{GEN}{RgX_rotate_shallow}{GEN P, long k, long p} returns $\kbd{P} * X^k
+\pmod {X^p-1}$, assuming the degree of $P$ is strictly less than $p$, and
+$k\geq 0$.
+
+\fun{void}{RgX_shift_inplace_init}{long v} $v \geq 0$, prepare for a later
+call to \tet{RgX_shift_inplace}. Reserves $v$ words on the stack.
+
+\fun{GEN}{RgX_shift_inplace}{GEN x, long v} $v \geq 0$, assume that
+\tet{RgX_shift_inplace_init}$(v)$ has been called (reserving $v$ words on the
+stack), immediately followed by a \typ{POL} $x$. Return \kbd{RgX\_shift}$(x,v)$
+by shifting $x$ in place. To be used as follows
+\bprog
+  RgX_shift_inplace_init(v);
+  av = avma;
+  ...
+  x = gerepileupto(av, ...); /* a t_POL */
+  return RgX_shift_inplace(x, v);
+ at eprog
+
+\fun{long}{RgX_valrem}{GEN P, GEN *pz} returns the valuation $v$ of the
+\typ{POL}~\kbd{P} with respect to its main variable $X$. Check whether
+coefficients are $0$ using \kbd{gequal0}. Set \kbd{*pz} to
+$\kbd{RgX\_shift\_shallow}(P,-v)$.
+
+\fun{long}{RgX_val}{GEN P} returns the valuation $v$ of the
+\typ{POL}~\kbd{P} with respect to its main variable $X$. Check whether
+coefficients are $0$ using \kbd{gequal0}.
+
+\fun{long}{RgX_valrem_inexact}{GEN P, GEN *z} as \kbd{RgX\_valrem}, using
+\kbd{isexactzero} instead of \kbd{gequal0}.
+
+\subsubsec{Basic arithmetic}
+
 \fun{GEN}{RgX_add}{GEN x,GEN y} adds \kbd{x} and \kbd{y}.
 
 \fun{GEN}{RgX_sub}{GEN x,GEN y} subtracts \kbd{x} and \kbd{y}.
@@ -7156,6 +7832,28 @@ $[a_0(X),a_1(X),\ldots,a_{k-1}(X)]$.  This is a shallow function.
 
 \fun{GEN}{RgX_Rg_sub}{GEN y, GEN x} returns $x-y$
 
+\fun{GEN}{RgX_Rg_mul}{GEN y, GEN x} multiplies the \kbd{RgX} \kbd{y}
+by the scalar \kbd{x}.
+
+\fun{GEN}{RgX_muls}{GEN y, long s} multiplies the \kbd{RgX} \kbd{y}
+by the \kbd{long}~\kbd{s}.
+
+\fun{GEN}{RgX_Rg_div}{GEN y, GEN x} divides the \kbd{RgX} \kbd{y}
+by the scalar \kbd{x}.
+
+\fun{GEN}{RgX_divs}{GEN y, long s} divides the \kbd{RgX} \kbd{y}
+by the \kbd{long}~\kbd{s}.
+
+\fun{GEN}{RgX_Rg_divexact}{GEN x, GEN y} exact division of the \kbd{RgX}
+\kbd{y} by the scalar \kbd{x}.
+
+\fun{GEN}{RgX_normalize}{GEN x} divides $x$ by its
+leading coefficient. If the latter is~$1$, $x$ itself is returned, not a
+copy. Leading coefficients equal to $0$ are stripped, e.g.
+\bprog
+  0.*t^3 + Mod(0,3)*t^2 + 2*t
+ at eprog\noindent is normalized to $t$.
+
 \fun{GEN}{RgX_mul}{GEN x, GEN y} multiplies the two \typ{POL} (in the same
 variable) \kbd{x} and \kbd{y}. Uses Karatsuba algorithm.
 
@@ -7169,10 +7867,6 @@ $\sum_{i = 0}^{\kbd{na-1}} \kbd{a}[i] X^i$ and
 $\sum_{i = 0}^{\kbd{nb-1}} \kbd{b}[i] X^i$. Returns their product (as a true
 \kbd{GEN}).
 
-\fun{GEN}{RgX_mullow}{GEN a, GEN b, long n} returns $a b$ modulo $X^n$,
-where $a,b$ are two \typ{POL} in the same variable $X$ and $n \geq 0$. Uses
-Karatsuba algorithm (Mulders, Hanrot-Zimmermann variant).
-
 \fun{GEN}{RgX_sqr}{GEN x} squares the \typ{POL} \kbd{x}. Uses Karatsuba
 algorithm.
 
@@ -7181,10 +7875,6 @@ algorithm.
 $\sum_{i = 0}^{\kbd{na-1}} \kbd{a}[i] X^i$. Return its square (as a true
 \kbd{GEN}).
 
-\fun{GEN}{RgX_sqrlow}{GEN a, long n} returns $a^2$ modulo $X^n$,
-where $a$ is a \typ{POL} in the variable $X$ and $n \geq 0$. Uses
-Karatsuba algorithm (Mulders, Hanrot-Zimmermann variant).
-
 \fun{GEN}{RgX_divrem}{GEN x, GEN y, GEN *r} by default, returns the Euclidean
 quotient and store the remainder in $r$. Three special values of $r$ change
 that behavior
@@ -7210,9 +7900,6 @@ $q$ and pseudo-remainder $r$ such that $\kbd{lc}(y)^{\deg(x) - \deg(y) + 1}x
 \fun{GEN}{RgX_pseudorem}{GEN x, GEN y} return the remainder
 in the pseudo-division of $x$ by $y$.
 
-\fun{long}{RgX_degree}{GEN x, long v} $x$ being a \typ{POL} and $v \geq 0$,
-returns the degree in $v$ of $x$. Error if $x$ is not a polynomial in $v$.
-
 \fun{GEN}{RgXQX_pseudorem}{GEN x, GEN y, GEN T} return the remainder
 in the pseudo-division of $x$ by $y$ over $R[X]/(T)$.
 
@@ -7231,48 +7918,7 @@ set \kbd{*ptr} to $r$.
 be a \typ{FRAC} if $n < 0$ and the valuation of \kbd{x} is not large
 enough.
 
-\fun{GEN}{RgX_shift}{GEN x, long n} returns $\kbd{x} * t^n$ if $n\geq 0$,
-and $\kbd{x} \bs t^{-n}$ otherwise.
-
-\fun{GEN}{RgX_shift_shallow}{GEN x, long n} as \kbd{RgX\_shift}, but
-shallow (coefficients are not copied).
-
-\fun{GEN}{RgX_rotate_shallow}{GEN P, long k, long p} returns $\kbd{P} * X^k
-\pmod {X^p-1}$, assuming the degree of $P$ is strictly less than $p$, and
-$k\geq 0$.
-
-\fun{void}{RgX_shift_inplace_init}{long v} $v \geq 0$, prepare for a later
-call to \tet{RgX_shift_inplace}. Reserves $v$ words on the stack.
-
-\fun{GEN}{RgX_shift_inplace}{GEN x, long v} $v \geq 0$, assume that
-\tet{RgX_shift_inplace_init}$(v)$ has been called (reserving $v$ words on the
-stack), immediately followed by a \typ{POL} $x$. Return \kbd{RgX\_shift}$(x,v)$
-by shifting $x$ in place. To be used as follows
-\bprog
-  RgX_shift_inplace_init(v);
-  av = avma;
-  ...
-  x = gerepileupto(av, ...); /* a t_POL */
-  return RgX_shift_inplace(x, v);
- at eprog
-
-\fun{long}{RgX_valrem}{GEN P, GEN *pz} returns the valuation $v$ of the
-\typ{POL}~\kbd{P} with respect to its main variable $X$. Check whether
-coefficients are $0$ using \kbd{gequal0}. Set \kbd{*pz} to
-$\kbd{RgX\_shift\_shallow}(P,-v)$.
-
-\fun{long}{RgX_val}{GEN P} returns the valuation $v$ of the
-\typ{POL}~\kbd{P} with respect to its main variable $X$. Check whether
-coefficients are $0$ using \kbd{gequal0}.
-
-\fun{long}{RgX_valrem_inexact}{GEN P, GEN *z} as \kbd{RgX\_valrem}, using
-\kbd{isexactzero} instead of \kbd{gequal0}.
-
-\fun{GEN}{RgX_deriv}{GEN x} returns the derivative of \kbd{x} with respect to
-its main variable.
-
-\fun{GEN}{RgX_integ}{GEN x} returns the primitive of \kbd{x} vanishing at
-$0$, with respect to its main variable.
+\subsubsec{GCD, Resultant}
 
 \fun{GEN}{RgX_gcd}{GEN x, GEN y} returns the GCD of \kbd{x} and \kbd{y},
 assumed to be \typ{POL}s in the same variable.
@@ -7299,19 +7945,7 @@ non-constant remainder in the polynomial remainder sequence if it exists and to
 \kbd{resultant\_all}, this function always uses the generic subresultant
 algorithm, hence always computes \kbd{sol}.
 
-\fun{GEN}{RgX_modXn_shallow}{GEN x, long n} return $\kbd{x \% } t^n$,
-where $n\geq 0$. Shallow function.
-
-\fun{GEN}{RgX_modXn_eval}{GEN Q, GEN x, long n} special case of
-\tet{RgX_RgXQ_eval}, when the modulus is a monomial:
-returns $\kbd{Q}(\kbd{x})$ modulo $t^n$, where $x \in R[t]$.
-
-\fun{GEN}{RgX_renormalize}{GEN x} remove leading terms in \kbd{x} which are
-equal to (necessarily inexact) zeros.
-
-\fun{GEN}{RgX_renormalize_lg}{GEN x, long lx} as \kbd{setlg(x, lx)}
-followed by \kbd{RgX\_renormalize(x)}. Assumes that $\kbd{lx} \leq
-\kbd{lg(x)}$.
+\subsubsec{Other operations}
 
 \fun{GEN}{RgX_gtofp}{GEN x, GEN prec} returns the polynomial obtained by
 applying
@@ -7324,22 +7958,11 @@ applying
   gnorml2( RgX_gtofp(x, prec) )
 @eprog
 
-\fun{GEN}{RgX_recip}{GEN P} returns the reverse of the polynomial
-$P$, i.e. $X^{\deg P} P(1/X)$.
-
-\fun{GEN}{RgX_recip_shallow}{GEN P} shallow function of \tet{RgX_recip}.
-
-\fun{GEN}{RgX_deflate}{GEN P, long d} assuming $P$ is a polynomial of the
-form $Q(X^d)$, return $Q$. Shallow function, not suitable for
-\kbd{gerepileupto}.
-
-\fun{long}{RgX_deflate_max}{GEN P, long *d} sets \kbd{d} to the largest exponent
-such that $P$ is of the form $P(x^d)$ (use \kbd{gequal0} to check
-whether coefficients are 0), $0$ if $P$ is the zero polynomial. Returns
-\kbd{RgX\_deflate(P,d)}.
+\fun{GEN}{RgX_deriv}{GEN x} returns the derivative of \kbd{x} with respect to
+its main variable.
 
-\fun{GEN}{RgX_inflate}{GEN P, long d} return $P(X^d)$. Shallow function, not
-suitable for \kbd{gerepileupto}.
+\fun{GEN}{RgX_integ}{GEN x} returns the primitive of \kbd{x} vanishing at
+$0$, with respect to its main variable.
 
 \fun{GEN}{RgX_rescale}{GEN P, GEN h} returns $h^{\deg(P)} P(x/h)$.
 \kbd{P} is an \kbd{RgX} and \kbd{h} is non-zero. (Leaves small objects on the
@@ -7351,28 +7974,66 @@ on the stack. Suitable but inefficient for \kbd{gerepileupto}.)
 \fun{GEN}{RgXV_unscale}{GEN v, GEN h} apply \kbd{RgX\_unscale} to a vector
 of \kbd{RgX}.
 
-\fun{int}{RgX_is_rational}{GEN P} return 1 is the \kbd{RgX}~$P$ has only
-rational coefficients (\typ{INT} and \typ{FRAC}), and 0 otherwise.
+\fun{GEN}{RgX_translate}{GEN P, GEN c} assume $c$ is a scalar or
+a polynomials whose main variable has lower priority than the main variable
+$X$ of $P$. Returns $P(X + c)$ (optimized for $c = \pm 1$).
 
-\fun{int}{RgX_is_QX}{GEN P} return 1 is the \kbd{RgX}~$P$ has only
-\typ{INT} and \typ{FRAC} coefficients, and 0 otherwise.
+\subsubsec{Function related to modular forms}
 
-\fun{int}{RgX_is_ZX}{GEN P} return 1 is the \kbd{RgX}~$P$ has only
-\typ{INT} coefficients, and 0 otherwise.
+\fun{GEN}{RgX_act_Gl2Q}{GEN g, long k} let $R$ be a commutative ring
+and $g = [a,b;c,d]$ be in $\text{GL}_2(\Q)$, $g$ acts (on the left)
+on homogeneous polynomials of degree $k-2$ in $V := R[X,Y]_{k-2}$ via
+$$ g\cdot P := P(dX-cY, -bX+aY) = (\det g)^{k-2} P((X,Y)\cdot g^{-1}).$$
+This function returns the matrix in $M_{k-1}(R)$ of $P\mapsto g\cdot P$ in
+the basis $(X^{k-2},\dots,Y^{k-2})$ of $V$.
 
-\fun{int}{RgX_is_monomial}{GEN x} returns 1 (true) if \kbd{x} is a non-zero
-monomial in its main variable, 0~otherwise.
+\fun{GEN}{RgX_act_ZGl2Q}{GEN z, long k} let $G:=\text{GL}_2(\Q)$, acting
+on $R[X,Y]_{k-2}$ and $z\in \Z[G]$. Return the matrix giving
+$P\mapsto z\cdot P$ in the basis $(X^{k-2},\dots,Y^{k-2})$.
 
-\fun{long}{RgX_equal}{GEN x, GEN y} returns $1$ if the \typ{POL}s $x$ and $y$
-have the same \kbd{degpol} and their coefficients are equal (as per
-\tet{gequal}). Variable numbers are not checked. Note that this is more
-stringent than \kbd{gequal(x,y)}, which only checks whether $x - y$ satisfies
-\kbd{gequal0}; in particular, they may have different apparent degrees provided
-the extra leading terms are $0$.
+\subsec{\kbd{RgXn}}
 
-\fun{long}{RgX_equal_var}{GEN x, GEN y} returns $1$ if $x$ and $y$
-have the same variable number and \kbd{RgX\_equal(x,y)} is $1$.
-\smallskip
+\fun{GEN}{RgXn_red_shallow}{GEN x, long n} return $\kbd{x \% } t^n$,
+where $n\geq 0$. Shallow function.
+
+\fun{GEN}{RgXn_mul}{GEN a, GEN b, long n} returns $a b$ modulo $X^n$,
+where $a,b$ are two \typ{POL} in the same variable $X$ and $n \geq 0$. Uses
+Karatsuba algorithm (Mulders, Hanrot-Zimmermann variant).
+
+\fun{GEN}{RgXn_sqr}{GEN a, long n} returns $a^2$ modulo $X^n$,
+where $a$ is a \typ{POL} in the variable $X$ and $n \geq 0$. Uses
+Karatsuba algorithm (Mulders, Hanrot-Zimmermann variant).
+
+\fun{GEN}{RgXn_inv}{GEN a, long n} returns $a^-1$ modulo $X^n$,
+where $a$ is a \typ{POL} in the variable $X$ and $n \geq 0$. Uses
+Newton-Raphson algorithm.
+
+\fun{GEN}{RgXn_powers}{GEN x, long m, long n} returns $[\kbd{x}^0,
+\dots, \kbd{x}^\kbd{m}]$ modulo $X^n$ as a \typ{VEC} of \kbd{RgXn}s.
+
+\fun{GEN}{RgXn_exp}{GEN a, long n} returns $exp(a)$ modulo $X^n$, assuming
+$a = 0 \mod{X}$. Uses Hanrot-Zimmermann algorithm.
+
+\fun{GEN}{RgXn_eval}{GEN Q, GEN x, long n} special case of
+\tet{RgX_RgXQ_eval}, when the modulus is a monomial:
+returns $\kbd{Q}(\kbd{x})$ modulo $t^n$, where $x \in R[t]$.
+
+\fun{GEN}{RgX_RgXn_eval}{GEN f, GEN x, long n} returns $\kbd{f}(\kbd{x})$ modulo
+$X^n$.
+
+\fun{GEN}{RgX_RgXnV_eval}{GEN f, GEN V, long n} as \kbd{RgX\_RgXn\_eval(f, x, n)},
+assuming $V$ was output by \kbd{RgXn\_powers(x, m, n)} for some $m\geq 1$.
+
+\fun{GEN}{RgXn_reverse}{GEN f, GEN n} assuming that $f = a\*x \mod{x^2}$
+with $a$ invertible, returns a \typ{POL} $g$ of degree $< n$ such that $(g
+\circ f)(x) = x$ modulo $x^n$.
+
+\subsec{\kbd{RgXnV}}
+
+\fun{GEN}{RgXnV_red_shallow}{GEN x, long n} apply \kbd{RgXn\_red\_shallow}
+to all the components of the vector $x$.
+
+\subsec{\kbd{RgXQ}}
 
 \fun{GEN}{RgXQ_mul}{GEN y, GEN x, GEN T} computes $xy$ mod $T$
 
@@ -7388,6 +8049,20 @@ $n$ being an \kbd{ulong}.
 \fun{GEN}{RgXQ_powers}{GEN x, long n, GEN T} returns $[\kbd{x}^0,
 \dots, \kbd{x}^\kbd{n}]$ as a \typ{VEC} of \kbd{RgXQ}s.
 
+\fun{GEN}{RgXQ_matrix_pow}{GEN y, long n, long m, GEN P} returns
+\kbd{RgXQ\_powers(y,m-1,P)}, as a matrix of dimension $n \geq \deg P$.
+
+\fun{GEN}{RgXQ_norm}{GEN x, GEN T} returns the norm of \kbd{Mod(x, T)}.
+
+\fun{GEN}{RgXQ_charpoly}{GEN x, GEN T, long v} returns the characteristic
+polynomial of \kbd{Mod(x, T)}, in variable $v$.
+
+\fun{GEN}{RgX_RgXQ_eval}{GEN f, GEN x, GEN T} returns $\kbd{f}(\kbd{x})$ modulo
+$T$.
+
+\fun{GEN}{RgX_RgXQV_eval}{GEN f, GEN V, GEN T} as \kbd{RgX\_RgXQ\_eval(f, x, T)},
+assuming $V$ was output by \kbd{RgXQ\_powers(x, n, T)} for some $n\geq 1$.
+
 \fun{int}{RgXQ_ratlift}{GEN x, GEN T, long amax, long bmax, GEN *P, GEN *Q}
 Assuming that $\kbd{amax}+\kbd{bmax}<\deg T$, attempts to recognize $x$ as a
 rational function $a/b$, i.e. to find \typ{POL}s $P$ and $Q$ such that
@@ -7409,28 +8084,7 @@ needs not compute the characteristic polynomial of $f$ mod $T$ (often already
 known in applications). In the trivial case where $n \leq 1$, returns a
 scalar, not a constant \typ{POL}.
 
-\fun{GEN}{RgXQ_matrix_pow}{GEN y, long n, long m, GEN P} returns
-\kbd{RgXQ\_powers(y,m-1,P)}, as a matrix of dimension $n \geq \deg P$.
-
-\fun{GEN}{RgXQ_norm}{GEN x, GEN T} returns the norm of \kbd{Mod(x, T)}.
-
-\fun{GEN}{RgXQ_charpoly}{GEN x, GEN T, long v} returns the characteristic
-polynomial of \kbd{Mod(x, T)}, in variable $v$.
-
-\fun{GEN}{RgX_RgXQ_eval}{GEN f, GEN x, GEN T} returns $\kbd{f}(\kbd{x})$ modulo
-$T$.
-
-\fun{GEN}{RgX_RgXQV_eval}{GEN f, GEN V, GEN T} as
-\kbd{RgX\_RgXQ\_eval(f, x, T)},
-assuming $V$ was output by \kbd{RgXQ\_powers(x, n, T)} for some $n\geq 1$.
-
-\fun{GEN}{RgX_translate}{GEN P, GEN c} assume $c$ is a scalar or
-a polynomials whose main variable has lower priority than the main variable
-$X$ of $P$. Returns $P(X + c)$ (optimized for $c = \pm 1$).
-
-\fun{GEN}{RgXQX_translate}{GEN P, GEN c, GEN T} assume the main variable
-$X$ of $P$ has higher priority than the main variable $Y$ of $T$ and $c$.
-Return a lift of $P(X+\text{Mod}(c(Y), T(Y)))$.
+\subsec{\kbd{RgXQV, RgXQC}}
 
 \fun{GEN}{RgXQC_red}{GEN z, GEN T} \kbd{z} a vector whose
 coefficients are \kbd{RgX}s (arbitrary \kbd{GEN}s in fact), reduce them to
@@ -7440,37 +8094,17 @@ coefficients are \kbd{RgX}s (arbitrary \kbd{GEN}s in fact), reduce them to
 coefficients are \kbd{RgX}s (arbitrary \kbd{GEN}s in fact), reduce them to
 \kbd{RgXQ}s (applying \kbd{grem} coefficientwise) in a \typ{VEC}.
 
+\fun{GEN}{RgXQV_RgXQ_mul}{GEN z, GEN x, GEN T} \kbd{z} multiplies the
+ \kbd{RgXQV} \kbd{z} by the scalar (\kbd{RgXQ}) \kbd{x}.
+
+\subsec{\kbd{RgXQX}}
+
 \fun{GEN}{RgXQX_red}{GEN z, GEN T} \kbd{z} a \typ{POL} whose
 coefficients are \kbd{RgX}s (arbitrary \kbd{GEN}s in fact), reduce them to
 \kbd{RgXQ}s (applying \kbd{grem} coefficientwise).
 
 \fun{GEN}{RgXQX_mul}{GEN x, GEN y, GEN T}
 
-\fun{GEN}{Kronecker_to_mod}{GEN z, GEN T} $z\in R[X]$ represents an element
-$P(X,Y)$ in $R[X,Y]$ mod $T(Y)$ in Kronecker form, i.e. $z = P(X,X^{2*n-1})$
-
-Let $R$ be some commutative ring, $n = \deg T$ and let $P(X,Y)\in R[X,Y]$ lift
-a polynomial in $K[Y]$, where $K := R[X]/(T)$ and $\deg_X P < 2n-1$ --- such as
-would result from multiplying minimal degree lifts of two polynomials in
-$K[Y]$. Let $z = P(t,t^{2*n-1})$ be a Kronecker form of $P$, this function
-returns the image of $P(X,t)$ in $K[t]$, with \typ{POLMOD} coefficients.
-Not stack-clean. Note that $t$ need not be the same variable as $Y$!
-
-\fun{GEN}{RgX_Rg_mul}{GEN y, GEN x} multiplies the \kbd{RgX} \kbd{y}
-by the scalar \kbd{x}.
-
-\fun{GEN}{RgX_muls}{GEN y, long s} multiplies the \kbd{RgX} \kbd{y}
-by the \kbd{long}~\kbd{s}.
-
-\fun{GEN}{RgX_Rg_div}{GEN y, GEN x} divides the \kbd{RgX} \kbd{y}
-by the scalar \kbd{x}.
-
-\fun{GEN}{RgX_divs}{GEN y, long s} divides the \kbd{RgX} \kbd{y}
-by the \kbd{long}~\kbd{s}.
-
-\fun{GEN}{RgX_Rg_divexact}{GEN x, GEN y} exact division of the \kbd{RgX}
-\kbd{y} by the scalar \kbd{x}.
-
 \fun{GEN}{RgXQX_RgXQ_mul}{GEN x, GEN y, GEN T} multiplies the \kbd{RgXQX}
 \kbd{y} by the scalar (\kbd{RgXQ}) \kbd{x}.
 
@@ -7482,6 +8116,20 @@ by the \kbd{long}~\kbd{s}.
 
 \fun{GEN}{RgXQX_rem}{GEN x, GEN y, GEN T, GEN *r}
 
+\fun{GEN}{RgXQX_translate}{GEN P, GEN c, GEN T} assume the main variable
+$X$ of $P$ has higher priority than the main variable $Y$ of $T$ and $c$.
+Return a lift of $P(X+\text{Mod}(c(Y), T(Y)))$.
+
+\fun{GEN}{Kronecker_to_mod}{GEN z, GEN T} $z\in R[X]$ represents an element
+$P(X,Y)$ in $R[X,Y]$ mod $T(Y)$ in Kronecker form, i.e. $z = P(X,X^{2*n-1})$
+
+Let $R$ be some commutative ring, $n = \deg T$ and let $P(X,Y)\in R[X,Y]$ lift
+a polynomial in $K[Y]$, where $K := R[X]/(T)$ and $\deg_X P < 2n-1$ --- such as
+would result from multiplying minimal degree lifts of two polynomials in
+$K[Y]$. Let $z = P(t,t^{2*n-1})$ be a Kronecker form of $P$, this function
+returns the image of $P(X,t)$ in $K[t]$, with \typ{POLMOD} coefficients.
+Not stack-clean. Note that $t$ need not be the same variable as $Y$!
+
 \newpage
 \chapter{Operations on general PARI objects}
 
@@ -7670,12 +8318,12 @@ copy).
 to a (normalized) polynomial in variable~\kbd{v} (as \kbd{gtopoly},
 without copy).
 
-\fun{GEN}{RgX_to_RgV}{GEN x, long N} converts the \typ{POL}~\kbd{x} to a
+\fun{GEN}{RgX_to_RgC}{GEN x, long N} converts the \typ{POL}~\kbd{x} to a
 \typ{COL}~\kbd{v} with \kbd{N} components. Coefficients of \kbd{x} are listed
 by increasing degree, so that \kbd{y[i]} is the coefficient of the term of
 degree $i-1$ in \kbd{x}.
 
-\fun{GEN}{Rg_to_RgV}{GEN x, long N} as \tet{RgX_to_RgV}, except that other
+\fun{GEN}{Rg_to_RgC}{GEN x, long N} as \tet{RgX_to_RgV}, except that other
 types than \typ{POL} are allowed for \kbd{x}, which is then considered as a
 constant polynomial.
 
@@ -7700,6 +8348,9 @@ priorities: the above is an invalid object if $\kbd{varncmp(v, w)} \geq 0$.
 \fun{GEN}{RgXX_to_RgM}{GEN x, long N} converts the \typ{POL}~\kbd{x} with
 \kbd{RgX} (or constant) coefficients to a matrix with \kbd{N} rows.
 
+\fun{long}{RgXY_degreex}{GEN P} return the degree of $P$ with respect to
+the secondary variable.
+
 \fun{GEN}{RgXY_swap}{GEN P, long n, long w} converts the bivariate polynomial
 $\kbd{P}(u,v)$ (a \typ{POL} with \typ{POL} or scalar coefficients) to
 $P(\kbd{pol\_x[w]},u)$, assuming \kbd{n} is an upper bound for
@@ -7771,7 +8422,7 @@ $O(\kbd{p}^\kbd{n})$.
 \fun{GEN}{scalarser}{GEN x, long v, long prec} creates a constant \typ{SER}
 in variable \kbd{v} and precision \kbd{prec}, whose constant coefficient is
 (a copy of) \kbd{x}, in other words $\kbd{x} + O(\kbd{v}^\kbd{prec})$.
-Assumes that \kbd{x} is non-zero.
+Assumes that $\kbd{prec}\geq 0$.
 
 \fun{GEN}{pol_0}{long v} Returns the constant polynomial $0$ in variable $v$.
 
@@ -7780,7 +8431,7 @@ Assumes that \kbd{x} is non-zero.
 \fun{GEN}{pol_x}{long v} Returns the monomial of degree $1$ in variable $v$.
 
 \fun{GEN}{pol_x_powers}{long N, long v} returns the powers of
-\kbd{pol\_x(v)}, of degree $0$ to $N$, in a vector with $N+1$ components.
+\kbd{pol\_x(v)}, of degree $0$ to $N-1$, in a vector with $N$ components.
 
 \fun{GEN}{scalarpol}{GEN x, long v} creates a constant \typ{POL} in variable
 \kbd{v}, whose constant coefficient is (a copy of) \kbd{x}.
@@ -7908,6 +8559,11 @@ containing \kbd{[x, y]}.
 
 \fun{GEN}{mkvecsmalln}{long n, ...} returns the \typ{VECSMALL} whose $n$
 coefficients (\kbd{long}) follow.
+\emph{Warning:} since this is a variadic function, C type promotion is not
+performed on the arguments by the compiler, thus you have to make sure that all
+the arguments are of type \kbd{long}, in particular integer constants need to
+be written with the \kbd{L} suffix: \kbd{mkvecsmalln(2, 1L, 2L)} is correct,
+but \kbd{mkvecsmalln(2, 1, 2)} is not.
 
 \subsec{Unclean constructors}\label{se:unclean}
 
@@ -7952,6 +8608,9 @@ equal to \kbd{[x,y,z,t]}.
 \fun{GEN}{mkcol5}{GEN a1, GEN a2, GEN a3, GEN a4, GEN a5} creates the
 5-dimensional \typ{COL} equal to $[a_1,a_2,a_3,a_4,a_5]$.
 
+\fun{GEN}{mkcol6}{GEN x, GEN y, GEN z, GEN t, GEN u, GEN v}
+creates the $6$-dimensional column vector \kbd{[x,y,z,t,u,v]~}.
+
 \fun{GEN}{mkintmod}{GEN x, GEN y} creates the \typ{INTMOD} \kbd{Mod(x, y)}.
 The inputs must be \typ{INT}s satisfying $0 \leq x < y$.
 
@@ -8045,6 +8704,9 @@ returns the $4$-dimensional \typ{COL} \kbd{[x,y,z,t]~}.
 \fun{GEN}{retmkcol5}{GEN x, GEN y, GEN z, GEN t, GEN u}
 returns the $5$-dimensional column vector \kbd{[x,y,z,t,u]~}.
 
+\fun{GEN}{retmkcol6}{GEN x, GEN y, GEN z, GEN t, GEN u, GEN v}
+returns the $6$-dimensional column vector \kbd{[x,y,z,t,u,v]~}.
+
 \fun{GEN}{retconst_col}{long n, GEN x}
 returns the $n$-dimensional \typ{COL} whose entries are constant and all
 equal to $x$.
@@ -8088,10 +8750,8 @@ returns the \typ{POLMOD} \kbd{Mod(x, y)}.
 \smallskip
 
 \fun{GEN}{mkintn}{long n, ...} returns the non-negative \typ{INT} whose
-development in base $2^{32}$ is given by the following $n$ words
-(\kbd{unsigned long}). It is assumed that all such arguments are less than
-$2^{32}$ (the actual \kbd{sizeof(long)} is irrelevant, the behavior is also
-as above on $64$-bit machines).
+development in base $2^{32}$ is given by the following $n$ 32bit-words
+(\kbd{unsigned int}).
 \bprog
   mkintn(3, a2, a1, a0);
 @eprog
@@ -8444,9 +9104,7 @@ comparison function, return a sorted concatenation, with duplicates removed.
 \fun{GEN}{merge_factor}{GEN fx, GEN fy, void *data, int (*cmp)(void *,GEN,GEN)}
 let \kbd{fx} and \kbd{fy} be factorization matrices for $X$ and $Y$
 sorted with respect to the comparison function \kbd{cmp} (see
-\tet{sort_factor}), returns the factorization of $X * Y$. Zero exponents in
-the latter factorization are preserved, e.g. when merging the factorization
-of $2$ and $1/2$, the result is $2^0$.
+\tet{sort_factor}), returns the factorization of $X * Y$.
 
 \fun{long}{gen_search}{GEN v, GEN y, long flag, void *data, int
 (*cmp)(void*,GEN,GEN)}.\hfil\break
@@ -8730,6 +9388,7 @@ binary powering. To treat the special case $n = 0$, we consider
 \kbd{gpowgs} as a series of \kbd{gmul}, so we follow the rule of returning
 result which is as exact as possible given the input. More precisely,
 we return
+
 \item \kbd{gen\_1} if $x$ has type \typ{INT}, \typ{REAL},  \typ{FRAC}, or
 \typ{PADIC}
 
@@ -8747,7 +9406,9 @@ $N$ (the gcd of the moduli that appear).
 
 \item the identity permutation for \typ{VECSMALL}.
 
-\item etc. Of course, the only practical use of this routine for $n = 0$ is
+\item etc.
+
+Of course, the only practical use of this routine for $n = 0$ is
 to obtain the multiplicative neutral element in the base ring (or to treat
 marginal cases that should be special cased anyway if there is the slightest
 doubt about what the result should be).
@@ -8756,6 +9417,8 @@ doubt about what the result should be).
 \typ{INT}, using left-shift binary powering. The case where $y = 0$
 (as all cases where $y$ is small) is handled by \kbd{gpowgs(x, 0)}.
 
+\fun{GEN}{gpowers}{GEN x, long n} returns the vector $[1,x,\dots,x^n]$.
+
 In addition we also have the obsolete forms:
 
 \fun{void}{gaddz}{GEN x, GEN y, GEN z}
@@ -9045,6 +9708,15 @@ the complex polynomial $x$ (with coefficients \typ{INT}, \typ{FRAC},
 as \typ{REAL} or \typ{COMPLEX} of \typ{REAL}s of precision \kbd{prec}
 (guaranteeing a non-$0$ imaginary part). See \tet{QX_complex_roots}.
 
+\fun{double}{fujiwara_bound}{GEN x} return a quick upper bound for the
+logarithm in base $2$ of the modulus of the largest complex roots of
+the polynomial $x$ (complex coefficients).
+
+\fun{double}{fujiwara_bound_real}{GEN x, long sign} return a quick upper
+bound for the logarithm in base $2$ of the absolute value of the largest
+real root of sign \var{sign} ($1$ or $-1$), for the polynomial $x$ (real
+coefficients).
+
 \fun{GEN}{polmod_to_embed}{GEN x, long prec} return the vector of complex
 embeddings of the \typ{POLMOD} $x$ (with complex coefficients). Shallow
 function, simple complex variant of \tet{conjvec}.
@@ -9066,6 +9738,10 @@ the coefficient of the term of degree \kbd{n} in the main variable.
 the series is either $0$ or equal to $t^v(1+O(t))$. Shallow function if the
 ``leading term'' is $1$.
 
+\fun{int}{ser_isexactzero}{GEN x} return $1$ if $x$ is a zero series, all
+of whose known coefficients are exact zeroes; this implies that
+$\kbd{sign}(x) = 0$ and $\kbd{lg}(x) \leq 3$.
+
 \section{Functions to handle \typ{FFELT}}
 These functions define the public interface of the \typ{FFELT} type to use in
 generic functions.  However, in specific functions, it is better to use the
@@ -9079,7 +9755,7 @@ its prime field; the cardinality of the dimension field is thus $p^f$.
 
 \fun{GEN}{FF_p_i}{GEN a} shallow version of \kbd{FF\_p}.
 
-\fun{GEN}{FF_q}{GEN a} returns the cardinal of the definition field of the
+\fun{GEN}{FF_q}{GEN a} returns the cardinality of the definition field of the
 \typ{FFELT} element \kbd{a}.
 
 \fun{GEN}{FF_mod}{GEN a} returns the polynomial (with reduced \typ{INT}
@@ -9110,6 +9786,11 @@ characteristic is small enough.
 finite field $\Z/p\Z$. Useful for generic code that wants to handle
 (inefficiently) $\Z/p\Z$ as if it were not a prime field.
 
+\fun{GEN}{Tp_to_FF}{GEN T, GEN p} returns a \typ{FFELT} equal to $1$ in the
+finite field $\F_p/(T)$, where $T$ is a \kbd{ZX}, assumed to be irreducible
+modulo $p$, or \kbd{NULL} in which case the routine acts as \tet{p_to_FF(p,0)}.
+No checks.
+
 \fun{GEN}{FF_1}{GEN a} returns the unity in the definition field of the
 \typ{FFELT} element \kbd{a}.
 
@@ -9287,6 +9968,8 @@ is inconsistent here, since we sometimes use the prefix \kbd{mp} even though
 
 \fun{GEN}{sqrtr}{GEN x} returns the square root of $x$.
 
+\fun{GEN}{cbrtr}{GEN x} returns the real cube root of $x$.
+
 \fun{GEN}{sqrtnr}{GEN x, long n} returns the $n$-th root of $x$, assuming
 $n\geq 1$ and $x > 0$. Not stack clean.
 
@@ -9326,6 +10009,8 @@ $x \exp(x) = y$, for $y > 0$ a \typ{REAL}.
 
 \fun{GEN}{sqrtr_abs}{GEN x} returns $\sqrt{|x|}$ assuming $x\neq 0$.
 
+\fun{GEN}{cbrtr_abs}{GEN x} returns $|x|^{1/3}$ assuming $x\neq 0$.
+
 \fun{GEN}{exp1r_abs}{GEN x} returns $\exp(|x|) - 1$, assuming $x \neq 0$.
 
 \fun{GEN}{logr_abs}{GEN x} returns $\log(|x|)$, assuming $x \neq 0$.
@@ -10276,6 +10961,13 @@ value of keys and test keys for equality, respectively. If \kbd{use\_stack}
 is non zero, the resulting table will use the PARI stack; otherwise, we use
 \kbd{malloc}.
 
+\fun{hashtable*}{hash_create_ulong}{ulong size, long stack} special case
+when the keys are \kbd{ulongs} with ordinary equality test.
+
+\fun{hashtable*}{hash_create_str}{ulong size, long stack} special case
+when the keys are character strings with string equality test (and
+\tet{hash_str} hash function).
+
 \fun{void}{hash_insert}{hashtable *h, void *k, void *v} inserts $(k,v)$
 in hashtable $h$. No copy is made: $k$ and $v$ themselves are stored. The
 implementation does not prevent one to insert two entries with equal
@@ -10284,11 +10976,34 @@ keys $k$, but which of the two is affected by later commands is undefined.
 \fun{hashentry*}{hash_search}{hashtable *h, void *k} look for an entry
 with key $k$ in $h$. Return it if it one exists, and \kbd{NULL} if not.
 
+\fun{hashentry*}{hash_search2}{hashtable *h, void *k, ulong hash} look for an
+entry with key $k$ in $h$, assuming \kbd{h->hash(k)} is \kbd{hash}. Return
+it if it one exists, and \kbd{NULL} if not.
+
+\fun{hashentry *}{hash_select}{hashtable *h, void *k, void *E, int(*select)(void
+*,hashentry *)} variant of \tet{hash_search}, useful when entries
+with identical keys are inserted: among the entries associated to
+key $k$, return one satisfying the selection criterion (such that
+\kbd{select(E,e)} is non-zero), or \kbd{NULL} if none exist.
+
 \fun{hashentry*}{hash_remove}{hashtable *h, void *k} deletes an entry $(k,v)$
 with key $k$ from $h$ and return it. (Return \kbd{NULL} if none was found.)
 Only the linking structures are freed, memory associated to $k$ and $v$
 is not reclaimed.
 
+\fun{hashentry*}{hash_remove_select}{hashtable *h, void *k, void *E, int(*select)(void *,hashentry *) }
+variant of \tet{hash_remove}, useful when entries with identical keys are
+inserted: among the entries associated to key $k$, return one satisfying the
+selection criterion (such that \kbd{select(E,e)} is non-zero) and delete it, or
+\kbd{NULL} if none exist. Only the linking structures are freed, memory
+associated to $k$ and $v$ is not reclaimed.
+
+\fun{GEN}{hash_keys}{hashtable *h} return in a \typ{VECSMALL} the keys
+stored in hashtable $h$.
+
+\fun{GEN}{hash_values}{hashtable *h} return in a \typ{VECSMALL}
+the values stored in hashtable $h$.
+
 \fun{void}{hash_destroy}{hashtable *h} deletes the hashtable, by removing all
 entries.
 
@@ -10480,12 +11195,18 @@ type as $A$ (\typ{VEC}, \typ{COL} or \typ{MAT}), and whose components
 are the $A[n],\dots,A[1]$. If $A$ is a \typ{MAT}, these are the
 \emph{columns} of $A$.
 
+\fun{void}{vecreverse_inplace}{GEN A} as \kbd{vecreverse}, but reverse
+$A$ in place.
+
 \fun{GEN}{vecpermute}{GEN A, GEN p} $p$ is a \typ{VECSMALL} representing
 a list $[p_1,\dots,p_n]$ of indices. Returns a \kbd{GEN} which has the same
 type as $A$ (\typ{VEC}, \typ{COL} or \typ{MAT}), and whose components
 are $A[p_1],\dots,A[p_n]$. If $A$ is a \typ{MAT}, these are the
 \emph{columns} of $A$.
 
+\fun{GEN}{vecsmallpermute}{GEN A, GEN p} as \kbd{vecpermute} when \kbd{A} is a
+\typ{VECSMALL}.
+
 \fun{GEN}{vecslicepermute}{GEN A, GEN p, long y1, long y2} short for
 \bprog
   vecslice(vecpermute(A,p), y1, y2)
@@ -10545,6 +11266,8 @@ components to $x$.
 pair-wise distinct, i.e. if $i\mapsto v[i]$ is a 1-to-1 mapping, else returns
 0.
 
+\fun{GEN}{vec_append}{GEN V, GEN s} append \kbd{s} to the vector \kbd{V}.
+
 \fun{GEN}{vec_shorten}{GEN v, long n} shortens the vector \kbd{v} to \kbd{n}
 components.
 
@@ -10816,6 +11539,9 @@ input.
 
 \fun{GEN}{gp_call}{void *E, GEN x} evaluates the closure \kbd{(GEN)E} on $x$.
 
+\fun{GEN}{gp_call2}{void *E, GEN x, GEN y} evaluates the closure \kbd{(GEN)E}
+on $(x,y)$.
+
 \fun{long}{gp_callbool}{void *E, GEN x} evaluates the closure \kbd{(GEN)E} on
 $x$, returns \kbd{1} if its result is non-zero, and \kbd{0} otherwise.
 
@@ -10825,8 +11551,9 @@ instruction request the iterator to terminate immediately.
 
 \section{Defaults}
 
-\fun{int}{pari_is_default}{const char *s} return $1$ if $s$ is the name
-of a default, $0$ otherwise.
+\fun{entree*}{pari_is_default}{const char *s} return the \kbd{entree}
+structure associated to $s$ if it is the name of a default, \kbd{NULL}
+otherwise.
 
 \fun{GEN}{setdefault}{const char *s, const char *v, long flag} is the
 low-level function underlying \kbd{default0}. If $s$ is \kbd{NULL}, call all
@@ -10852,8 +11579,11 @@ a \typ{STR} otherwise.
 
 \noindent Low-level functions called by \kbd{setdefault}:
 
+
 \fun{GEN}{sd_TeXstyle}{const char *v, long flag}
 
+\fun{GEN}{sd_breakloop}{const char *v, long flag}
+
 \fun{GEN}{sd_colors}{const char *v, long flag}
 
 \fun{GEN}{sd_compatible}{const char *v, long flag}
@@ -10866,14 +11596,28 @@ a \typ{STR} otherwise.
 
 \fun{GEN}{sd_debugmem}{const char *v, long flag}
 
+\fun{GEN}{sd_echo}{const char *v, long flag}
+
 \fun{GEN}{sd_factor_add_primes}{const char *v, long flag}
 
 \fun{GEN}{sd_factor_proven}{const char *v, long flag}
 
 \fun{GEN}{sd_format}{const char *v, long flag}
 
+\fun{GEN}{sd_graphcolormap}{const char *v, long flag}
+
+\fun{GEN}{sd_graphcolors}{const char *v, long flag}
+
+\fun{GEN}{sd_help}{const char *v, long flag}
+
+\fun{GEN}{sd_histfile}{const char *v, long flag}
+
 \fun{GEN}{sd_histsize}{const char *v, long flag}
 
+\fun{GEN}{sd_lines}{const char *v, long flag}
+
+\fun{GEN}{sd_linewrap}{const char *v, long flag}
+
 \fun{GEN}{sd_log}{const char *v, long flag}
 
 \fun{GEN}{sd_logfile}{const char *v, long flag}
@@ -10886,12 +11630,22 @@ a \typ{STR} otherwise.
 
 \fun{GEN}{sd_parisize}{const char *v, long flag}
 
+\fun{GEN}{sd_parisizemax}{const char *v, long flag}
+
 \fun{GEN}{sd_path}{const char *v, long flag}
 
 \fun{GEN}{sd_prettyprinter}{const char *v, long flag}
 
 \fun{GEN}{sd_primelimit}{const char *v, long flag}
 
+\fun{GEN}{sd_prompt}{const char *v, long flag}
+
+\fun{GEN}{sd_prompt_cont}{const char *v, long flag}
+
+\fun{GEN}{sd_psfile}{const char *v, long flag}
+
+\fun{GEN}{sd_readline}{const char *v, long flag}
+
 \fun{GEN}{sd_realprecision}{const char *v, long flag}
 
 \fun{GEN}{sd_recover}{const char *v, long flag}
@@ -10902,14 +11656,18 @@ a \typ{STR} otherwise.
 
 \fun{GEN}{sd_simplify}{const char *v, long flag}
 
-\fun{GEN}{sd_sopath}{char *v, int flag}
+\fun{GEN}{sd_sopath}{const char *v, int flag}
 
 \fun{GEN}{sd_strictargs}{const char *v, long flag}
 
 \fun{GEN}{sd_strictmatch}{const char *v, long flag}
 
+\fun{GEN}{sd_timer}{const char *v, long flag}
+
 \fun{GEN}{sd_threadsize}{const char *v, long flag}
 
+\fun{GEN}{sd_threadsizemax}{const char *v, long flag}
+
 \noindent Generic functions used to implement defaults: most of the above
 routines are implemented in terms of the following generic ones. In all
 routines below
@@ -11046,11 +11804,17 @@ if the \emph{tag}-component of $S$ is non empty \emph{and} has relative
 $p$-adic precision $\geq \kbd{prec}$, return it. Otherwise insert (a clone
 of) \kbd{build(S, prec)} as \emph{tag}-component in $S$, and return it.
 
-\fun{GEN}{obj_checkbuild_prec}{GEN S, long tag, GEN (*build)(GEN,long), long
+\fun{GEN}{obj_checkbuild_realprec}{GEN S, long tag, GEN (*build)(GEN,long), long
 prec} if the \emph{tag}-component of $S$ is non empty \emph{and} has
 \kbd{gprecision} $\geq \kbd{prec}$, return it. Otherwise insert (a clone of)
 \kbd{build(S, prec)} as \emph{tag}-component in $S$, and return it.
 
+\fun{GEN}{obj_checkbuild_prec}{GEN S, long tag, GEN (*build)(GEN,long), GEN
+(*pr)(GEN), long prec} if the \emph{tag}-component of $S$ is non empty
+\emph{and} has precision $\kbd{pr}(x)\geq \kbd{prec}$, return it. Otherwise
+insert (a clone of) \kbd{build(S, prec)} as \emph{tag}-component in $S$,
+and return it.
+
 \fun{void}{obj_free}{GEN S} destroys all clones stored in the $n$ tagged
 components, and replace them by the initial value $0$. The regular entries of
 $S$ are unaffected, and $S$ remains a valid object. This is used to
diff --git a/doc/usersch6.tex b/doc/usersch6.tex
index c2b9ce0..38baa1a 100644
--- a/doc/usersch6.tex
+++ b/doc/usersch6.tex
@@ -4,6 +4,7 @@
 %
 % Permission is granted to copy, distribute and/or modify this document
 % under the terms of the GNU General Public License
+\newpage
 \chapter{Technical Reference Guide for Algebraic Number Theory}
 
 \section{General Number Fields}
@@ -183,6 +184,9 @@ embeddings of $K$.
 \fun{GEN}{nf_get_roundG}{GEN nf} returns a rescaled version of $G$, rounded
 to nearest integers, specifically \tet{RM_round_maxrank}$(G)$.
 
+\fun{GEN}{nf_get_ramified_primes}{GEN nf} returns the vector of ramified
+primes.
+
 \fun{GEN}{nf_get_Tr}{GEN nf} returns the matrix of the Trace quadratic form
 on the basis $(w_1,\ldots,w_n)$: its $(i,j)$ entry is $\text{Tr} w_i w_j$.
 
@@ -298,13 +302,25 @@ $L/K$.
 $\Z_L$ as a $\Z_K$-module, as a pseudo-matrix $(A,I)$ in HNF.
 
 \fun{GEN}{rnf_get_disc}{GEN rnf} is the output $[\goth{d}, s]$
- of \kbd{rnfdisc}
+ of \kbd{rnfdisc}.
+
+\fun{GEN}{rnf_get_idealdisc}{GEN rnf} is the ideal discriminant $\goth{d}$
+from \kbd{rnfdisc}.
 
 \fun{GEN}{rnf_get_index}{GEN rnf} is the index ideal $\goth{f}$
 
 \fun{GEN}{rnf_get_polabs}{GEN rnf} returns an absolute polynomial defining
 $L/\Q$.
 
+\fun{GEN}{rnf_get_alpha}{GEN rnf} a root $\alpha$ of the polynomial
+defining the base field, modulo \kbd{polabs} (cf.~\kbd{rnfequation})
+
+\fun{GEN}{rnf_get_k}{GEN rnf}
+a small integer $k$ such that $\theta = \beta + k\alpha$ is a root of
+\kbd{polabs}, where $\beta$ is a root of \kbd{pol}
+and $\alpha$ a root of the polynomial defining the base field,
+as in \tet{rnf_get_alpha} (cf.~also \kbd{rnfequation}).
+
 \fun{GEN}{rnf_get_invzk}{GEN rnf} contains $A^{-1}$, where $(A,I)$
 is the chosen pseudo-basis for $\Z_L$ over $\Z_K$.
 
@@ -431,7 +447,7 @@ Returns \kbd{LONG\_MAX} is $x$ is $0$.
 (with coefficients in \kbd{nf}) on the algebraic number $a$ (also in $nf$).
 
 \fun{GEN}{FpX_FpC_nfpoleval}{GEN nf, GEN pol, GEN a, GEN p} evaluate the
-\typ{FpX} \kbd{pol} on the algebraic number $a$ (also in $nf$).
+\kbd{FpX} \kbd{pol} on the algebraic number $a$ (also in $nf$).
 
 The following three functions implement trivial functionality akin to
 Euclidean division for which we currently have no real use. Of course, even if
@@ -588,6 +604,9 @@ by $n$). Otherwise, understand it as an element and returns the $1$-line
 
 \fun{GEN}{famat_inv_shallow}{GEN f} shallow version of \tet{famat_inv}.
 
+\fun{GEN}{famat_Z_gcd}{GEN M, GEN n} restrict the \var{famat} $M$ to
+the prime power dividing $n$.
+
 \fun{GEN}{to_famat}{GEN x, GEN k} given an element $x$ and an exponent
 $k$, returns the \var{famat} $x^k$.
 
@@ -812,13 +831,34 @@ iff $p$ is inert, and a \kbd{ZM} otherwise. Shallow function.
 
 \fun{GEN}{pr_norm}{GEN pr} returns the norm $p^f$ of the maximal ideal.
 
+\fun{GEN}{idealprimedec}{GEN nf, GEN p} list of maximal ideals dividing the
+prime $p$.
+
+\fun{GEN}{idealprimedec_limit_f}{GEN nf, GEN p, long f} as \tet{idealprimedec},
+limiting the list to primes of residual degree $\leq f$ if $f$ is non-zero.
+
+\fun{GEN}{idealprimedec_limit_norm}{GEN nf, GEN p, GEN B} as
+\tet{idealprimedec}, limiting the list to primes of norm $\leq B$, which
+must be a positive \typ{INT}.
+
 \subsec{Reducing modulo maximal ideals}
 
 \fun{GEN}{nfmodprinit}{GEN nf, GEN pr} returns an abstract \kbd{modpr}
 structure, associated to reduction modulo the maximal ideal \kbd{pr}, in
 \kbd{idealprimedec} format. From this data we can quickly project any
-\kbd{pr}-integral number field element to the residue field. This function is
-almost useless in library mode, we rather use:
+\kbd{pr}-integral number field element to the residue field.
+
+\fun{GEN}{modpr_get_pr}{GEN x} return the \kbd{pr} component from a \kbd{modpr}
+structure.
+
+\fun{GEN}{modpr_get_p}{GEN x} return the $p$ component from a \kbd{modpr}
+structure (underlying rational prime).
+
+\fun{GEN}{modpr_get_T}{GEN x} return the \kbd{T} component from a \kbd{modpr}
+structure: either \kbd{NULL} (prime of degree $1$) or an irreducible
+\kbd{FpX} defining the residue field over $\F_p$.
+
+In library mode, it is often easier to use directly
 
 \fun{GEN}{nf_to_Fq_init}{GEN nf, GEN *ppr, GEN *pT, GEN *pp} concrete
 version of \kbd{nfmodprinit}: \kbd{nf} and \kbd{*ppr} are the inputs, the
@@ -921,9 +961,17 @@ equal to $0$ or $1$, return as a \typ{VECSMALL} the list of indices $i$
 such that $v[i] = 1$. If $v$ is already a \typ{VECSMALL}, return it
 (not suitable for \kbd{gerepile} in this case).
 
+\fun{GEN}{vecsmall01_to_indices}{GEN v} as
+\bprog
+  vec01_to_indices(zv_to_ZV(v));
+ at eprog
+
 \fun{GEN}{indices_to_vec01}{GEN p, long n} return the $0/1$ vector of length
 $n$ with ones exactly at the positions $p[1], p[2], \ldots$
 
+\fun{GEN}{nfembed}{GEN nf, GEN x, long k} returns a floating point
+approximation of the $k$-th embedding of $x$ (associated to the $k$-th
+complex root in \kbd{nf.roots}).
 
 \fun{GEN}{nfsign}{GEN nf,GEN x} $x$ being a number field element and \kbd{nf}
 any form of number field, return the $0-1$-vector giving the signs of the
@@ -1339,6 +1387,11 @@ then it contains generators.
 
 \subsec{Relative equations, Galois conjugates}
 
+\fun{GEN}{nfissquarefree}{GEN nf, GEN P} given $P$ a polynomial with
+coefficients in \var{nf}, return $1$ is $P$ is squarefree, and $0$
+otherwise. If is allowed (though less efficient) to replace \var{nf}
+by a monic \kbd{ZX} defining the field.
+
 \fun{GEN}{rnfequationall}{GEN A, GEN B, long *pk, GEN *pLPRS} $A$ is either an
 \var{nf} type (corresponding to a number field $K$) or an irreducible \kbd{ZX}
 defining a number field $K$. $B$ is an irreducible polynomial in $K[X]$.
@@ -1483,23 +1536,14 @@ not \kbd{nf\_GENMAT}. Don't use them:
 
 \fun{GEN}{smallpolred2}{GEN x}, use \tet{Polred}.
 
+\fun{GEN}{polred0}{GEN x, long flag, GEN p}
+
 \fun{GEN}{polredabs}{GEN x}
 
 \fun{GEN}{polredabs2}{GEN x}
 
 \fun{GEN}{polredabsall}{GEN x, long flun}
 
-\noindent \kbd{nfmaxord} wrappers implementing the old \kbd{nfbasis} interface:
-use the $[T,\var{listP}$ format.
-
-\fun{GEN}{polred0}{GEN x, long flag, GEN p}
-
-\fun{GEN}{nfbasis0}{GEN x,long flag,GEN p}
-
-\fun{GEN}{nfdisc0}{GEN x,long flag, GEN p}
-
-\fun{GEN}{factorpadic0}{GEN f,GEN p,long r,long flag}
-
 \noindent Superseded by \tet{bnrdisc}:
 
 \fun{GEN}{discrayabs}{GEN bnr,GEN subgroup}
@@ -1997,6 +2041,11 @@ maximal orders of number fields with respect to the $T_2$ quadratic form, to
 ensure that the first vector in the output basis corresponds to $1$ (which is
 a shortest vector).
 
+\item  \tet{LLL_COMPATIBLE}. This is a no-op on 64-bit kernels; on 32-bit
+kernels, restrict to 64-bit-compatible accuracies in the course of LLL
+algorithms. This is very likely to produce identical results on all
+kernels, but this is not guaranteed.
+
 The last three flags are mutually exclusive, either 0 or a single one must be
 set:
 
@@ -2097,4 +2146,12 @@ Finds a small $e$ such that the rank of $G_e$ is equal to the rank of $G$
 step to speed up LLL reductions, see \tet{nf_get_Gtwist}.
 Suitable for \kbd{gerepileupto}, but does not collect garbage.
 
+\section{Central simple algebras}
+
+\fun{void}{checkal}{GEN a} raise an exception if $a$ was not initialized
+by \tet{alinit}.
+
+\fun{long}{al_type}{GEN al} internal function called by \tet{altype}: assume
+\kbd{al} was created by \tet{alinit} (thereby saving a call to \kbd{checkal}).
+
 \newpage
diff --git a/doc/usersch7.tex b/doc/usersch7.tex
index 8c0da49..e922dea 100644
--- a/doc/usersch7.tex
+++ b/doc/usersch7.tex
@@ -57,6 +57,8 @@ is defined, one of
 
   \tet{t_ELL_Q} the field of rational numbers;
 
+  \tet{t_ELL_NF} a number field;
+
   \tet{t_ELL_Qp} the field of $p$-adic numbers, for some prime $p$;
 
   \tet{t_ELL_Fp} a prime finite field, base field elements are represented as
@@ -78,6 +80,8 @@ over $\Q$, raises \tet{pari_err_TYPE} otherwise.
 \fun{void}{checkell_Qp}{GEN e} checks whether $e$ is an \kbd{ell}, defined
 over some $\Q_p$, raises \tet{pari_err_TYPE} otherwise.
 
+\fun{void}{checkellisog}{GEN v} raise an error unless $v$ is an isogeny,
+from \tet{ellisogeny}.
 
 \subsec{Extracting info from an \kbd{ell} structure}
 
@@ -120,11 +124,43 @@ returned.
 \fun{void}{ellQ_get_Nfa}{GEN e, GEN *N, GEN *faN} sets $N$ to the conductor
 and \kbd{faN} to its factorization
 
+\fun{int}{ell_is_integral}{GEN e} return $1$ if $e$ is given by an integral
+model, and $0$ otherwise.
+
+\fun{long}{ellQ_get_CM}{GEN e} if $e$ has CM by a principal imaginary
+quadratic order, return its discriminant. Else return $0$.
+
+\fun{long}{ellap_CM_fast}{GEN e, ulong p, long CM} assuming that $p$
+does not divide the discriminant of $E$ (in particular, $E$ has good
+reduction at $p$), and that \kbd{CM} is as given by \tet{ellQ_get_CM},
+return the trace of Frobenius for $E/\F_p$. This is meant to quickly compute
+lots of $a_p$, esp.~when $e$ has CM by a principal quadratic order.
+
 \fun{long}{ellrootno_global}{GEN e} returns $[c, [c_{p_1}, \dots,c_{p_k}]]$,
 where the \typ{INT} $c\in \{-1,1\}$ is the global root number, and the
 $c_{p_i}$ are the local root numbers at all prime divisors of the conductor,
 ordered as in \kbd{faN} above.
 
+\fun{GEN}{ellheightoo}{GEN E, GEN P, long prec} given $P = [x,y]$ an affine
+point on $E$, return the (canonical) local height at infinity
+$\lambda_\infty(P) \in \R$.
+
+\fun{long}{ellorder_Q}{GEN E, GEN P} return the order of $P\in E(\Q)$, using
+the impossible value $0$ for a point of infinite order. Ultimately called
+by the generic \tet{ellorder} function.
+
+\fun{GEN}{point_to_a4a6}{GEN E, GEN P, GEN p, GEN *a4} given $E/\Q$,
+$p\neq 2,3$ not dividing the discriminant of $E$ and $P\in E(\Q)$ outside the
+kernel of reduction, return the image of $P$ on the short Weierstrass
+model $y^2 = x^3 + a_4x + a_6$ isomorphic to the reduction $E_p$ of $E$ at $p$.
+Also set \kbd{a4} to the $a_4$ coefficient in the above model. This function
+allows quick computations modulo varying primes $p$, avoiding the overhead of
+\kbd{ellinit}$(E,p)$, followed by a change of coordinates. It produces data
+suitable for \kbd{FpE} routines.
+
+\fun{GEN}{point_to_a4a6_Fl}{GEN E, GEN P, ulong p, ulong *pa4} as
+\tet{point_to_a4a6}, returning a \kbd{Fle}.
+
 \fun{GEN}{elldatagenerators}{GEN E} returns generators for $E(\Q)$
 extracted from Cremona's table.
 
@@ -140,6 +176,27 @@ converting unneeded dynamic data and avoids potential memory leaks
 (the changed curve would have had to be deleted using \tet{obj_free}). The
 original curve $e$ is updated as well with the same information.
 
+\fun{GEN}{ellanal_globalred_all}{GEN e, GEN *v, GEN *N, GEN *tam} as
+\tet{ellanal_globalred}; further set \kbd{*N} to the curve conductor
+and \kbd{*tam} to the product of the local Tamagawa numbers, including
+the factor at infinity (multiply by the number of connected components
+of $e(\R)$).
+
+\fun{GEN}{ellintegralmodel}{GEN e, GEN *pv} return an integral model
+for $e$ (in \kbd{ellinit} form, over $\Q$). Set $v = \kbd{NULL}$ (already
+integral, we returned $e$ itself), else to the variable change
+$[u,0,0,0]$ making $e$ integral. We have $u = 1/t$, $t > 1$.
+
+\misctitle{Deprecated routines}
+
+\fun{GEN}{elltors0}{GEN e, long flag)} this function is deprecated; use
+\tet{elltors}
+
+\subsubsec{Curves over a number field \var{nf}}
+
+\fun{GEN}{ellnf_get_nf}{GEN x} returns the field over which $E$ is defined
+(\var{nf} or \var{bnf} structure).
+
 \subsubsec{Curves over $\Q_p$}
 
 \fun{GEN}{ellQp_get_p}{GEN E} returns $p$
@@ -238,10 +295,42 @@ infinity.
 \fun{GEN}{ellinf}{} returns the point at infinity \kbd{[0]}.
 
 \subsec{Change of variables}
+
 \fun{GEN}{ellchangeinvert}{GEN w} given a change of variables $w =
 [u,r,s,t]$, returns the inverse change of variables $w'$, such that if $E' =
 \kbd{ellchangecurve(E, w)}$, then $E = \kbd{ellchangecurve}(E, w')$.
 
+\subsec{Generic helper functions}
+
+The naming scheme assumes an affine equation
+$F(x,y) = f(x) - (y^2 + h(x)y) = 0$
+in standard Weierstrass form: $f = x^3+a_2x^2+a_4x+a_6$, $h = a_1x + a_3$.
+
+\fun{GEN}{ellbasechar}{GEN E} returns the characteristic of the base ring over
+which $E$ is defined.
+
+\fun{GEN}{ec_bmodel}{GEN E} returns the polynomial $4x^3 + b_2x^2 + 2b_4x +
+b_6$.
+
+\fun{GEN}{ec_f_evalx}{GEN E, GEN x} returns $f(x)$.
+
+\fun{GEN}{ec_h_evalx}{GEN E, GEN x} returns $h(x)$.
+
+\fun{GEN}{ec_dFdx_evalQ}{GEN E, GEN Q} returns $3x^2 + 2a_2x + a_4 -a_1y$,
+where $Q = [x,y]$.
+
+\fun{GEN}{ec_dFdy_evalQ}{GEN E, GEN Q} returns $-(2y + a_1 x + a_3)$,
+where $Q = [x,y]$.
+
+\fun{GEN}{ec_dmFdy_evalQ}{GEN e, GEN Q} returns $2y + a_1 x + a_3$,
+where $Q = [x,y]$.
+
+\fun{GEN}{ec_2divpol_evalx}{GEN E, GEN x} returns
+$4x^3 + b_2x^2 + 2b_4x + b_6$.
+
+\fun{GEN}{ec_half_deriv_2divpol_evalx}{GEN E, GEN x} returns
+$6x^2 + b_2x + b_4$.
+
 \subsec{Functions to handle elliptic curves over finite fields}
 
 \subsubsec{Tolerant routines}
@@ -253,17 +342,10 @@ a non-prime finite field $\F_q$, ignore $p$ and return $q+1 - \#E(\F_q)$.
 When $p$ is implied ($E$ defined over $\Q_p$ or a finite field), $p$ can be
 omitted (set to \kbd{NULL}).
 
-\fun{GEN}{ellsea}{GEN E, GEN p, long s} available if the \kbd{seadata}
-package is installed. This function returns $\#E(\F_p)$, using the
-Schoof-Elkies-Atkin algorithm; it is called by \kbd{ellap}: same conditions
-as above for $E$, except that \tet{t_ELL_Fq} are not allowed. The extra flag
-\kbd{s}, if set to a non-zero value, causes the computation to return
-\kbd{gen\_0} (an impossible cardinality) if one of the small primes $\ell>s$
-divides the curve order. For cryptographic applications, where one is usually
-interested in curves of prime order, setting $s=1$ efficiently weeds out most
-uninteresting curves; if curves of order a power of $2$ times a prime are
-acceptable, set $s=2$. There is no guarantee that the resulting cardinality
-is prime, only that it has no small prime divisor larger than $s$.
+\misctitle{Deprecated routines}
+
+\fun{GEN}{ellsea}{GEN E, GEN p, long s} deprecated, use \kbd{Fp\_ellcard\_SEA}
+instead.
 
 \subsubsec{Curves defined a non-prime finite field}
 In this subsection, we assume that \tet{ell_get_type}$(E)$ is \tet{t_ELL_Fq}.
@@ -322,18 +404,25 @@ parameters $a_4$ and $a_6$ are given as \typ{INT}s when required.
 \fun{GEN}{Fp_ellj}{GEN a4, GEN a6, GEN p}
 returns the $j$-invariant of the curve $E$.
 
-\fun{GEN}{Fp_ellcard}{GEN a4, GEN a6, GEN p} returns the cardinal of the group
-$E(\F_p)$.
+\fun{int}{Fp_elljissupersingular}{GEN j, GEN p} returns $1$ if $j$ is the
+$j$-invariant of a supersingular curve over $\F_p$, $0$ otherwise.
+
+\fun{GEN}{Fp_ellcard}{GEN a4, GEN a6, GEN p} returns the cardinality of the
+group $E(\F_p)$.
 
-\fun{GEN}{Fp_ellcard_SEA}{GEN a4, GEN a6, GEN p, long s} same as
-\tet{ellsea} when only $[a_4,a_6]$ are given.
+\fun{GEN}{Fp_ellcard_SEA}{GEN a4, GEN a6, GEN p, long s}
+available if the \kbd{seadata} package is installed. This function returns
+$\#E(\F_p)$, using the Schoof-Elkies-Atkin algorithm.
 
-\fun{GEN}{Fq_ellcard_SEA}{GEN a4, GEN a6, GEN q, GEN T, GEN p, long s} same
-as \tet{ellsea} when only $[a_4,a_6]$ are given, over $\F_p[t]/(T)$.
-Assume $p\neq 2,3$.
+The extra flag \kbd{s}, if set to a non-zero value, causes the computation to
+return \kbd{gen\_0} (an impossible cardinality) if one of the small primes
+$\ell>s$ divides the curve order. For cryptographic applications, where one
+is usually interested in curves of prime order, setting $s=1$ efficiently
+weeds out most uninteresting curves; if curves of order a power of $2$ times
+a prime are acceptable, set $s=2$.
 
 \fun{GEN}{Fp_ffellcard}{GEN a4, GEN a6, GEN q, long n, GEN p} returns the
-cardinal of the group $E(\F_q)$ where $q=p^n$.
+cardinality of the group $E(\F_q)$ where $q=p^n$.
 
 \fun{GEN}{Fp_ellgroup}{GEN a4, GEN a6, GEN N, GEN p, GEN *pt_m} returns the
 group structure $D$ of the group $E(\F_p)$, which is assumed to be of order $N$
@@ -395,10 +484,40 @@ Weil pairing of the points of $m$-torsion $P$ and $Q$.
 Let $p$ be a prime \kbd{ulong}, and $E$ the elliptic curve given by the
 equation $E:y^2=x^3+a_4\*x+a_6$, where $a_4$ and $a_6$ are \kbd{ulong}.
 A \kbd{Fle} is either the point at infinity (\kbd{ellinf()}), or a \kbd{Flv}
-with two components.
+with two components $[x,y]$.
 
-\fun{long}{Fl_elltrace}{ulong a4, ulong a6, ulong p} returns the trace $t$ of the Frobenius of
-$E(\F_p)$. The cardinal of $E(\F_p)$ is thus $p+1-t$, which might not fit in a \kbd{ulong}.
+\fun{long}{Fl_elltrace}{ulong a4, ulong a6, ulong p} returns the trace $t$ of
+the Frobenius of $E(\F_p)$. The cardinality of $E(\F_p)$ is thus $p+1-t$,
+which might not fit in an \kbd{ulong}.
+
+\fun{long}{Fl_elltrace_CM}{long CM, ulong a4, ulong a6, ulong p} as
+\tet{Fl_elltrace}. If \kbd{CM} is $0$, use the standard algorithm; otherwise
+assume the curve has CM by a principal imaginary quadratic order of
+discriminant \kbd{CM} and use a faster algorithm. Useful when the curve is
+the reduction of $E/\Q$, which has CM by a principal order, and we need the
+trace of Frobenius for many distinct $p$, see \tet{ellQ_get_CM}.
+
+\fun{ulong}{Fl_elldisc}{ulong a4, ulong a6, ulong p}
+returns the discriminant of the curve $E$.
+
+\fun{ulong}{Fl_elldisc_pre}{ulong a4, ulong a6, ulong p, ulong pi}
+returns the discriminant of the curve $E$, assuming $pi$ is the pseudo inverse
+of $p$.
+
+\fun{ulong}{Fl_ellj}{ulong a4, ulong a6, ulong p}
+returns the $j$-invariant of the curve $E$.
+
+\fun{ulong}{Fl_ellj_pre}{ulong a4, ulong a6, ulong p, ulong pi}
+returns the $j$-invariant of the curve $E$, assuming $pi$ is the pseudo inverse
+of $p$.
+
+\fun{void}{Fl_ellj_to_a4a6}{ulong j, ulong p, ulong *pt_a4, ulong *pt_a6}
+Set \kbd{*pt\_a4} to $a_4$ and \kbd{*pt\_a6} to $a_6$ where $a_4$ and $a_6$
+define a fixed elliptic curve with $j$-invariant $j$.
+
+\fun{void}{Fl_elltwist}{ulong a4, ulong a6, ulong D, ulong p, ulong *pt_a4, ulong *pt_a6}
+Set \kbd{*pt\_a4} to $a'_4$ and \kbd{*pt\_a6} to $a'_6$ where $a'_4$ and $a'_6$
+define the twist of $E$ by the discriminant $D$.
 
 \fun{GEN}{Fle_add}{GEN P, GEN Q, ulong a4, ulong p}
 
@@ -412,8 +531,44 @@ $E(\F_p)$. The cardinal of $E(\F_p)$ is thus $p+1-t$, which might not fit in a \
 
 \fun{GEN}{Fle_order}{GEN P, GEN o, ulong a4, ulong p}
 
+\fun{GEN}{Fle_log}{GEN P, GEN G, GEN o, ulong a4, ulong p}
+
 \fun{GEN}{random_Fle}{ulong a4, ulong a6, ulong p}
 
+\fun{GEN}{random_Fle_pre}{ulong a4, ulong a6, ulong p, ulong pi}
+
+\fun{GEN}{Fle_changepoint}{GEN x, GEN ch, ulong p}, \kbd{ch} is assumed
+to give the change of coordinates $[u,r,s,t]$ as a \typ{VECSMALL}.
+
+\fun{GEN}{Fle_changepointinv}{GEN x, GEN ch, ulong p}, as \tet{Fle_changepoint}
+
+\subsec{\kbd{Flj}}
+
+Let $p$ be a prime \kbd{ulong}, and $E$ the elliptic curve given by the
+equation $E:y^2=x^3+a_4\*x+a_6$, where $a_4$ and $a_6$ are \kbd{ulong}.
+A \kbd{Flj} is a \kbd{Flv} with three components $[x,y,z]$, representing
+the affine point $[x/z^2,y/z^3]$ in Jacobian coordinates, the point at
+infinity being represented by $[1, 1, 0]$. The following must holds:
+$y^2=x^3+a_4\*x\*z^4+a_6\*z^6$. For all non-zero $u$, the points
+$[u^2\*x,u^3\*y,u\*z]$ and $[x,y,z]$ are representing the same affine point.
+
+Below, \kbd{pi} is assumed to be the precomputed inverse of $p$.
+
+\fun{GEN}{Fle_to_Flj}{GEN P} convert a \kbd{Fle} to an equivalent \kbd{Flj}.
+
+\fun{GEN}{Flj_to_Fle_pre}{GEN P} convert a \kbd{Flj} to the equivalent
+\kbd{Fle}.
+
+\fun{GEN}{Flj_add_pre}{GEN P, GEN Q, ulong a4, ulong p, ulong pi}
+
+\fun{GEN}{Flj_dbl_pre}{GEN P, ulong a4, ulong p, ulong pi}
+
+\fun{GEN}{Flj_neg}{GEN P, ulong p} return $-P$.
+
+\fun{GEN}{Flj_mulu_pre}{GEN P, ulong n, ulong a4, ulong p, ulong pi}
+
+\fun{GEN}{random_Flj_pre}{ulong a4, ulong a6, ulong p, ulong pi}
+
 \subsec{Elliptic curves over $\F_{2^n}$}
 Let $T$ be an irreducible \kbd{F2x} and $E$ the
 elliptic curve given by either the equation
@@ -489,6 +644,10 @@ $a_2$ and $a_6$ being \kbd{Flx} in $\F_3[X]/(T)$. In that case, the parameter
 \fun{GEN}{Flxq_ellj}{GEN a4, GEN a6, GEN T, ulong p}
 returns the $j$-invariant of the curve $E$.
 
+\fun{void}{Flxq_ellj_to_a4a6}{GEN j, GEN T, ulong p, GEN *pt_a4, GEN *pt_a6}
+Set \kbd{*pt\_a4} to $a_4$ and \kbd{*pt\_a6} to $a_6$ where $a_4$ and $a_6$
+define a fixed elliptic curve with $j$-invariant $j$.
+
 \fun{GEN}{Flxq_ellcard}{GEN a4, GEN a6, GEN T, ulong p}
 returns the order of $E(\F_p[X]/(T))$.
 
@@ -549,9 +708,18 @@ in $\F_p[X]/(T)$.  A \kbd{FpXQE} is a point of $E(\F_p[X]/(T))$.
 \fun{GEN}{FpXQ_ellj}{GEN a4, GEN a6, GEN T, GEN p}
 returns the $j$-invariant of the curve $E$.
 
+\fun{int}{FpXQ_elljissupersingular}{GEN j, GEN T, GEN p} returns $1$ if $j$ is
+the $j$-invariant of a supersingular curve over $\F_p[X]/(T)$, $0$ otherwise.
+
 \fun{GEN}{FpXQ_ellcard}{GEN a4, GEN a6, GEN T, GEN p}
 returns the order of $E(\F_p[X]/(T))$.
 
+\fun{GEN}{Fq_ellcard_SEA}{GEN a4, GEN a6, GEN q, GEN T, GEN p, long s}
+available if the \kbd{seadata} package is installed. This function returns
+$\#E(\F_p[X]/(T))$, using the Schoof-Elkies-Atkin algorithm.
+Assume $p\neq 2,3$, and $q$ is the cardinality of $\F_p[X]/(T)$.
+The parameter $s$ has the same meaning as in \kbd{Fp\_ellcard\_SEA}.
+
 \fun{GEN}{FpXQ_ellgroup}{GEN a4, GEN a6, GEN N, GEN T, GEN p, GEN *pt_m}
 Return the group structure $D$ of the group $E(\F_p[X]/(T))$,
 which is assumed to be of order $N$ and set $*pt_m=m$.
diff --git a/examples/Inputrc b/examples/Inputrc
index d0a986f..9b660db 100644
--- a/examples/Inputrc
+++ b/examples/Inputrc
@@ -5,6 +5,11 @@
 "\e\C-h": backward-kill-word
 "\C-xd": dump-functions
 
+# Comment out for GAP-style history search with up/down arrows
+# (default style is to use ^r/^s)
+# "\e[A": history-search-backward
+# "\e[B": history-search-forward
+
 $if Pari-GP
   set convert-meta on
   set output-meta off
diff --git a/examples/minigp.c b/examples/minigp.c
index a20fc33..a0aea61 100644
--- a/examples/minigp.c
+++ b/examples/minigp.c
@@ -4,40 +4,14 @@
 #include <readline/history.h>
 #include <setjmp.h>
 
-char * prompt = NULL;
-int chrono = 0;
 jmp_buf env;
 
-GEN sd_prompt(const char *v, long flag)
-{
-  if (v) { pari_free(prompt); prompt = strdup(v); }
-  if (flag == d_RETURN) return strtoGENstr(prompt);
-  else if (flag == d_ACKNOWLEDGE)
-    pari_printf("   prompt = \"%s\"\n", prompt);
-  return gnil;
-}
-GEN
-sd_timer(const char *v, long flag)
-{ return sd_toggle(v,flag,"timer", &chrono); }
+int gp_is_interactive(void) { return pari_infile == stdin; }
 void gp_err_recover(long numerr) { longjmp(env, numerr); }
 void gp_quit(long exitcode) { exit(exitcode); }
-void help(const char *s)
-{
-  entree *ep = is_entry(s);
-  if (ep && ep->help)
-    pari_printf("%s\n",ep->help);
-  else
-    pari_printf("Function %s not found\n",s);
-}
 
 entree functions_gp[]={
   {"quit",0,(void*)gp_quit,11,"vD0,L,","quit({status = 0}): quit, return to the system with exit status 'status'."},
-  {"help",0,(void*)help,11,"vr","help(fun): display help for function fun"},
-  {NULL,0,NULL,0,NULL,NULL}};
-
-entree default_gp[]={
-  {"prompt",0,(void*)sd_prompt,16,"","(default) string to be printed as prompt"},
-  {"timer",0,(void*)sd_timer,16,"","(default) toggle timer on/off"},
   {NULL,0,NULL,0,NULL,NULL}};
 
 #define col(a) term_get_color(NULL, a)
@@ -46,17 +20,18 @@ int main(int argc, char **argv)
 {
   pari_init(8000000,500000);
   pari_add_module(functions_gp);
-  pari_add_defaults_module(default_gp);
+  cb_pari_err_recover = gp_err_recover;
+  cb_pari_is_interactive = gp_is_interactive;
+  cb_pari_quit = gp_quit;
   sd_colors("lightbg",d_INITRC);
-  sd_prompt("? ",d_INITRC);
   pari_printf("Welcome to minigp!\n");
-  cb_pari_err_recover = gp_err_recover;
+  gp_load_gprc();
   (void)setjmp(env);
   while(1)
   {
     GEN z;
-    char *pr = pari_sprintf("%s%s%s",col(c_PROMPT),prompt,col(c_INPUT));
-    char *in = readline(pr);
+    const char *prompt = gp_format_prompt(GP_DATA->prompt);
+    char *in = readline(prompt);
     pari_timer T;
     long time;
 
@@ -64,17 +39,18 @@ int main(int argc, char **argv)
     if (!*in) continue;
 
     add_history(in);
+    gp_echo_and_log(prompt,in);
     timer_start(&T); z = gp_read_str(in); time = timer_delay(&T);
     pari_add_hist(z, time);
     if (z != gnil && in[strlen(in)-1] != ';')
     {
       pari_printf("%s%%%lu = %s",col(c_HIST),pari_nb_hist(),col(c_OUTPUT));
       output(z);
+      pari_puts(col(c_NONE));
     }
-    if (chrono && time)
-      pari_printf("%stime = %s%ld ms%s.\n",
-                  col(c_NONE),col(c_TIME),time,col(c_NONE));
-    free(in); avma = top;
+    if (GP_DATA->chrono && time)
+      pari_printf("time = %s\n", gp_format_time(time) );
+    free(in); avma = pari_mainstack->top;
   }
   return 0;
 }
diff --git a/misc/gprc.dft b/misc/gprc.dft
index b8d7b7c..8009754 100644
--- a/misc/gprc.dft
+++ b/misc/gprc.dft
@@ -6,10 +6,16 @@
 \\ Read ~/.gprc.gp (GP script) before gp prompts you for commands.
 \\ read "~/.gprc.gp"
 
-/* Most important options */
+/* Critical options */
 
-\\ Set PARI stack size to 10 Mbytes = 10^7 bytes
-\\ parisize = 10M
+\\ Limit PARI stack size to 400 Mbytes = 4*10^8 bytes
+\\ parisizemax = 400M
+
+\\ Set PARI typical stack size to 40 Mbytes = 4*10^7 bytes (will grow as
+\\ needed, up to parisizemax)
+\\ parisize = 40M
+
+/* Important options */
 
 \\ Save a history of all input commands in this file, and load it in each
 \\ new session's history
@@ -76,7 +82,7 @@
 \\  This file should be put in $HOME/.gprc or /etc/gprc and contains:
 \\  * references to gp scripts that are to be run BEFORE the first gp prompt.
 \\
-\\    Syntax: read "filename"  (quotes are mandatory. ~ syntax allowed)
+\\    Syntax: read "filename"  (quotes mandatory; ~ syntax for homedir allowed)
 \\
 \\  * options settings
 \\
@@ -85,8 +91,8 @@
 \\  Options which are not set here assume default values in gp. The command
 \\  default() under GP lists available options and their default values.
 \\
-\\  Options settings can be overriden by command line switches. For instance
-\\  gp --default parisize=10M
-\\  will set parisize to 10000000, regardless of what is in .gprc
-\\  They can also be changed under GP using default(): e.g.
-\\  default(parisize,"10M") 
+\\  Options settings are overriden by command line switches. For instance
+\\    gp --default parisizemax=1G
+\\  sets parisize to 1 GByte, regardless of what is in .gprc
+\\  They can also be changed under GP using default(), e.g.
+\\    default(parisize,"10M") 
diff --git a/misc/tex2mail.in b/misc/tex2mail.in
index 316f00e..ed14707 100755
--- a/misc/tex2mail.in
+++ b/misc/tex2mail.in
@@ -1,4 +1,4 @@
-#!@perl@
+#!@runtime_perl@
 # Original version by Ilya Zakharevich. Minor updates by the PARI group
 # Features:
 #      % at the end of a line followed by \n\n is recognized as end of 
diff --git a/src/basemath/F2x.c b/src/basemath/F2x.c
index 0e523f5..cba66e6 100644
--- a/src/basemath/F2x.c
+++ b/src/basemath/F2x.c
@@ -660,26 +660,26 @@ F2x_deriv(GEN z)
 GEN
 F2x_gcd(GEN a, GEN b)
 {
-  pari_sp av = avma, lim = stack_lim(av,2);
+  pari_sp av = avma;
   if (lg(b) > lg(a)) swap(a, b);
   while (lgpol(b))
   {
     GEN c = F2x_rem(a,b);
     a = b; b = c;
-    if (low_stack(lim,stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"F2x_gcd (d = %ld)",F2x_degree(c));
       gerepileall(av,2, &a,&b);
     }
   }
-  if (low_stack(lim,stack_lim(av,2))) a = gerepileuptoleaf(av, a);
+  if (gc_needed(av,2)) a = gerepileuptoleaf(av, a);
   return a;
 }
 
 GEN
 F2x_extgcd(GEN a, GEN b, GEN *ptu, GEN *ptv)
 {
-  pari_sp av=avma, lim = stack_lim(av,2);
+  pari_sp av=avma;
   GEN u,v,d,d1,v1;
   long vx = a[1];
   d = a; d1 = b;
@@ -690,7 +690,7 @@ F2x_extgcd(GEN a, GEN b, GEN *ptu, GEN *ptv)
     v = F2x_add(v,F2x_mul(q,v1));
     u=v; v=v1; v1=u;
     u=r; d=d1; d1=u;
-    if (low_stack(lim,stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"F2x_extgcd (d = %ld)",F2x_degree(d));
       gerepileall(av,5, &d,&d1,&u,&v,&v1);
@@ -698,14 +698,14 @@ F2x_extgcd(GEN a, GEN b, GEN *ptu, GEN *ptv)
   }
   if (ptu) *ptu = F2x_div(F2x_add(d, F2x_mul(b,v)), a);
   *ptv = v;
-  if (low_stack(lim,stack_lim(av,2))) gerepileall(av,ptu?3:2,&d,ptv,ptu);
+  if (gc_needed(av,2)) gerepileall(av,ptu?3:2,&d,ptv,ptu);
   return d;
 }
 
 static GEN
 F2x_halfgcd_i(GEN a, GEN b)
 {
-  pari_sp av=avma, lim = stack_lim(av,2);
+  pari_sp av=avma;
   GEN u,u1,v,v1;
   long vx = a[1];
   long n = (F2x_degree(a)+1)>>1;
@@ -717,7 +717,7 @@ F2x_halfgcd_i(GEN a, GEN b)
     a = b; b = r; swap(u,u1); swap(v,v1);
     u1 = F2x_add(u1, F2x_mul(u, q));
     v1 = F2x_add(v1, F2x_mul(v, q));
-    if (low_stack(lim,stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"F2x_halfgcd (d = %ld)",F2x_degree(b));
       gerepileall(av,6, &a,&b,&u1,&v1,&u,&v);
@@ -907,16 +907,6 @@ F2xq_conjvec(GEN x, GEN T)
   return z;
 }
 
-GEN
-random_F2x(long d, long vs)
-{
-  long i, l = nbits2lg(d+1);
-  GEN y = cgetg(l,t_VECSMALL); y[1] = vs;
-  for (i=2; i<l; i++) y[i] = pari_rand();
-  y[l-1] &= (1UL<<remsBIL(d))-1UL;
-  return F2x_renormalize(y,l);
-}
-
 static GEN
 _F2xq_pow(void *data, GEN x, GEN n)
 {
@@ -977,7 +967,6 @@ F2x_is_smooth(GEN g, long r)
     if (F2x_degree(f)==0) return 1;
     g = F2x_issquare(f) ? F2x_sqrt(f): f;
   }
-  return 0;
 }
 
 static GEN
@@ -1084,7 +1073,7 @@ F2xq_log_Coppersmith_d(GEN W, GEN g, long r, long n, GEN T, GEN mo)
 static GEN
 F2xq_log_find_rel(GEN b, long r, GEN T, GEN *g, ulong *e)
 {
-  pari_sp av = avma, lim = stack_lim(av,2);
+  pari_sp av = avma;
   while (1)
   {
     GEN M;
@@ -1103,7 +1092,7 @@ F2xq_log_find_rel(GEN b, long r, GEN T, GEN *g, ulong *e)
         return rel;
       }
     }
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"F2xq_log_find_rel");
       *g = gerepileuptoleaf(av, *g);
diff --git a/src/basemath/F2xqE.c b/src/basemath/F2xqE.c
index 1f8b1ca..3558e9d 100644
--- a/src/basemath/F2xqE.c
+++ b/src/basemath/F2xqE.c
@@ -311,7 +311,7 @@ F2xqE_tangent_update(GEN R, GEN Q, GEN a2, GEN T, GEN *pt_R)
     *pt_R = ellinf();
     return F2xqE_vert(R, Q, T);
   } else {
-    GEN slope, tmp1, tmp2;
+    GEN slope = NULL, tmp1, tmp2;
     *pt_R = F2xqE_dbl_slope(R, a2, T, &slope);
     tmp1 = F2x_add(gel(Q, 1), gel(R, 1));
     tmp2 = F2x_add(F2xq_mul(tmp1, slope, T), gel(R,2));
@@ -346,7 +346,7 @@ F2xqE_chord_update(GEN R, GEN P, GEN Q, GEN a2, GEN T, GEN *pt_R)
       return F2xqE_vert(R, Q, T);
     }
   } else {
-    GEN slope, tmp1, tmp2;
+    GEN slope = NULL, tmp1, tmp2;
     *pt_R = F2xqE_add_slope(P, R, a2, T, &slope);
     tmp1  = F2xq_mul(F2x_add(gel(Q, 1), gel(R, 1)), slope, T);
     tmp2  = F2x_add(tmp1, gel(R, 2));
diff --git a/src/basemath/FF.c b/src/basemath/FF.c
index 1dfb9aa..ccdbc40 100644
--- a/src/basemath/FF.c
+++ b/src/basemath/FF.c
@@ -116,7 +116,7 @@ FF_equalm1(GEN x)
   case t_FF_FpXQ:
     return (degpol(y) == 0 && Fp_cmp_1(gel(y,2), p));
   default:
-    return (degpol(y) == 0 && (ulong)y[2] == pp-1);
+    return (degpol(y) == 0 && uel(y,2) == pp-1);
   }
 }
 
@@ -981,15 +981,6 @@ F2xq_ell_to_a4a6(GEN E, GEN T)
 }
 
 static GEN
-Fq_to_FpXQ(GEN x, GEN T)
-{
-  if (typ(x)==t_INT)
-    return scalarpol(x, varn(T));
-  else
-    return x;
-}
-
-static GEN
 FqV_to_FpXQV(GEN x, GEN T)
 {
   pari_sp av = avma;
@@ -1016,7 +1007,7 @@ FF_ellcard(GEN E)
   switch(fg[1])
   {
   case t_FF_FpXQ:
-    return FpXQ_ellcard(Fq_to_FpXQ(gel(e,1),T), Fq_to_FpXQ(gel(e,2),T),T,p);
+    return FpXQ_ellcard(Fq_to_FpXQ(gel(e,1),T,p), Fq_to_FpXQ(gel(e,2),T,p),T,p);
   case t_FF_F2xq:
     return F2xq_ellcard(gel(e,1),gel(e,2),T);
   default:
@@ -1038,7 +1029,7 @@ FF_ellgroup(GEN E)
   switch(fg[1])
   {
   case t_FF_FpXQ:
-    G = FpXQ_ellgroup(Fq_to_FpXQ(gel(e,1),T),Fq_to_FpXQ(gel(e,2),T),N,T,p,&m);
+    G = FpXQ_ellgroup(Fq_to_FpXQ(gel(e,1),T,p),Fq_to_FpXQ(gel(e,2),T,p),N,T,p,&m);
     break;
   case t_FF_F2xq:
     G = F2xq_ellgroup(gel(e,1),gel(e,2),N,T,&m); break;
@@ -1062,7 +1053,7 @@ FF_ellgens(GEN E)
   {
   case t_FF_FpXQ:
     e3 = FqV_to_FpXQV(gel(e,3),T);
-    F = FpXQ_ellgens(Fq_to_FpXQ(gel(e,1),T),Fq_to_FpXQ(gel(e,2),T),e3,G,m,T,p);
+    F = FpXQ_ellgens(Fq_to_FpXQ(gel(e,1),T,p),Fq_to_FpXQ(gel(e,2),T,p),e3,G,m,T,p);
     break;
   case t_FF_F2xq:
     F = F2xq_ellgens(gel(e,1),gel(e,2),gel(e,3),G,m,T);
@@ -1145,7 +1136,7 @@ FF_ellrandom(GEN E)
   switch (fg[1])
   {
   case t_FF_FpXQ:
-    Q = random_FpXQE(Fq_to_FpXQ(gel(e,1),T), Fq_to_FpXQ(gel(e,2),T), T, p);
+    Q = random_FpXQE(Fq_to_FpXQ(gel(e,1),T,p), Fq_to_FpXQ(gel(e,2),T,p), T, p);
     Q = FpXQE_changepoint(Q, FqV_to_FpXQV(gel(e,3), T) , T, p);
     break;
   case t_FF_F2xq:
@@ -1393,7 +1384,7 @@ to_FF_fact(long vP, GEN P, GEN E, GEN ff, pari_sp av)
     GEN Q = simplify_shallow(gel(P,j)); /* may contain pols of degree 0 */
     if (typ(Q) == t_POL) setvarn(Q, vP);
     gel(u,j) = Q;
-    gel(v,j) = utoi((ulong)E[j]);
+    gel(v,j) = utoi(uel(E,j));
   }
   y = gerepilecopy(av, y); u = gel(y,1);
   zf = FF_zero(ff);
@@ -1401,29 +1392,6 @@ to_FF_fact(long vP, GEN P, GEN E, GEN ff, pari_sp av)
   return y;
 }
 
-/*Warning: FFX are polynomials whose coefficients are compatible with FF:
- * t_INT t_INTMOD, t_FFELT. Assume varncmp(varn(T), varn(x)) < 0 */
-static GEN
-FFX_to_FqX(GEN x, GEN T, GEN p)
-{
-  long i, l = lg(x);
-  GEN z = cgetg(l, t_POL); z[1] = x[1];
-
-  for (i = 2; i < l; i++)
-  {
-    GEN y = gel(x,i);
-    if (typ(y) == t_FFELT)
-    {
-      y = FF_to_FpXQ(y);
-      setvarn(y, varn(T)); /* paranoia */
-    }
-    else
-      y = Rg_to_FpXQ(y, T,p);
-    gel(z,i) = simplify_shallow(y);
-  }
-  return normalizepol_lg(z, l);
-}
-
 static GEN
 FFX_init_fix_varn(GEN P, GEN x, GEN *pT, GEN *pp)
 {
@@ -1443,7 +1411,7 @@ FFX_init_fix_varn(GEN P, GEN x, GEN *pT, GEN *pp)
     T=Flx_to_ZX(T);
   }
   setvarn(T, 1);
-  Q = FFX_to_FqX(P, T,p);
+  Q = RgX_to_FqX(P, T,p);
   setvarn(Q, 0);
 
   *pT = T;
@@ -1490,11 +1458,21 @@ ffgen(GEN T, long v)
       if (!FpX_is_squarefree(T,p)) pari_err_IRREDPOL("ffgen",T);
       break;
     case t_INT:
-      d = Z_isanypower(T, &p);
-      if (!d) { d = 1; p = T; }
-      if (!BPSW_psp(p)) pari_err_PRIME("ffgen",p);
+      d = ispseudoprimepower(T,&p);
+      if (!d) pari_err_PRIME("ffgen",T);
       T = init_Fq(p, d, v);
       break;
+    case t_VEC: case t_COL:
+      if (lg(T) == 3) {
+        p = gel(T,1);
+        A = gel(T,2);
+        if (typ(p) == t_INT && typ(A) == t_INT)
+        {
+          d = itos(A);
+          T = init_Fq(p, d, v);
+          break;
+        }
+      }
     default:
       pari_err_TYPE("ffgen",T);
       return NULL;
@@ -1566,6 +1544,44 @@ p_to_FF(GEN p, long v)
   gel(ff,3) = T;
   gel(ff,4) = p; return ff;
 }
+GEN
+Tp_to_FF(GEN T, GEN p)
+{
+  GEN A, ff;
+  long v;
+  if (!T) return p_to_FF(p,0);
+  ff = cgetg(5,t_FFELT);
+  v = varn(T);
+  if (lgefint(p)==3)
+  {
+    ulong pp = p[2];
+    long sv = evalvarn(v);
+    if (pp==2)
+    {
+      ff[1] = t_FF_F2xq;
+      T = ZX_to_F2x(T);
+      A = pol1_F2x(sv);
+      p = gen_2;
+    }
+    else
+    {
+      ff[1] = t_FF_Flxq;
+      T = ZX_to_Flx(T, pp);
+      A = pol1_Flx(sv);
+      p = icopy(p);
+    }
+  }
+  else
+  {
+    ff[1] = t_FF_FpXQ;
+    T = ZX_copy(T);
+    A = pol_1(v);
+    p = icopy(p);
+  }
+  gel(ff,2) = A;
+  gel(ff,3) = T;
+  gel(ff,4) = p; return ff;
+}
 
 GEN
 fforder(GEN x, GEN o)
@@ -1662,22 +1678,22 @@ FFM_to_raw(GEN x)
 }
 
 static GEN
-FqC_to_FpXQC(GEN x, GEN T)
+FqC_to_FpXQC(GEN x, GEN T, GEN p)
 {
   long i, lx;
   GEN y = cgetg_copy(x,&lx);
   for(i=1; i<lx; i++)
-    gel(y, i) = Fq_to_FpXQ(gel(x, i), T);
+    gel(y, i) = Fq_to_FpXQ(gel(x, i), T, p);
   return y;
 }
 
 static GEN
-FqM_to_FpXQM(GEN x, GEN T)
+FqM_to_FpXQM(GEN x, GEN T, GEN p)
 {
   long i, lx;
   GEN y = cgetg_copy(x,&lx);
   for(i=1; i<lx; i++)
-    gel(y, i) = FqC_to_FpXQC(gel(x, i), T);
+    gel(y, i) = FqC_to_FpXQC(gel(x, i), T, p);
   return y;
 }
 
@@ -1692,7 +1708,7 @@ FFM_wrap(GEN M, GEN ff, GEN (*Fq)(GEN,GEN,GEN),
   _getFF(ff,&T,&p,&pp); M = FFM_to_raw(M);
   switch(ff[1])
   {
-  case t_FF_FpXQ: M = FqM_to_FpXQM(Fq(M,T,p), T); break;
+  case t_FF_FpXQ: M = FqM_to_FpXQM(Fq(M,T,p), T, p); break;
   case t_FF_F2xq: M = F2xq(M,T); break;
   default: M = Flxq(M,T,pp); break;
   }
@@ -1763,9 +1779,10 @@ FFM_mul(GEN M, GEN N, GEN ff)
   pari_sp av = avma;
   ulong pp;
   GEN P, T, p;
+  int is_sqr = M==N;
   _getFF(ff, &T, &p, &pp);
   M = FFM_to_raw(M);
-  N = FFM_to_raw(N);
+  N = is_sqr? M: FFM_to_raw(N);
   switch (ff[1])
   {
   case t_FF_FpXQ: P = FqM_mul(M, N, T, p); break;
diff --git a/src/basemath/Fle.c b/src/basemath/Fle.c
new file mode 100644
index 0000000..0f6b186
--- /dev/null
+++ b/src/basemath/Fle.c
@@ -0,0 +1,583 @@
+/* Copyright (C) 2014  The PARI group.
+
+This file is part of the PARI/GP package.
+
+PARI/GP 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. It is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY WHATSOEVER.
+
+Check the License for details. You should have received a copy of it, along
+with the package; see the file 'COPYING'. If not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+#include "pari.h"
+#include "paripriv.h"
+
+/* Not so fast arithmetic with points over elliptic curves over Fl */
+
+/***********************************************************************/
+/**                                                                   **/
+/**                              Flj                                  **/
+/**                                                                   **/
+/***********************************************************************/
+
+/* Arithmetic is implemented using Jacobian coordinates, representing
+ * a projective point (x : y : z) on E by [z*x , z^2*y , z].  This is
+ * probably not the fastest representation available for the given
+ * problem, but they're easy to implement and up to 60% faster than
+ * the school-book method used in Fle_mulu().
+ */
+
+/*
+ * Cost: 1M + 8S + 1*a + 10add + 1*8 + 2*2 + 1*3.
+ * Source: http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-2007-bl
+ */
+
+INLINE void
+Flj_dbl_indir_pre(GEN P, GEN Q, ulong a4, ulong p, ulong pi)
+{
+  ulong X1, Y1, Z1;
+  ulong XX, YY, YYYY, ZZ, S, M, T;
+
+  X1 = P[1]; Y1 = P[2]; Z1 = P[3];
+
+  if (Z1 == 0)
+  {
+    Q[1] = X1; Q[2] = Y1; Q[3] = Z1;
+    return;
+  }
+
+  XX = Fl_sqr_pre(X1, p, pi);
+  YY = Fl_sqr_pre(Y1, p, pi);
+  YYYY = Fl_sqr_pre(YY, p, pi);
+  ZZ = Fl_sqr_pre(Z1, p, pi);
+  S = Fl_double(Fl_sub(Fl_sqr_pre(Fl_add(X1, YY, p), p, pi),
+                       Fl_add(XX, YYYY, p), p), p);
+  M = Fl_add(Fl_triple(XX, p),
+             Fl_mul_pre(a4, Fl_sqr_pre(ZZ, p, pi), p, pi), p);
+  T = Fl_sub(Fl_sqr_pre(M, p, pi), Fl_double(S, p), p);
+  Q[1] = T;
+  Q[2] = Fl_sub(Fl_mul_pre(M, Fl_sub(S, T, p), p, pi),
+                Fl_double(Fl_double(Fl_double(YYYY, p), p), p), p);
+  Q[3] = Fl_sub(Fl_sqr_pre(Fl_add(Y1, Z1, p), p, pi),
+                Fl_add(YY, ZZ, p), p);
+}
+
+INLINE void
+Flj_dbl_pre_inplace(GEN P, ulong a4, ulong p, ulong pi)
+{
+  Flj_dbl_indir_pre(P, P, a4, p, pi);
+}
+
+GEN
+Flj_dbl_pre(GEN P, ulong a4, ulong p, ulong pi)
+{
+  GEN Q = cgetg(4, t_VECSMALL);
+  Flj_dbl_indir_pre(P, Q, a4, p, pi);
+  return Q;
+}
+
+/*
+ * Cost: 11M + 5S + 9add + 4*2.
+ * Source: http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#addition-add-2007-bl
+ */
+
+INLINE void
+Flj_add_indir_pre(GEN P, GEN Q, GEN R, ulong a4, ulong p, ulong pi)
+{
+  ulong X1, Y1, Z1, X2, Y2, Z2;
+  ulong Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V, W;
+  X1 = P[1]; Y1 = P[2]; Z1 = P[3];
+  X2 = Q[1]; Y2 = Q[2]; Z2 = Q[3];
+
+  if (Z2 == 0) {
+    R[1] = X1; R[2] = Y1; R[3] = Z1;
+    return;
+  }
+
+  if (Z1 == 0) {
+    R[1] = X2; R[2] = Y2; R[3] = Z2;
+    return;
+  }
+
+  Z1Z1 = Fl_sqr_pre(Z1, p, pi);
+  Z2Z2 = Fl_sqr_pre(Z2, p, pi);
+  U1 = Fl_mul_pre(X1, Z2Z2, p, pi);
+  U2 = Fl_mul_pre(X2, Z1Z1, p, pi);
+  S1 = Fl_mul_pre(Y1, Fl_mul_pre(Z2, Z2Z2, p, pi), p, pi);
+  S2 = Fl_mul_pre(Y2, Fl_mul_pre(Z1, Z1Z1, p, pi), p, pi);
+  H = Fl_sub(U2, U1, p);
+  r = Fl_double(Fl_sub(S2, S1, p), p);
+
+  /* If points are equal we must double. */
+  if (H == 0) {
+    if (r == 0) {
+      /* Points are equal so double. */
+      Flj_dbl_indir_pre(P, R, a4, p, pi);
+    } else {
+      /* Points are opposite so return zero. */
+      R[1] = R[2] = 1; R[3] = 0;
+    }
+    return;
+  }
+  I = Fl_sqr_pre(Fl_double(H, p), p, pi);
+  J = Fl_mul_pre(H, I, p, pi);
+  V = Fl_mul_pre(U1, I, p, pi);
+  W = Fl_sub(Fl_sqr_pre(r, p, pi), Fl_add(J, Fl_double(V, p), p), p);
+  R[1] = W;
+  R[2] = Fl_sub(Fl_mul_pre(r, Fl_sub(V, W, p), p, pi),
+                Fl_double(Fl_mul_pre(S1, J, p, pi), p), p);
+  R[3] = Fl_mul_pre(Fl_sub(Fl_sqr_pre(Fl_add(Z1, Z2, p), p, pi),
+                           Fl_add(Z1Z1, Z2Z2, p), p), H, p, pi);
+}
+
+INLINE void
+Flj_add_pre_inplace(GEN P, GEN Q, ulong a4, ulong p, ulong pi)
+{
+  Flj_add_indir_pre(P, Q, P, a4, p, pi);
+}
+
+GEN
+Flj_add_pre(GEN P, GEN Q, ulong a4, ulong p, ulong pi)
+{
+  GEN R = cgetg(4, t_VECSMALL);
+  Flj_add_indir_pre(P, Q, R, a4, p, pi);
+  return R;
+}
+
+GEN
+Flj_neg(GEN Q, ulong p)
+{
+  return mkvecsmall3(Q[1], Fl_neg(Q[2], p), Q[3]);
+}
+
+typedef struct {
+  ulong n; /* The number being represented */
+  ulong pbits, nbits;  /* Positive bits and negative bits */
+  ulong lnzb; /* Leading non-zero bit */
+} naf_t;
+
+/*
+ * Return the signed binary representation (i.e. the Non-Adjacent Form
+ * in base 2) of 0 <= a < 2^63.
+ */
+static void
+naf_repr(naf_t *x, ulong a)
+{
+  long t, i;
+  ulong pbits, nbits;
+  ulong c0 = 0, c1, a0;
+
+  x->n = a;
+  pbits = nbits = 0;
+  for (i = 0; a; a >>= 1, ++i) {
+    a0 = a & 1;
+    c1 = (c0 + a0 + ((a & 2) >> 1)) >> 1;
+    t = c0 + a0 - (c1 << 1);
+    if (t < 0)
+      nbits |= (1UL << i);
+    else if (t > 0)
+      pbits |= (1UL << i);
+    c0 = c1;
+  }
+  c1 = c0 >> 1;
+  t = c0 - (c1 << 1);
+  /* Note that we don't need to check whether t < 0, since a >= 0 implies
+   * that this most significant signed bit must be non-negative. */
+#if 0
+  if (t < 0)
+    nbits |= (1UL << i);
+  else
+#endif
+  if (t > 0)
+    pbits |= (1UL << i);
+
+  x->pbits = pbits;
+  x->nbits = nbits;
+  /* Note that expu returns the least nonzero bit in the argument,
+   * like the bit-scan-rev instruction on Intel architectures. */
+  /* Using pbits here is justified by the fact that a >= 0, so the
+   * most significant bit must be positive. */
+  x->lnzb = expu(pbits) - 2;
+}
+
+/*
+ * Standard left-to-right signed double-and-add to compute [n]P.
+ */
+
+static GEN
+Flj_mulu_pre_naf(GEN P, ulong n, ulong a4, ulong p, ulong pi, const naf_t *x)
+{
+  GEN R, Pinv;
+  ulong pbits, nbits, lnzb;
+  ulong m;
+
+  if (n == 0)
+    return mkvecsmall3(1, 1, 0);
+  if (n == 1)
+    return Flv_copy(P);
+
+  R = Flj_dbl_pre(P, a4, p, pi);
+  if (n == 2)
+    return R;
+
+  pbits = x->pbits;
+  nbits = x->nbits;
+  lnzb = x->lnzb;
+
+  Pinv = Flj_neg(P, p);
+  m = (1UL << lnzb);
+  for ( ; m; m >>= 1) {
+    Flj_dbl_pre_inplace(R, a4, p, pi);
+    if (m & pbits)
+      Flj_add_pre_inplace(R, P, a4, p, pi);
+    else if (m & nbits)
+      Flj_add_pre_inplace(R, Pinv, a4, p, pi);
+  }
+  avma = (pari_sp)R; return R;
+}
+
+GEN
+Flj_mulu_pre(GEN P, ulong n, ulong a4, ulong p, ulong pi)
+{
+  naf_t x;
+  naf_repr(&x, n);
+  return Flj_mulu_pre_naf(P, n, a4, p, pi, &x);
+}
+
+ulong
+Flj_order_ufact(GEN P, ulong n, GEN F, ulong a4, ulong p, ulong pi)
+{
+  pari_sp av = avma;
+  ulong res = 1;
+  long i, nfactors;
+  GEN primes, exps;
+
+  primes = gel(F, 1);
+  nfactors = lg(primes);
+  exps = gel(F, 2);
+
+  for (i = 1; i < nfactors; ++i) {
+    ulong q, pp = primes[i];
+    long ei = exps[i];
+    long j, k;
+    naf_t x;
+    GEN b;
+
+    for (q = pp, j = 1; j < ei; ++j)
+      q *= pp;
+    b = Flj_mulu_pre(P, n / q, a4, p, pi);
+
+    naf_repr(&x, pp);
+    for (j = 0; j < ei && b[3] != 0; ++j)
+      b = Flj_mulu_pre_naf(b, pp, a4, p, pi, &x);
+    if (b[3] != 0)
+      return 0;
+    for (k = 0; k < j; ++k)
+      res *= pp;
+    avma = av;
+  }
+  return res;
+}
+
+GEN
+Fle_to_Flj(GEN P)
+{ return ell_is_inf(P) ? mkvecsmall3(1UL, 1UL, 0UL):
+                         mkvecsmall3(P[1], P[2], 1UL);
+}
+
+GEN
+Flj_to_Fle_pre(GEN P, ulong p, ulong pi)
+{
+  if (P[3] == 0) return ellinf();
+  else
+  {
+    ulong Z = Fl_inv(P[3], p);
+    ulong Z2 = Fl_sqr_pre(Z, p, pi);
+    ulong X3 = Fl_mul_pre(P[1], Z2, p, pi);
+    ulong Y3 = Fl_mul_pre(P[2], Fl_mul_pre(Z, Z2, p, pi), p, pi);
+    return mkvecsmall2(X3, Y3);
+  }
+}
+
+INLINE void
+random_Fle_pre_indir(ulong a4, ulong a6, ulong p, ulong pi,
+                     ulong *pt_x, ulong *pt_y)
+{
+  ulong x, x2, y, rhs;
+  do
+  {
+    x   = random_Fl(p); /*  x^3+a4*x+a6 = x*(x^2+a4)+a6  */
+    x2  = Fl_sqr_pre(x, p, pi);
+    rhs = Fl_add(Fl_mul_pre(x, Fl_add(x2, a4, p), p, pi), a6, p);
+  } while ((!rhs && !Fl_add(Fl_triple(x2,p),a4,p)) || krouu(rhs, p) < 0);
+  y = Fl_sqrt_pre(rhs, p, pi);
+  *pt_x = x; *pt_y = y;
+}
+
+GEN
+random_Flj_pre(ulong a4, ulong a6, ulong p, ulong pi)
+{
+  ulong x, y;
+  random_Fle_pre_indir(a4, a6, p, pi, &x, &y);
+  return mkvecsmall3(x, y, 1);
+}
+
+/***********************************************************************/
+/**                                                                   **/
+/**                              Fle                                  **/
+/**                                                                   **/
+/***********************************************************************/
+GEN
+Fle_changepoint(GEN x, GEN ch, ulong p)
+{
+  ulong p1,u,r,s,t,v,v2,v3;
+  GEN z;
+  if (ell_is_inf(x)) return x;
+  u = ch[1]; r = ch[2];
+  s = ch[3]; t = ch[4];
+  v = Fl_inv(u, p); v2 = Fl_sqr(v,p); v3 = Fl_mul(v,v2,p);
+  p1 = Fl_sub(x[1],r,p);
+  z = cgetg(3,t_VECSMALL);
+  z[1] = Fl_mul(v2, p1, p);
+  z[2] = Fl_mul(v3, Fl_sub(x[2], Fl_add(Fl_mul(s,p1, p),t, p),p),p);
+  return z;
+}
+
+GEN
+Fle_changepointinv(GEN x, GEN ch, ulong p)
+{
+  ulong u, r, s, t, X, Y, u2, u3, u2X;
+  GEN z;
+  if (ell_is_inf(x)) return x;
+  X = x[1]; Y = x[2];
+  u = ch[1]; r = ch[2];
+  s = ch[3]; t = ch[4];
+  u2 = Fl_sqr(u, p); u3 = Fl_mul(u,u2,p);
+  u2X = Fl_mul(u2,X, p);
+  z = cgetg(3, t_VECSMALL);
+  z[1] = Fl_add(u2X,r,p);
+  z[2] = Fl_add(Fl_mul(u3,Y,p), Fl_add(Fl_mul(s,u2X,p), t, p), p);
+  return z;
+}
+static GEN
+Fle_dbl_slope(GEN P, ulong a4, ulong p, ulong *slope)
+{
+  ulong x, y, Qx, Qy;
+  if (ell_is_inf(P) || !P[2]) return ellinf();
+  x = P[1]; y = P[2];
+  *slope = Fl_div(Fl_add(Fl_triple(Fl_sqr(x,p), p), a4, p),
+                  Fl_double(y, p), p);
+  Qx = Fl_sub(Fl_sqr(*slope, p), Fl_double(x, p), p);
+  Qy = Fl_sub(Fl_mul(*slope, Fl_sub(x, Qx, p), p), y, p);
+  return mkvecsmall2(Qx, Qy);
+}
+
+GEN
+Fle_dbl(GEN P, ulong a4, ulong p)
+{
+  ulong slope;
+  return Fle_dbl_slope(P,a4,p,&slope);
+}
+
+static GEN
+Fle_add_slope(GEN P, GEN Q, ulong a4, ulong p, ulong *slope)
+{
+  ulong Px, Py, Qx, Qy, Rx, Ry;
+  if (ell_is_inf(P)) return Q;
+  if (ell_is_inf(Q)) return P;
+  Px = P[1]; Py = P[2];
+  Qx = Q[1]; Qy = Q[2];
+  if (Px==Qx)
+    return Py==Qy ? Fle_dbl_slope(P, a4, p, slope): ellinf();
+  *slope = Fl_div(Fl_sub(Py, Qy, p), Fl_sub(Px, Qx, p), p);
+  Rx = Fl_sub(Fl_sub(Fl_sqr(*slope, p), Px, p), Qx, p);
+  Ry = Fl_sub(Fl_mul(*slope, Fl_sub(Px, Rx, p), p), Py, p);
+  return mkvecsmall2(Rx, Ry);
+}
+
+GEN
+Fle_add(GEN P, GEN Q, ulong a4, ulong p)
+{
+  ulong slope;
+  return Fle_add_slope(P,Q,a4,p,&slope);
+}
+
+static GEN
+Fle_neg(GEN P, ulong p)
+{
+  if (ell_is_inf(P)) return P;
+  return mkvecsmall2(P[1], Fl_neg(P[2], p));
+}
+
+GEN
+Fle_sub(GEN P, GEN Q, ulong a4, ulong p)
+{
+  pari_sp av = avma;
+  ulong slope;
+  return gerepileupto(av, Fle_add_slope(P, Fle_neg(Q, p), a4, p, &slope));
+}
+
+struct _Fle
+{
+  ulong a4,a6;
+  ulong p;
+};
+
+static GEN
+_Fle_dbl(void *E, GEN P)
+{
+  struct _Fle *ell = (struct _Fle *) E;
+  return Fle_dbl(P, ell->a4, ell->p);
+}
+
+static GEN
+_Fle_add(void *E, GEN P, GEN Q)
+{
+  struct _Fle *ell=(struct _Fle *) E;
+  return Fle_add(P, Q, ell->a4, ell->p);
+}
+
+GEN
+Fle_mulu(GEN P, ulong n, ulong a4, ulong p)
+{
+  ulong pi;
+  if (!n || ell_is_inf(P)) return ellinf();
+  if (n==1) return zv_copy(P);
+  if (n==2) return Fle_dbl(P, a4, p);
+  pi = get_Fl_red(p);
+  return Flj_to_Fle_pre(Flj_mulu_pre(Fle_to_Flj(P), n, a4, p, pi), p, pi);
+}
+
+static GEN
+_Fle_mul(void *E, GEN P, GEN n)
+{
+  pari_sp av = avma;
+  struct _Fle *e=(struct _Fle *) E;
+  long s = signe(n);
+  GEN Q;
+  if (!s || ell_is_inf(P)) return ellinf();
+  if (s < 0) P = Fle_neg(P, e->p);
+  if (is_pm1(n)) return s > 0? zv_copy(P): P;
+  Q = (lgefint(n)==3) ? Fle_mulu(P, uel(n,2), e->a4, e->p):
+                        gen_pow(P, n, (void*)e, &_Fle_dbl, &_Fle_add);
+  return s > 0? Q: gerepileuptoleaf(av, Q);
+}
+
+GEN
+Fle_mul(GEN P, GEN n, ulong a4, ulong p)
+{
+  struct _Fle E;
+  E.a4 = a4; E.p = p;
+  return _Fle_mul(&E, P, n);
+}
+
+/* Finds a random non-singular point on E */
+
+GEN
+random_Fle_pre(ulong a4, ulong a6, ulong p, ulong pi)
+{
+  ulong x, y;
+  random_Fle_pre_indir(a4, a6, p, pi, &x, &y);
+  return mkvecsmall2(x, y);
+}
+
+GEN
+random_Fle(ulong a4, ulong a6, ulong p)
+{ return random_Fle_pre(a4, a6, p, get_Fl_red(p)); }
+
+static GEN
+_Fle_rand(void *E)
+{
+  struct _Fle *e=(struct _Fle *) E;
+  return random_Fle(e->a4, e->a6, e->p);
+}
+
+static const struct bb_group Fle_group={_Fle_add,_Fle_mul,_Fle_rand,hash_GEN,zv_equal,ell_is_inf,NULL};
+
+GEN
+Fle_order(GEN z, GEN o, ulong a4, ulong p)
+{
+  pari_sp av = avma;
+  struct _Fle e;
+  e.a4=a4;
+  e.p=p;
+  return gerepileuptoint(av, gen_order(z, o, (void*)&e, &Fle_group));
+}
+
+GEN
+Fle_log(GEN a, GEN b, GEN o, ulong a4, ulong p)
+{
+  pari_sp av = avma;
+  struct _Fle e;
+  e.a4=a4;
+  e.p=p;
+  return gerepileuptoint(av, gen_PH_log(a, b, o, (void*)&e, &Fle_group));
+}
+
+ulong
+Fl_ellj(ulong a4, ulong a6, ulong p)
+{
+  if (SMALL_ULONG(p))
+  {
+    /* a43 = 4 a4^3 */
+    ulong a43 = Fl_double(Fl_double(Fl_mul(a4, Fl_sqr(a4, p), p), p), p);
+    /* a62 = 27 a6^2 */
+    ulong a62 = Fl_mul(Fl_sqr(a6, p), 27 % p, p);
+    ulong z1 = Fl_mul(a43, 1728 % p, p);
+    ulong z2 = Fl_add(a43, a62, p);
+    return Fl_div(z1, z2, p);
+  } else
+    return Fl_ellj_pre(a4, a6, p, get_Fl_red(p));
+}
+
+void
+Fl_ellj_to_a4a6(ulong j, ulong p, ulong *pt_a4, ulong *pt_a6)
+{
+  ulong zagier = 1728 % p;
+  if (j == 0)           { *pt_a4 = 0; *pt_a6 =1; }
+  else if (j == zagier) { *pt_a4 = 1; *pt_a6 =0; }
+  else
+  {
+    ulong k = Fl_sub(zagier, j, p);
+    ulong kj = Fl_mul(k, j, p);
+    ulong k2j = Fl_mul(kj, k, p);
+    *pt_a4 = Fl_triple(kj, p);
+    *pt_a6 = Fl_double(k2j, p);
+  }
+}
+
+ulong
+Fl_elldisc_pre(ulong a4, ulong a6, ulong p, ulong pi)
+{
+  /* D = -(4A^3 + 27B^2) */
+  ulong t1, t2;
+  t1 = Fl_mul_pre(a4, Fl_sqr_pre(a4, p, pi), p, pi);
+  t1 = Fl_double(Fl_double(t1, p), p);
+  t2 = Fl_mul_pre(27 % p, Fl_sqr_pre(a6, p, pi), p, pi);
+  return Fl_neg(Fl_add(t1, t2, p), p);
+}
+
+ulong
+Fl_elldisc(ulong a4, ulong a6, ulong p)
+{
+  if (SMALL_ULONG(p))
+  {
+    /* D = -(4A^3 + 27B^2) */
+    ulong t1, t2;
+    t1 = Fl_mul(a4, Fl_sqr(a4, p), p);
+    t1 = Fl_double(Fl_double(t1, p), p);
+    t2 = Fl_mul(27 % p, Fl_sqr(a6, p), p);
+    return Fl_neg(Fl_add(t1, t2, p), p);
+  } else
+    return Fl_elldisc_pre(a4, a6, p, get_Fl_red(p));
+}
+
+void
+Fl_elltwist(ulong a4, ulong a6, ulong D, ulong p, ulong *pt_a4, ulong *pt_a6)
+{
+  ulong D2 = Fl_sqr(D, p);
+  *pt_a4 = Fl_mul(a4, D2, p);
+  *pt_a6 = Fl_mul(a6, Fl_mul(D, D2, p), p);
+}
diff --git a/src/basemath/Flx.c b/src/basemath/Flx.c
index 3b0c874..bfa4826 100644
--- a/src/basemath/Flx.c
+++ b/src/basemath/Flx.c
@@ -218,6 +218,17 @@ ZX_to_Flx(GEN x, ulong p)
   return Flx_renormalize(a,lx);
 }
 
+/* return x[0 .. dx] mod p as t_VECSMALL. Assume x a t_POL*/
+GEN
+zx_to_Flx(GEN x, ulong p)
+{
+  long i, lx = lg(x);
+  GEN a = cgetg(lx, t_VECSMALL);
+  a[1] = x[1];
+  for (i=2; i<lx; i++) uel(a,i) = umodsu(x[i], p);
+  return Flx_renormalize(a,lx);
+}
+
 ulong
 Rg_to_Fl(GEN x, ulong p)
 {
@@ -329,7 +340,7 @@ Flx_red(GEN z, ulong p)
   long i, l = lg(z);
   GEN x = cgetg(l, t_VECSMALL);
   x[1] = z[1];
-  for (i=2; i<l; i++) x[i] = ((ulong) z[i])%p;
+  for (i=2; i<l; i++) x[i] = uel(z,i)%p;
   return Flx_renormalize(x,l);
 }
 
@@ -598,13 +609,13 @@ Flx_mullimb_ok(GEN x, GEN y, ulong p, long a, long b)
 }
 
 INLINE ulong
-Flx_mullimb(GEN x, GEN y, ulong p, long a, long b)
+Flx_mullimb(GEN x, GEN y, ulong p, ulong pi, long a, long b)
 {
   ulong p1 = 0;
   long i;
   for (i=a; i<b; i++)
     if (y[i])
-      p1 = Fl_add(p1, Fl_mul(y[i],x[-i],p), p);
+      p1 = Fl_add(p1, Fl_mul_pre(y[i],x[-i],p, pi), p);
   return p1;
 }
 
@@ -625,9 +636,10 @@ Flx_mulspec_basecase(GEN x, GEN y, ulong p, long nx, long ny)
   }
   else
   {
-    for (i=0; i<ny; i++)z[i] = Flx_mullimb(x+i,y,p,0,i+1);
-    for (  ; i<nx; i++) z[i] = Flx_mullimb(x+i,y,p,0,ny);
-    for (  ; i<nz; i++) z[i] = Flx_mullimb(x+i,y,p,i-nx+1,ny);
+    ulong pi = get_Fl_red(p);
+    for (i=0; i<ny; i++)z[i] = Flx_mullimb(x+i,y,p,pi,0,i+1);
+    for (  ; i<nx; i++) z[i] = Flx_mullimb(x+i,y,p,pi,0,ny);
+    for (  ; i<nz; i++) z[i] = Flx_mullimb(x+i,y,p,pi,i-nx+1,ny);
   }
   z -= 2; return Flx_renormalize(z, lz);
 }
@@ -637,7 +649,7 @@ int_to_Flx(GEN z, ulong p)
 {
   long i, l = lgefint(z);
   GEN x = cgetg(l, t_VECSMALL);
-  for (i=2; i<l; i++) x[i] = ((ulong) z[i])%p;
+  for (i=2; i<l; i++) x[i] = uel(z,i)%p;
   return Flx_renormalize(x, l);
 }
 
@@ -699,23 +711,43 @@ Flx_eval2BILspec(GEN x, long k, long l)
 }
 
 static GEN
-Z_mod2BIL_Flx(GEN x, long bs, long d, ulong p)
+Z_mod2BIL_Flx_2(GEN x, long d, ulong p)
 {
   long i, offset, lm = lgefint(x)-2, l = d+3;
+  ulong pi = get_Fl_red(p);
   GEN pol = cgetg(l, t_VECSMALL);
-  pari_sp av = avma;
   pol[1] = 0;
-  for (i=0, offset=0; i <= d; i++, offset += bs)
-  {
-    long lz = minss(bs, lm-offset);
-    GEN z = adduispec_offset(0, x, offset, lz);
-    pol[i+2] = umodiu(z, p);
-    avma = av;
-  }
+  for (i=0, offset=0; offset+1 < lm; i++, offset += 2)
+    pol[i+2] = remll_pre(*int_W(x,offset+1), *int_W(x,offset), p, pi);
+  if (offset < lm)
+    pol[i+2] = (*int_W(x,offset)) % p;
   return Flx_renormalize(pol,l);
 }
 
 static GEN
+Z_mod2BIL_Flx_3(GEN x, long d, ulong p)
+{
+  long i, offset, lm = lgefint(x)-2, l = d+3;
+  ulong pi = get_Fl_red(p);
+  GEN pol = cgetg(l, t_VECSMALL);
+  pol[1] = 0;
+  for (i=0, offset=0; offset+2 < lm; i++, offset += 3)
+    pol[i+2] = remlll_pre(*int_W(x,offset+2), *int_W(x,offset+1),
+                          *int_W(x,offset), p, pi);
+  if (offset+1 < lm)
+    pol[i+2] = remll_pre(*int_W(x,offset+1), *int_W(x,offset), p, pi);
+  else if (offset < lm)
+    pol[i+2] = (*int_W(x,offset)) % p;
+  return Flx_renormalize(pol,l);
+}
+
+static GEN
+Z_mod2BIL_Flx(GEN x, long bs, long d, ulong p)
+{
+  return bs==2 ? Z_mod2BIL_Flx_2(x, d, p): Z_mod2BIL_Flx_3(x, d, p);
+}
+
+static GEN
 Flx_mulspec_mulii_inflate(GEN x, GEN y, long N, ulong p, long nx, long ny)
 {
   pari_sp av = avma;
@@ -832,19 +864,20 @@ Flx_sqrspec_basecase(GEN x, ulong p, long nx)
   }
   else
   {
-    z[0] = Fl_sqr(x[0], p);
+    ulong pi = get_Fl_red(p);
+    z[0] = Fl_sqr_pre(x[0], p, pi);
     for (i=1; i<nx; i++)
     {
-      p1 = Flx_mullimb(x+i,x,p,0, (i+1)>>1);
+      p1 = Flx_mullimb(x+i,x,p,pi,0, (i+1)>>1);
       p1 = Fl_add(p1, p1, p);
-      if ((i&1) == 0) p1 = Fl_add(p1, Fl_sqr(x[i>>1], p), p);
+      if ((i&1) == 0) p1 = Fl_add(p1, Fl_sqr_pre(x[i>>1], p, pi), p);
       z[i] = p1;
     }
     for (  ; i<nz; i++)
     {
-      p1 = Flx_mullimb(x+i,x,p,i-nx+1, (i+1)>>1);
+      p1 = Flx_mullimb(x+i,x,p,pi,i-nx+1, (i+1)>>1);
       p1 = Fl_add(p1, p1, p);
-      if ((i&1) == 0) p1 = Fl_add(p1, Fl_sqr(x[i>>1], p), p);
+      if ((i&1) == 0) p1 = Fl_add(p1, Fl_sqr_pre(x[i>>1], p, pi), p);
       z[i] = p1;
     }
   }
@@ -932,15 +965,15 @@ Flx_sqr(GEN x, ulong p)
 }
 
 GEN
-Flx_pow(GEN x, long n, ulong p)
+Flx_powu(GEN x, ulong n, ulong p)
 {
   GEN y = pol1_Flx(x[1]), z;
-  long m;
+  ulong m;
   if (n == 0) return y;
   m = n; z = x;
   for (;;)
   {
-    if (m&1) y = Flx_mul(y,z, p);
+    if (m&1UL) y = Flx_mul(y,z, p);
     m >>= 1; if (!m) return y;
     z = Flx_sqr(z, p);
   }
@@ -966,6 +999,49 @@ Flx_recip(GEN x)
   return z;
 }
 
+/* Return h^degpol(P) P(x / h) */
+GEN
+Flx_rescale(GEN P, ulong h, ulong p)
+{
+  long i, l = lg(P);
+  GEN Q = cgetg(l,t_VECSMALL);
+  ulong hi = h;
+  Q[l-1] = P[l-1];
+  for (i=l-2; i>=2; i--)
+  {
+    Q[i] = Fl_mul(P[i], hi, p);
+    if (i == 2) break;
+    hi = Fl_mul(hi,h, p);
+  }
+  Q[1] = P[1]; return Q;
+}
+
+static long
+Flx_multhreshold(GEN T, ulong p, long half, long mul, long mul2, long kara)
+{
+  long na = lgpol(T);
+  switch (maxlengthcoeffpol(p,na))
+  {
+  case 0:
+    if (na>=Flx_MUL_HALFMULII_LIMIT)
+      return na>=half;
+    break;
+  case 1:
+    if (na>=Flx_MUL_MULII_LIMIT)
+      return na>=mul;
+    break;
+  case 2:
+    if (na>=Flx_MUL_MULII2_LIMIT)
+      return na>=mul2;
+    break;
+  case 3:
+    if (na>=70)
+      return na>=70;
+    break;
+  }
+  return na>=kara;
+}
+
 /*
  * x/polrecip(P)+O(x^n)
  */
@@ -1064,7 +1140,10 @@ Flx_invBarrett(GEN T, ulong p)
   long l=lg(T);
   GEN r;
   if (l<5) return pol0_Flx(T[1]);
-  if (l<=Flx_INVBARRETT_LIMIT)
+  if (!Flx_multhreshold(T,p, Flx_INVBARRETT_HALFMULII_LIMIT,
+                             Flx_INVBARRETT_MULII_LIMIT,
+                             Flx_INVBARRETT_MULII2_LIMIT,
+                             Flx_INVBARRETT_KARATSUBA_LIMIT))
   {
     ulong c = T[l-1];
     if (c!=1)
@@ -1085,9 +1164,13 @@ Flx_invBarrett(GEN T, ulong p)
 GEN
 Flx_get_red(GEN T, ulong p)
 {
-  if (typ(T)==t_VECSMALL && lg(T) >= Flx_BARRETT_LIMIT)
-    retmkvec2(Flx_invBarrett(T,p),T);
-  return T;
+  if (typ(T)!=t_VECSMALL || !Flx_multhreshold(T,p,
+                         Flx_BARRETT_HALFMULII_LIMIT,
+                         Flx_BARRETT_MULII_LIMIT,
+                         Flx_BARRETT_MULII2_LIMIT,
+                         Flx_BARRETT_KARATSUBA_LIMIT))
+    return T;
+  retmkvec2(Flx_invBarrett(T,p),T);
 }
 
 /* separate from Flx_divrem for maximal speed. */
@@ -1137,19 +1220,20 @@ Flx_rem_basecase(GEN x, GEN y, ulong p)
   }
   else
   {
-    z[dz] = Fl_mul(inv, x[dx], p);
+    ulong pi = get_Fl_red(p);
+    z[dz] = Fl_mul_pre(inv, x[dx], p, pi);
     for (i=dx-1; i>=dy; --i)
     {
       p1 = p - x[i]; /* compute -p1 instead of p1 (pb with ulongs otherwise) */
       for (j=i-dy+1; j<=i && j<=dz; j++)
-        p1 = Fl_add(p1, Fl_mul(z[j],y[i-j],p), p);
-      z[i-dy] = p1? Fl_mul(p - p1, inv, p): 0;
+        p1 = Fl_add(p1, Fl_mul_pre(z[j],y[i-j],p,pi), p);
+      z[i-dy] = p1? Fl_mul_pre(p - p1, inv, p, pi): 0;
     }
     for (i=0; i<dy; i++)
     {
-      p1 = Fl_mul(z[0],y[i],p);
+      p1 = Fl_mul_pre(z[0],y[i],p,pi);
       for (j=1; j<=i && j<=dz; j++)
-        p1 = Fl_add(p1, Fl_mul(z[j],y[i-j],p), p);
+        p1 = Fl_add(p1, Fl_mul_pre(z[j],y[i-j],p,pi), p);
       c[i] = Fl_sub(x[i], p1, p);
     }
   }
@@ -1188,7 +1272,7 @@ Flx_divrem_basecase(GEN x, GEN y, ulong p, GEN *pr)
   x += 2;
   y += 2;
   z = cgetg(dz + 3, t_VECSMALL); z[1] = sv; z += 2;
-  inv = (ulong)y[dy];
+  inv = uel(y, dy);
   if (inv != 1UL) inv = Fl_inv(inv,p);
 
   if (SMALL_ULONG(p))
@@ -1211,7 +1295,7 @@ Flx_divrem_basecase(GEN x, GEN y, ulong p, GEN *pr)
     z[dz] = Fl_mul(inv, x[dx], p);
     for (i=dx-1; i>=dy; --i)
     { /* compute -p1 instead of p1 (pb with ulongs otherwise) */
-      p1 = p - (ulong)x[i];
+      p1 = p - uel(x,i);
       for (j=i-dy+1; j<=i && j<=dz; j++)
         p1 = Fl_add(p1, Fl_mul(z[j],y[i-j],p), p);
       z[i-dy] = p1? Fl_mul(p - p1, inv, p): 0;
@@ -1497,7 +1581,7 @@ Flx_splitting(GEN p, long k)
 static GEN
 Flx_halfgcd_basecase(GEN a, GEN b, ulong p)
 {
-  pari_sp av=avma, lim = stack_lim(av,2);
+  pari_sp av=avma;
   GEN u,u1,v,v1;
   long vx = a[1];
   long n = lgpol(a)>>1;
@@ -1509,7 +1593,7 @@ Flx_halfgcd_basecase(GEN a, GEN b, ulong p)
     a = b; b = r; swap(u,u1); swap(v,v1);
     u1 = Flx_sub(u1, Flx_mul(u, q, p), p);
     v1 = Flx_sub(v1, Flx_mul(v, q ,p), p);
-    if (low_stack(lim,stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"Flx_halfgcd (d = %ld)",degpol(b));
       gerepileall(av,6, &a,&b,&u1,&v1,&u,&v);
@@ -1632,14 +1716,14 @@ Flx_halfgcd(GEN x, GEN y, ulong p)
 static GEN
 Flx_gcd_basecase(GEN a, GEN b, ulong p)
 {
-  pari_sp av = avma, lim = stack_lim(av,2);
+  pari_sp av = avma;
   ulong iter = 0;
   if (lg(b) > lg(a)) swap(a, b);
   while (lgpol(b))
   {
     GEN c = Flx_rem(a,b,p);
     iter++; a = b; b = c;
-    if (low_stack(lim,stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"Flx_gcd (d = %ld)",degpol(c));
       gerepileall(av,2, &a,&b);
@@ -1651,7 +1735,7 @@ Flx_gcd_basecase(GEN a, GEN b, ulong p)
 GEN
 Flx_gcd(GEN x, GEN y, ulong p)
 {
-  pari_sp av = avma, lim = stack_lim(av,2);
+  pari_sp av = avma;
   if (!lgpol(x)) return Flx_copy(y);
   while (lg(y)>Flx_GCD_LIMIT)
   {
@@ -1663,7 +1747,7 @@ Flx_gcd(GEN x, GEN y, ulong p)
     }
     c = FlxM_Flx_mul2(Flx_halfgcd(x,y, p), x, y, p);
     x = gel(c,1); y = gel(c,2);
-    if (low_stack(lim,stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"Flx_gcd (y = %ld)",degpol(y));
       gerepileall(av,2,&x,&y);
@@ -1718,13 +1802,12 @@ Flx_is_smooth(GEN g, long r, ulong p)
     if (degpol(f)==0) return 1;
     g = Flx_is_l_pow(f,p) ? Flx_deflate(f, p): f;
   }
-  return 0;
 }
 
 static GEN
 Flx_extgcd_basecase(GEN a, GEN b, ulong p, GEN *ptu, GEN *ptv)
 {
-  pari_sp av=avma, lim = stack_lim(av,2);
+  pari_sp av=avma;
   GEN u,v,d,d1,v1;
   long vx = a[1];
   d = a; d1 = b;
@@ -1735,7 +1818,7 @@ Flx_extgcd_basecase(GEN a, GEN b, ulong p, GEN *ptu, GEN *ptv)
     v = Flx_sub(v,Flx_mul(q,v1,p),p);
     u=v; v=v1; v1=u;
     u=r; d=d1; d1=u;
-    if (low_stack(lim,stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"Flx_extgcd (d = %ld)",degpol(d));
       gerepileall(av,5, &d,&d1,&u,&v,&v1);
@@ -1868,43 +1951,56 @@ Flx_extresultant(GEN a, GEN b, ulong p, GEN *ptU, GEN *ptV)
 }
 
 ulong
-Flx_eval(GEN x, ulong y, ulong p)
+Flx_eval_powers_pre(GEN x, GEN y, ulong p, ulong pi)
+{
+  ulong l0, l1, h0, h1, v1,  i = 1, lx = lg(x)-1;
+  LOCAL_OVERFLOW;
+  LOCAL_HIREMAINDER;
+  x++;
+
+  if (lx == 1)
+    return 0;
+  l1 = mulll(uel(x,i), uel(y,i)); h1 = hiremainder; v1 = 0;
+  while (++i < lx) {
+    l0 = mulll(uel(x,i), uel(y,i)); h0 = hiremainder;
+    l1 = addll(l0, l1); h1 = addllx(h0, h1); v1 += overflow;
+  }
+  if (v1 == 0) return remll_pre(h1, l1, p, pi);
+  else return remlll_pre(v1, h1, l1, p, pi);
+}
+
+INLINE ulong
+Flx_eval_pre_i(GEN x, ulong y, ulong p, ulong pi)
 {
-  ulong p1,r;
-  long j, i=lg(x)-1;
+  ulong p1;
+  long i=lg(x)-1;
   if (i<=2)
     return (i==2)? x[2]: 0;
   p1 = x[i];
-  /* specific attention to sparse polynomials (see poleval)*/
-  if (SMALL_ULONG(p))
+  for (i--; i>=2; i--)
+    p1 = Fl_add(uel(x,i), Fl_mul_pre(p1, y, p, pi), p);
+  return p1;
+}
+
+ulong
+Flx_eval_pre(GEN x, ulong y, ulong p, ulong pi)
+{
+  if (degpol(x) > 15)
   {
-    for (i--; i>=2; i=j-1)
-    {
-      for (j=i; !x[j]; j--)
-        if (j==2)
-        {
-          if (i != j) y = Fl_powu(y, i-j+1, p);
-          return (p1 * y) % p;
-        }
-      r = (i==j)? y: Fl_powu(y, i-j+1, p);
-      p1 = ((p1*r) + x[j]) % p;
-    }
+    pari_sp av = avma;
+    GEN v = Fl_powers_pre(y, degpol(x), p, pi);
+    ulong r =  Flx_eval_powers_pre(x, v, p, pi);
+    avma = av;
+    return r;
   }
   else
-  {
-    for (i--; i>=2; i=j-1)
-    {
-      for (j=i; !x[j]; j--)
-        if (j==2)
-        {
-          if (i != j) y = Fl_powu(y, i-j+1, p);
-          return Fl_mul(p1, y, p);
-        }
-      r = (i==j)? y: Fl_powu(y, i-j+1, p);
-      p1 = Fl_add((ulong)x[j], Fl_mul(p1,r,p), p);
-    }
-  }
-  return p1;
+    return Flx_eval_pre_i(x, y, p, pi);
+}
+
+ulong
+Flx_eval(GEN x, ulong y, ulong p)
+{
+  return Flx_eval_pre(x, y, p, get_Fl_red(p));
 }
 
 static GEN
@@ -1929,6 +2025,94 @@ Flv_roots_to_pol(GEN a, ulong p, long vs)
   setlg(p1, k); return divide_conquer_assoc(p1, (void *)&p, _Flx_mul);
 }
 
+INLINE void
+Flv_inv_pre_indir(GEN w, GEN v, ulong p, ulong pi)
+{
+  pari_sp av = avma;
+  GEN c;
+  register ulong u;
+  register long n = lg(w), i;
+
+  if (n == 1)
+    return;
+
+  c = cgetg(n, t_VECSMALL);
+  c[1] = w[1];
+  for (i = 2; i < n; ++i)
+    c[i] = Fl_mul_pre(w[i], c[i - 1], p, pi);
+
+  i = n - 1;
+  u = Fl_inv(c[i], p);
+  for ( ; i > 1; --i) {
+    ulong t = Fl_mul_pre(u, c[i - 1], p, pi);
+    u = Fl_mul_pre(u, w[i], p, pi);
+    v[i] = t;
+  }
+  v[1] = u;
+  avma = av;
+}
+
+void
+Flv_inv_pre_inplace(GEN v, ulong p, ulong pi)
+{
+  Flv_inv_pre_indir(v, v, p, pi);
+}
+
+GEN
+Flv_inv_pre(GEN w, ulong p, ulong pi)
+{
+  GEN v = cgetg(lg(w), t_VECSMALL);
+  Flv_inv_pre_indir(w, v, p, pi);
+  return v;
+}
+
+INLINE void
+Flv_inv_indir(GEN w, GEN v, ulong p)
+{
+  pari_sp av = avma;
+  GEN c;
+  register ulong u;
+  register long n = lg(w), i;
+
+  if (n == 1)
+    return;
+
+  c = cgetg(n, t_VECSMALL);
+  c[1] = w[1];
+  for (i = 2; i < n; ++i)
+    c[i] = Fl_mul(w[i], c[i - 1], p);
+
+  i = n - 1;
+  u = Fl_inv(c[i], p);
+  for ( ; i > 1; --i) {
+    ulong t = Fl_mul(u, c[i - 1], p);
+    u = Fl_mul(u, w[i], p);
+    v[i] = t;
+  }
+  v[1] = u;
+  avma = av;
+}
+
+void
+Flv_inv_inplace(GEN v, ulong p)
+{
+  if (SMALL_ULONG(p))
+    Flv_inv_indir(v, v, p);
+  else
+    Flv_inv_pre_indir(v, v, p, get_Fl_red(p));
+}
+
+GEN
+Flv_inv(GEN w, ulong p)
+{
+  GEN v = cgetg(lg(w), t_VECSMALL);
+  if (SMALL_ULONG(p))
+    Flv_inv_indir(w, v, p);
+  else
+    Flv_inv_pre_indir(w, v, p, get_Fl_red(p));
+  return v;
+}
+
 GEN
 Flx_div_by_X_x(GEN a, ulong x, ulong p, ulong *rem)
 {
@@ -1959,50 +2143,134 @@ Flx_div_by_X_x(GEN a, ulong x, ulong p, ulong *rem)
   return z;
 }
 
-/* u P(X) + v P(-X) */
+/* xa, ya = t_VECSMALL */
+static GEN
+Flv_producttree(GEN xa, ulong p, long vs)
+{
+  long n = lg(xa)-1;
+  long m = expu(n-1)+1;
+  GEN T = cgetg(m+1, t_VEC), t;
+  long i, j, k;
+  t = cgetg(((n+1)>>1)+1, t_VEC);
+  for (j=1, k=1; k<n; j++, k+=2)
+    gel(t, j) = mkvecsmall4(vs, Fl_mul(xa[k], xa[k+1], p),
+        Fl_neg(Fl_add(xa[k],xa[k+1],p),p), 1);
+  if (k==n) gel(t, j) = mkvecsmall3(vs, Fl_neg(xa[k], p), 1);
+  gel(T,1) = t;
+  for (i=2; i<=m; i++)
+  {
+    GEN u = gel(T, i-1);
+    long n = lg(u)-1;
+    t = cgetg(((n+1)>>1)+1, t_VEC);
+    for (j=1, k=1; k<n; j++, k+=2)
+      gel(t, j) = Flx_mul(gel(u, k), gel(u, k+1), p);
+    if (k==n) gel(t, j) = gel(u, k);
+    gel(T, i) = t;
+  }
+  return T;
+}
+
+static GEN
+Flx_Flv_multieval_tree(GEN P, GEN xa, GEN T, ulong p)
+{
+  long i,j,k;
+  long m = lg(T)-1, n = lg(xa)-1;
+  GEN t;
+  GEN R = cgetg(n+1, t_VECSMALL);
+  GEN Tp = cgetg(m+1, t_VEC);
+  gel(Tp, m) = mkvec(P);
+  for (i=m-1; i>=1; i--)
+  {
+    GEN u = gel(T, i);
+    GEN v = gel(Tp, i+1);
+    long n = lg(u)-1;
+    t = cgetg(n+1, t_VEC);
+    for (j=1, k=1; k<n; j++, k+=2)
+    {
+      gel(t, k)   = Flx_rem(gel(v, j), gel(u, k), p);
+      gel(t, k+1) = Flx_rem(gel(v, j), gel(u, k+1), p);
+    }
+    if (k==n) gel(t, k) = gel(v, j);
+    gel(Tp, i) = t;
+  }
+  {
+    GEN u = gel(T, i+1);
+    GEN v = gel(Tp, i+1);
+    long n = lg(u)-1;
+    for (j=1, k=1; j<=n; j++)
+    {
+      long c, d = degpol(gel(u,j));
+      for (c=1; c<=d; c++, k++)
+        R[k] = Flx_eval(gel(v, j), xa[k], p);
+    }
+  }
+  avma = (pari_sp) R;
+  return R;
+}
+
 static GEN
-Flx_even_odd_comb(GEN P, ulong u, ulong v, ulong p)
+FlvV_polint_tree(GEN T, GEN R, GEN xa, GEN ya, ulong p, long vs)
 {
-  long i, l = lg(P);
-  GEN y = cgetg(l,t_VECSMALL);
-  y[1]=P[1];
-  for (i=2; i<l; i++)
+  long m = lg(T)-1, n = lg(ya)-1;
+  long i,j,k;
+  GEN Tp = cgetg(m+1, t_VEC);
+  GEN t = cgetg(lg(gel(T,1)), t_VEC);
+  for (j=1, k=1; k<n; j++, k+=2)
+  {
+    ulong a = Fl_mul(ya[k], R[k], p), b = Fl_mul(ya[k+1], R[k+1], p);
+    gel(t, j) = mkvecsmall3(vs, Fl_neg(Fl_add(Fl_mul(xa[k], b, p ),
+                            Fl_mul(xa[k+1], a, p), p), p), Fl_add(a, b, p));
+    gel(t, j) = Flx_renormalize(gel(t, j), 4);
+  }
+  if (k==n) gel(t, j) = Fl_to_Flx(Fl_mul(ya[k], R[k], p), vs);
+  gel(Tp, 1) = t;
+  for (i=2; i<=m; i++)
   {
-    ulong t = P[i];
-    y[i] = (t == 0)? 0:
-                     (i&1)? Fl_mul(t, Fl_sub(u, v, p), p)
-                          : Fl_mul(t, Fl_add(u, v, p), p);
+    GEN u = gel(T, i-1);
+    GEN t = cgetg(lg(gel(T,i)), t_VEC);
+    GEN v = gel(Tp, i-1);
+    long n = lg(v)-1;
+    for (j=1, k=1; k<n; j++, k+=2)
+      gel(t, j) = Flx_add(Flx_mul(gel(u, k), gel(v, k+1), p),
+                          Flx_mul(gel(u, k+1), gel(v, k), p), p);
+    if (k==n) gel(t, j) = gel(v, k);
+    gel(Tp, i) = t;
   }
-  return Flx_renormalize(y,l);
+  return gmael(Tp,m,1);
+}
+
+GEN
+Flx_Flv_multieval(GEN P, GEN xa, ulong p)
+{
+  pari_sp av = avma;
+  GEN T = Flv_producttree(xa, p, P[1]);
+  return gerepileuptoleaf(av, Flx_Flv_multieval_tree(P, xa, T, p));
 }
 
-/* xa, ya = t_VECSMALL */
 GEN
 Flv_polint(GEN xa, GEN ya, ulong p, long vs)
 {
-  long i, j, n = lg(xa);
-  GEN T,dP, P = cgetg(n+1, t_VECSMALL);
-  GEN Q = Flv_roots_to_pol(xa, p, vs);
-  ulong inv;
-  P[1] = vs;
-  for (j=2; j<=n; j++) P[j] = 0UL;
-  for (i=1; i<n; i++)
-  {
-    if (!ya[i]) continue;
-    T = Flx_div_by_X_x(Q, xa[i], p, NULL);
-    inv = Fl_inv(Flx_eval(T,xa[i], p), p);
-    if (i < n-1 && (ulong)(xa[i] + xa[i+1]) == p)
-    {
-      dP = Flx_even_odd_comb(T, Fl_mul(ya[i],inv,p), Fl_mul(ya[i+1],inv,p), p);
-      i++; /* x_i = -x_{i+1} */
-    }
-    else
-      dP = Flx_Fl_mul(T, Fl_mul(ya[i],inv,p), p);
-    for (j=2; j<lg(dP); j++) P[j] = Fl_add(P[j], dP[j], p);
-    avma = (pari_sp)Q;
-  }
-  avma = (pari_sp)P;
-  return Flx_renormalize(P,n+1);
+  pari_sp av = avma;
+  GEN T = Flv_producttree(xa, p, vs);
+  long m = lg(T)-1;
+  GEN P = Flx_deriv(gmael(T, m, 1), p);
+  GEN R = Flv_inv(Flx_Flv_multieval_tree(P, xa, T, p), p);
+  return gerepileuptoleaf(av, FlvV_polint_tree(T, R, xa, ya, p, vs));
+}
+
+GEN
+Flv_FlvV_polint(GEN xa, GEN ya, ulong p, long vs)
+{
+  pari_sp av = avma;
+  GEN T = Flv_producttree(xa, p, vs);
+  long m = lg(T)-1, l = lg(ya)-1;
+  long i;
+  GEN P = Flx_deriv(gmael(T, m, 1), p);
+  GEN R = Flv_inv(Flx_Flv_multieval_tree(P, xa, T, p), p);
+  GEN M = cgetg(l+1, t_VEC);
+  for (i=1; i<=l; i++)
+    gel(M,i) = FlvV_polint_tree(T, R, xa, gel(ya,i), p, vs);
+  return gerepilecopy(av, M);
 }
 
 /***********************************************************************/
@@ -2117,7 +2385,7 @@ Flxq_invsafe(GEN x, GEN T, ulong p)
   GEN V, z = Flx_extgcd(get_Flx_mod(T), x, p, NULL, &V);
   ulong iz;
   if (degpol(z)) return NULL;
-  iz = Fl_inv ((ulong)z[2], p);
+  iz = Fl_inv (uel(z,2), p);
   return Flx_Fl_mul(V, iz, p);
 }
 
@@ -2152,6 +2420,19 @@ Flxq_matrix_pow(GEN y, long n, long m, GEN P, ulong l)
   return FlxV_to_Flm(Flxq_powers(y,m-1,P,l),n);
 }
 
+GEN
+Flx_Frobenius(GEN T, ulong p)
+{
+  return Flxq_powu(polx_Flx(get_Flx_var(T)), p, T, p);
+}
+
+GEN
+Flx_matFrobenius(GEN T, ulong p)
+{
+  long n = get_Flx_degree(T);
+  return Flxq_matrix_pow(Flx_Frobenius(T, p), n, n, T, p);
+}
+
 static struct bb_algebra Flxq_algebra = { _Flxq_red,_Flxq_add,_Flxq_mul,_Flxq_sqr,_Flxq_one,_Flxq_zero};
 
 GEN
@@ -2284,12 +2565,6 @@ Flxq_pow_Frobenius(GEN x, GEN n, GEN aut, GEN T, ulong p)
 }
 
 static GEN
-Flx_Frobenius(GEN T, ulong p)
-{
-  return Flxq_powu(polx_Flx(get_Flx_var(T)), p, T, p);
-}
-
-static GEN
 _Flxq_pow(void *data, GEN x, GEN n)
 {
   struct _Flxq *D = (struct _Flxq*)data;
@@ -2310,18 +2585,54 @@ _Flxq_rand(void *data)
   return z;
 }
 
+/* discrete log in FpXQ for a in Fp^*, g in FpXQ^* of order ord */
+static GEN
+Fl_Flxq_log(ulong a, GEN g, GEN o, GEN T, ulong p)
+{
+  pari_sp av = avma;
+  GEN q,n_q,ord,ordp, op;
+
+  if (a == 1UL) return gen_0;
+  /* p > 2 */
+
+  ordp = utoi(p - 1);
+  ord  = dlog_get_ord(o);
+  if (!ord) ord = T? subis(powuu(p, get_FpX_degree(T)), 1): ordp;
+  if (a == p - 1) /* -1 */
+    return gerepileuptoint(av, shifti(ord,-1));
+  ordp = gcdii(ordp, ord);
+  op = typ(o)==t_MAT ? famat_Z_gcd(o, ordp) : ordp;
+
+  q = NULL;
+  if (T)
+  { /* we want < g > = Fp^* */
+    if (!equalii(ord,ordp)) {
+      q = diviiexact(ord,ordp);
+      g = Flxq_pow(g,q,T,p);
+    }
+  }
+  n_q = Fp_log(utoi(a), utoi(uel(g,2)), op, utoi(p));
+  if (lg(n_q)==1) return gerepileuptoleaf(av, n_q);
+  if (q) n_q = mulii(q, n_q);
+  return gerepileuptoint(av, n_q);
+}
+
 static GEN
 Flxq_easylog(void* E, GEN a, GEN g, GEN ord)
 {
   struct _Flxq *f = (struct _Flxq *)E;
+  GEN T = f->T;
+  ulong p = f->p;
+  long d = get_Flx_degree(T);
   if (Flx_equal1(a)) return gen_0;
   if (Flx_equal(a,g)) return gen_1;
-  if (!degpol(a) && !degpol(g))
-    return Fp_log(utoi(a[2]),utoi(g[2]),ord, utoi(f->p));
-  if (typ(ord)!=t_INT || get_Flx_degree(f->T)<4 || cmpiu(ord,1UL<<27)<0)
+  if (!degpol(a))
+    return Fl_Flxq_log(uel(a,2), g, ord, T, p);
+  if (typ(ord)!=t_INT || d <= 4 || d == 6 || cmpiu(ord,1UL<<27)<0)
     return NULL;
-  return Flxq_log_index(a,g,ord,f->T,f->p);
+  return Flxq_log_index(a, g, ord, T, p);
 }
+
 int
 Flx_equal(GEN V, GEN W)
 {
@@ -2334,29 +2645,37 @@ Flx_equal(GEN V, GEN W)
 
 static const struct bb_group Flxq_star={_Flxq_mul,_Flxq_pow,_Flxq_rand,hash_GEN,Flx_equal,Flx_equal1,Flxq_easylog};
 
+const struct bb_group *
+get_Flxq_star(void **E, GEN T, ulong p)
+{
+  struct _Flxq *e = (struct _Flxq *) stack_malloc(sizeof(struct _Flxq));
+  e->T = T; e->p  = p; e->aut =  Flx_Frobenius(T, p);
+  *E = (void*)e; return &Flxq_star;
+}
+
 GEN
 Flxq_order(GEN a, GEN ord, GEN T, ulong p)
 {
-  struct _Flxq E;
-  E.T=T; E.p=p; E.aut = Flx_Frobenius(T,p);
-  return gen_order(a,ord,(void*)&E,&Flxq_star);
+  void *E;
+  const struct bb_group *S = get_Flxq_star(&E,T,p);
+  return gen_order(a,ord,E,S);
 }
 
 GEN
 Flxq_log(GEN a, GEN g, GEN ord, GEN T, ulong p)
 {
-  struct _Flxq E;
-  GEN v = dlog_get_ordfa(ord);
-  ord = mkvec2(gel(v,1),ZM_famat_limit(gel(v,2),int2n(27)));
-  E.T=T; E.p=p; E.aut = Flx_Frobenius(T,p);
-  return gen_PH_log(a,g,ord,(void*)&E,&Flxq_star);
+  void *E;
+  pari_sp av = avma;
+  const struct bb_group *S = get_Flxq_star(&E,T,p);
+  GEN v = dlog_get_ordfa(ord), F = gmael(v,2,1);
+  if (Flxq_log_use_index(gel(F,lg(F)-1), T, p))
+    ord = mkvec2(gel(v,1),ZM_famat_limit(gel(v,2),int2n(27)));
+  return gerepileuptoleaf(av, gen_PH_log(a,g,ord,E,S));
 }
 
 GEN
 Flxq_sqrtn(GEN a, GEN n, GEN T, ulong p, GEN *zeta)
 {
-  struct _Flxq E;
-  GEN o;
   if (!lgpol(a))
   {
     if (signe(n) < 0) pari_err_INV("Flxq_sqrtn",a);
@@ -2364,9 +2683,16 @@ Flxq_sqrtn(GEN a, GEN n, GEN T, ulong p, GEN *zeta)
       *zeta=pol1_Flx(get_Flx_var(T));
     return pol0_Flx(get_Flx_var(T));
   }
-  E.T=T; E.p=p; E.aut = Flx_Frobenius(T,p);
-  o = addis(powuu(p,get_Flx_degree(T)),-1);
-  return gen_Shanks_sqrtn(a,n,o,zeta,(void*)&E,&Flxq_star);
+  else
+  {
+    void *E;
+    pari_sp av = avma;
+    const struct bb_group *S = get_Flxq_star(&E,T,p);
+    GEN o = addis(powuu(p,get_Flx_degree(T)),-1);
+    GEN s = gen_Shanks_sqrtn(a,n,o,zeta,E,S);
+    if (s) gerepileall(av, zeta?2:1, &s, zeta);
+    return s;
+  }
 }
 
 GEN
@@ -2379,14 +2705,8 @@ Flxq_sqrt(GEN a, GEN T, ulong p)
 int
 Flxq_issquare(GEN x, GEN T, ulong p)
 {
-  pari_sp av;
-  GEN m;
-  ulong z;
   if (lgpol(x) == 0 || p == 2) return 1;
-  av = avma;
-  m = diviuexact(subis(powuu(p, get_Flx_degree(T)), 1), p - 1);
-  z = Flxq_pow(x, m, T, p)[2];
-  avma = av; return krouu(z, p) == 1;
+  return krouu(Flxq_norm(x,T,p), p) == 1;
 }
 
 /* assume T irreducible mod p */
@@ -2417,11 +2737,10 @@ Flxq_lroot(GEN a, GEN T, long p)
 {
   pari_sp av=avma;
   long n = get_Flx_degree(T), d = degpol(a);
-  long v = get_Flx_var(T);
-  GEN sqx,V;
+  GEN sqx, V;
   if (n==1) return leafcopy(a);
   if (n==2) return Flxq_powu(a, p, T, p);
-  sqx = Flxq_autpow(Flxq_powu(polx_Flx(v), p, T, p), n-1, T, p);
+  sqx = Flxq_autpow(Flx_Frobenius(T, p), n-1, T, p);
   if (d==1 && a[2]==0 && a[3]==1) return gerepileuptoleaf(av, sqx);
   if (d>=p)
   {
@@ -2460,8 +2779,9 @@ Flxq_charpoly(GEN x, GEN TB, ulong p)
 {
   pari_sp ltop=avma;
   GEN T = get_Flx_mod(TB);
-  GEN xm1 = deg1pol_shallow(pol1_Flx(x[1]),Flx_neg(x,p),evalvarn(MAXVARN));
-  return gerepileupto(ltop, Flx_FlxY_resultant(T, xm1 ,p));
+  GEN xm1 = deg1pol_shallow(pol1_Flx(x[1]),Flx_neg(x,p),evalvarn(fetch_var()));
+  GEN r = Flx_FlxY_resultant(T, xm1, p);
+  (void)delete_var(); return gerepileupto(ltop, r);
 }
 
 GEN
@@ -2531,7 +2851,7 @@ gener_Flxq(GEN T, ulong p, GEN *po)
     gel(L2,j++) = diviiexact(q, gel(L2,i));
   }
   setlg(L2, j);
-  F = Flxq_powu(polx_Flx(evalvarn(vT)), p, T, p); /* Frobenius */
+  F = Flx_Frobenius(T, p);
   for (av = avma;; avma = av)
   {
     ulong RES;
@@ -2549,7 +2869,7 @@ gener_Flxq(GEN T, ulong p, GEN *po)
     for (i = 1; i < j; i++)
     {
       GEN a = Flxq_pow_Frobenius(tt, gel(L2,i), F, T, p);
-      if (!degpol(a) && (ulong)a[2] == RES) break;
+      if (!degpol(a) && uel(a,2) == RES) break;
     }
     if (i == j) break;
   }
@@ -2603,6 +2923,156 @@ const struct bb_field *get_Flxq_field(void **E, GEN T, ulong p)
 
 /***********************************************************************/
 /**                                                                   **/
+/**                               Fl2                                 **/
+/**                                                                   **/
+/***********************************************************************/
+/* Fl2 objects are Flv of length 2 [a,b] representing a+bsqrt(D) for
+   a non-square D.
+*/
+
+INLINE GEN
+mkF2(ulong a, ulong b) { return mkvecsmall2(a,b); }
+
+GEN
+Fl2_mul_pre(GEN x, GEN y, ulong D, ulong p, ulong pi)
+{
+  ulong xaya, xbyb, Db2, mid;
+  ulong z1, z2;
+  ulong x1 = x[1], x2 = x[2], y1 = y[1], y2 = y[2];
+  xaya = Fl_mul_pre(x1,y1,p,pi);
+  if (x2==0 && y2==0) return mkF2(xaya,0);
+  if (x2==0) return mkF2(xaya,Fl_mul_pre(x1,y2,p,pi));
+  if (y2==0) return mkF2(xaya,Fl_mul_pre(x2,y1,p,pi));
+  xbyb = Fl_mul_pre(x2,y2,p,pi);
+  mid = Fl_mul_pre(Fl_add(x1,x2,p), Fl_add(y1,y2,p),p,pi);
+  Db2 = Fl_mul_pre(D, xbyb, p,pi);
+  z1 = Fl_add(xaya,Db2,p);
+  z2 = Fl_sub(mid,Fl_add(xaya,xbyb,p),p);
+  return mkF2(z1,z2);
+}
+
+GEN
+Fl2_sqr_pre(GEN x, ulong D, ulong p, ulong pi)
+{
+  ulong a = x[1], b = x[2];
+  ulong a2, Db2, ab;
+  a2 = Fl_sqr_pre(a,p,pi);
+  if (b==0) return mkF2(a2,0);
+  Db2= Fl_mul_pre(D, Fl_sqr_pre(b,p,pi), p,pi);
+  ab = Fl_mul_pre(a,b,p,pi);
+  return mkF2(Fl_add(a2,Db2,p), Fl_double(ab,p));
+}
+
+ulong
+Fl2_norm_pre(GEN x, ulong D, ulong p, ulong pi)
+{
+  ulong a2 = Fl_sqr_pre(x[1],p,pi);
+  return x[2]? Fl_sub(a2, Fl_mul_pre(D, Fl_sqr_pre(x[2], p,pi), p,pi), p): a2;
+}
+
+GEN
+Fl2_inv_pre(GEN x, ulong D, ulong p, ulong pi)
+{
+  ulong n, ni;
+  if (x[2] == 0) return mkF2(Fl_inv(x[1],p),0);
+  n = Fl_sub(Fl_sqr_pre(x[1], p,pi),
+             Fl_mul_pre(D, Fl_sqr_pre(x[2], p,pi), p,pi), p);
+  ni = Fl_inv(n,p);
+  return mkF2(Fl_mul_pre(x[1], ni, p,pi),
+               Fl_neg(Fl_mul_pre(x[2], ni, p,pi), p));
+}
+
+int
+Fl2_equal1(GEN x) { return x[1]==1 && x[2]==0; }
+
+struct _Fl2 {
+  ulong p, pi, D;
+};
+
+
+static GEN
+_Fl2_sqr(void *data, GEN x)
+{
+  struct _Fl2 *D = (struct _Fl2*)data;
+  return Fl2_sqr_pre(x, D->D, D->p, D->pi);
+}
+static GEN
+_Fl2_mul(void *data, GEN x, GEN y)
+{
+  struct _Fl2 *D = (struct _Fl2*)data;
+  return Fl2_mul_pre(x,y, D->D, D->p, D->pi);
+}
+
+/* n-Power of x in Z/pZ[X]/(T), as t_VECSMALL. */
+GEN
+Fl2_pow_pre(GEN x, GEN n, ulong D, ulong p, ulong pi)
+{
+  pari_sp av = avma;
+  struct _Fl2 d;
+  GEN y;
+  long s = signe(n);
+  if (!s) return mkF2(1,0);
+  if (s < 0)
+    x = Fl2_inv_pre(x,D,p,pi);
+  if (is_pm1(n)) return s < 0 ? x : zv_copy(x);
+  d.p = p; d.pi = pi; d.D=D;
+  y = gen_pow_i(x, n, (void*)&d, &_Fl2_sqr, &_Fl2_mul);
+  return gerepileuptoleaf(av, y);
+}
+
+static GEN
+_Fl2_pow(void *data, GEN x, GEN n)
+{
+  struct _Fl2 *D = (struct _Fl2*)data;
+  return Fl2_pow_pre(x, n, D->D, D->p, D->pi);
+}
+
+static GEN
+_Fl2_rand(void *data)
+{
+  struct _Fl2 *D = (struct _Fl2*)data;
+  ulong a = random_Fl(D->p), b=random_Fl(D->p-1)+1;
+  return mkF2(a,b);
+}
+
+static const struct bb_group Fl2_star={_Fl2_mul, _Fl2_pow, _Fl2_rand,
+       hash_GEN, zv_equal, Fl2_equal1, NULL};
+
+GEN
+Fl2_sqrtn_pre(GEN a, GEN n, ulong D, ulong p, ulong pi, GEN *zeta)
+{
+  struct _Fl2 E;
+  GEN o;
+  if (a[1]==0 && a[2]==0)
+  {
+    if (signe(n) < 0) pari_err_INV("Flxq_sqrtn",a);
+    if (zeta) *zeta=mkF2(1,0);
+    return zv_copy(a);
+  }
+  E.p=p; E.pi = pi; E.D = D;
+  o = addis(powuu(p,2),-1);
+  return gen_Shanks_sqrtn(a,n,o,zeta,(void*)&E,&Fl2_star);
+}
+
+GEN
+Flx_Fl2_eval_pre(GEN x, GEN y, ulong D, ulong p, ulong pi)
+{
+  GEN p1;
+  long i = lg(x)-1;
+  if (i <= 2)
+    return mkF2(i == 2? x[2]: 0, 0);
+  p1 = mkF2(x[i], 0);
+  for (i--; i>=2; i--)
+  {
+    p1 = Fl2_mul_pre(p1, y, D, p, pi);
+    uel(p1,1) = Fl_add(uel(p1,1), uel(x,i), p);
+  }
+  return p1;
+}
+
+
+/***********************************************************************/
+/**                                                                   **/
 /**                               FlxV                                **/
 /**                                                                   **/
 /***********************************************************************/
@@ -2739,6 +3209,16 @@ Fly_to_FlxY(GEN B, long sv)
 }
 
 GEN
+zxX_to_FlxX(GEN B, ulong p)
+{
+  long i, lb = lg(B);
+  GEN b = cgetg(lb,t_POL);
+  for (i=2; i<lb; i++)
+    gel(b,i) = zx_to_Flx(gel(B,i), p);
+  b[1] = B[1]; return FlxX_renormalize(b, lb);
+}
+
+GEN
 FlxX_to_ZXX(GEN B)
 {
   long i, lb = lg(B);
@@ -3017,24 +3497,54 @@ FlxY_evalx(GEN Q, ulong x, ulong p)
 }
 
 GEN
-FlxY_Flxq_evalx(GEN P, GEN x, GEN T, ulong p)
+FlxY_evalx_powers_pre(GEN pol, GEN ypowers, ulong p, ulong pi)
+{
+  long i, len = lg(pol);
+  GEN res = cgetg(len, t_VECSMALL);
+  res[1] = pol[1] & VARNBITS;
+  for (i = 2; i < len; ++i)
+    res[i] = Flx_eval_powers_pre(gel(pol, i), ypowers, p, pi);
+  return Flx_renormalize(res, len);
+}
+
+ulong
+FlxY_eval_powers_pre(GEN pol, GEN ypowers, GEN xpowers, ulong p, ulong pi)
+{
+  pari_sp av = avma;
+  GEN t = FlxY_evalx_powers_pre(pol, ypowers, p, pi);
+  ulong out = Flx_eval_powers_pre(t, xpowers, p, pi);
+  avma = av;
+  return out;
+}
+
+GEN
+FlxY_FlxqV_evalx(GEN P, GEN x, GEN T, ulong p)
 {
   long i, lP = lg(P);
   GEN res = cgetg(lP,t_POL);
   res[1] = P[1];
   for(i=2; i<lP; i++)
-    gel(res,i) = Flx_Flxq_eval(gel(P,i), x, T, p);
+    gel(res,i) = Flx_FlxqV_eval(gel(P,i), x, T, p);
   return FlxX_renormalize(res, lP);
 }
 
 GEN
+FlxY_Flxq_evalx(GEN P, GEN x, GEN T, ulong p)
+{
+  pari_sp av = avma;
+  long n = brent_kung_optpow(get_Flx_degree(T)-1,lgpol(P),1);
+  GEN xp = Flxq_powers(x, n, T, p);
+  return gerepileupto(av, FlxY_FlxqV_evalx(P, xp, T, p));
+}
+
+GEN
 FlxY_Flx_div(GEN x, GEN y, ulong p)
 {
   long i, l;
   GEN z;
   if (degpol(y) == 0)
   {
-    ulong t = (ulong)y[2];
+    ulong t = uel(y,2);
     if (t == 1) return x;
     t = Fl_inv(t, p);
     z = cgetg_copy(x, &l); z[1] = x[1];
@@ -3426,11 +3936,11 @@ FlxqX_gcd(GEN x, GEN y, GEN T, ulong p)
 GEN
 FlxqX_safegcd(GEN P, GEN Q, GEN T, ulong p)
 {
-  pari_sp btop, ltop = avma, st_lim;
+  pari_sp btop, ltop = avma;
   GEN U;
   if (!signe(P)) return gcopy(Q);
   if (!signe(Q)) return gcopy(P);
-  btop = avma; st_lim = stack_lim(btop, 1);
+  btop = avma;
   for(;;)
   {
     U = Flxq_invsafe(leading_term(Q), T, p);
@@ -3438,7 +3948,7 @@ FlxqX_safegcd(GEN P, GEN Q, GEN T, ulong p)
     Q = FlxqX_Flxq_mul_to_monic(Q,U,T,p);
     P = FlxqX_rem(P,Q,T,p);
     if (!signe(P)) break;
-    if (low_stack(st_lim, stack_lim(btop, 1)))
+    if (gc_needed(btop, 1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"FlxqX_safegcd");
       gerepileall(btop, 2, &P,&Q);
@@ -3506,6 +4016,141 @@ FlxqV_roots_to_pol(GEN V, GEN T, ulong p, long v)
   return gerepileupto(ltop, FlxqXV_prod(W, T, p));
 }
 
+/*** FlxqM ***/
+
+static GEN
+kron_pack_Flx_spec_half(GEN x, long l) {
+  if (l == 0)
+    return gen_0;
+  return Flx_to_int_halfspec(x, l);
+}
+
+static GEN
+kron_pack_Flx_spec(GEN x, long l) {
+  long i;
+  GEN w, y;
+  if (l == 0)
+    return gen_0;
+  y = cgetipos(l + 2);
+  for (i = 0, w = int_LSW(y); i < l; i++, w = int_nextW(w))
+    *w = x[i];
+  return y;
+}
+
+static GEN
+kron_pack_Flx_spec_2(GEN x, long l) {
+  return Flx_eval2BILspec(x, 2, l);
+}
+
+static GEN
+kron_pack_Flx_spec_3(GEN x, long l) {
+  return Flx_eval2BILspec(x, 3, l);
+}
+
+static GEN
+kron_unpack_Flx(GEN z, ulong p)
+{
+  long i, l = lgefint(z);
+  GEN x = cgetg(l, t_VECSMALL), w;
+  for (w = int_LSW(z), i = 2; i < l; w = int_nextW(w), i++)
+    x[i] = ((ulong) *w) % p;
+  return Flx_renormalize(x, l);
+}
+
+static GEN
+kron_unpack_Flx_2(GEN x, ulong p) {
+  long d = (lgefint(x)-1)/2 - 1;
+  return Z_mod2BIL_Flx_2(x, d, p);
+}
+
+static GEN
+kron_unpack_Flx_3(GEN x, ulong p) {
+  long d = lgefint(x)/3 - 1;
+  return Z_mod2BIL_Flx_3(x, d, p);
+}
+
+static GEN
+FlxM_pack_ZM(GEN M, GEN (*pack)(GEN, long)) {
+  long i, j, l, lc;
+  GEN N = cgetg_copy(M, &l), x;
+  if (l == 1)
+    return N;
+  lc = lgcols(M);
+  for (j = 1; j < l; j++) {
+    gel(N, j) = cgetg(lc, t_COL);
+    for (i = 1; i < lc; i++) {
+      x = gcoeff(M, i, j);
+      gcoeff(N, i, j) = pack(x + 2, lgpol(x));
+    }
+  }
+  return N;
+}
+
+static GEN
+ZM_unpack_FlxqM(GEN M, GEN T, ulong p, GEN (*unpack)(GEN, ulong))
+{
+  long i, j, l, lc, sv = get_Flx_var(T);
+  GEN N = cgetg_copy(M, &l), x;
+  if (l == 1)
+    return N;
+  lc = lgcols(M);
+  for (j = 1; j < l; j++) {
+    gel(N, j) = cgetg(lc, t_COL);
+    for (i = 1; i < lc; i++) {
+      x = unpack(gcoeff(M, i, j), p);
+      x[1] = sv;
+      gcoeff(N, i, j) = Flx_rem(x, T, p);
+    }
+  }
+  return N;
+}
+
+GEN
+FlxqM_mul_Kronecker(GEN A, GEN B, GEN T, ulong p)
+{
+  pari_sp av = avma;
+  long l, n = lg(A) - 1;
+  GEN C, D, z;
+  GEN (*pack)(GEN, long), (*unpack)(GEN, ulong);
+  int is_sqr = A==B;
+
+  /*
+    cf. Flx_mulspec(), maxlengthcoeffpol()
+    z  can be 1, 2, 3 or (theoretically) 4 words long
+  */
+  z = muliu(muliu(sqru(p - 1), degpol(T)), n);
+  l = lgefint(z);
+  avma = av;
+
+  switch (l - 2) {
+  case 1:
+    if (HIGHWORD(z[2]) == 0) {
+      pack = kron_pack_Flx_spec_half;
+      unpack = int_to_Flx_half;
+    } else {
+      pack = kron_pack_Flx_spec;
+      unpack = kron_unpack_Flx;
+    }
+    break;
+  case 2:
+    pack = kron_pack_Flx_spec_2;
+    unpack = kron_unpack_Flx_2;
+    break;
+  case 3:
+    pack = kron_pack_Flx_spec_3;
+    unpack = kron_unpack_Flx_3;
+    break;
+  default:
+    /* not implemented, probably won't occur in practice */
+    return NULL;
+  }
+  A = FlxM_pack_ZM(A, pack);
+  B = is_sqr? A: FlxM_pack_ZM(B, pack);
+  C = ZM_mul(A, B);
+  D = ZM_unpack_FlxqM(C, T, p, unpack);
+  return gerepilecopy(av, D);
+}
+
 /*******************************************************************/
 /*                                                                 */
 /*                       (Fl[X]/T(X))[Y] / S(Y)                    */
@@ -3663,25 +4308,33 @@ FlxqX_FlxqXQ_eval(GEN Q, GEN x, GEN S, GEN T, ulong p)
 }
 
 static GEN
-FlxqXQ_autpow_sqr(void * T, GEN x)
+FlxqXQ_autpow_sqr(void * E, GEN x)
 {
-  FlxqXQ_muldata *D = (FlxqXQ_muldata *)T;
+  FlxqXQ_muldata *D = (FlxqXQ_muldata *)E;
+  GEN T = D->T;
+  ulong p = D->p;
   GEN phi = gel(x,1), S = gel(x,2);
-  GEN phi2 = Flx_Flxq_eval(phi,phi,D->T,D->p);
-  GEN Sphi = FlxY_Flxq_evalx(S,phi,D->T,D->p);
-  GEN S2 = FlxqX_FlxqXQ_eval(Sphi, S, D->S,D->T,D->p);
+  long n = brent_kung_optpow(get_Flx_degree(T)-1,lgpol(S)+1,1);
+  GEN V = Flxq_powers(phi, n, T, p);
+  GEN phi2 = Flx_FlxqV_eval(phi, V, T, p);
+  GEN Sphi = FlxY_FlxqV_evalx(S, V, T, p);
+  GEN S2 = FlxqX_FlxqXQ_eval(Sphi, S, D->S, T, p);
   return mkvec2(phi2, S2);
 }
 
 static GEN
-FlxqXQ_autpow_mul(void * T, GEN x, GEN y)
+FlxqXQ_autpow_mul(void * E, GEN x, GEN y)
 {
-  FlxqXQ_muldata *D = (FlxqXQ_muldata *)T;
+  FlxqXQ_muldata *D = (FlxqXQ_muldata *)E;
+  GEN T = D->T;
+  ulong p = D->p;
   GEN phi1 = gel(x,1), S1 = gel(x,2);
   GEN phi2 = gel(y,1), S2 = gel(y,2);
-  GEN phi3 = Flx_Flxq_eval(phi1,phi2,D->T,D->p);
-  GEN Sphi = FlxY_Flxq_evalx(S1,phi2,D->T,D->p);
-  GEN S3 = FlxqX_FlxqXQ_eval(Sphi, S2, D->S,D->T,D->p);
+  long n = brent_kung_optpow(get_Flx_degree(T)-1,lgpol(S1)+1,1);
+  GEN V = Flxq_powers(phi2, n, T, p);
+  GEN phi3 = Flx_FlxqV_eval(phi1,V,T,p);
+  GEN Sphi = FlxY_FlxqV_evalx(S1,V,T,p);
+  GEN S3 = FlxqX_FlxqXQ_eval(Sphi, S2, D->S, T, p);
   return mkvec2(phi3, S3);
 }
 
@@ -3694,19 +4347,23 @@ FlxqXQV_autpow(GEN aut, long n, GEN S, GEN T, ulong p)
 }
 
 static GEN
-FlxqXQ_autsum_mul(void * T, GEN x, GEN y)
+FlxqXQ_autsum_mul(void *E, GEN x, GEN y)
 {
-  FlxqXQ_muldata *D = (FlxqXQ_muldata *)T;
+  FlxqXQ_muldata *D = (FlxqXQ_muldata *)E;
+  GEN T = D->T;
+  ulong p = D->p;
   GEN phi1 = gel(x,1), S1 = gel(x,2), a1 = gel(x,3);
   GEN phi2 = gel(y,1), S2 = gel(y,2), a2 = gel(y,3);
-  GEN phi3 = Flx_Flxq_eval(phi1,phi2,D->T,D->p);
-  GEN Sphi = FlxY_Flxq_evalx(S1,phi2,D->T,D->p);
+  long n2 = brent_kung_optpow(get_Flx_degree(T)-1, lgpol(S1)+lgpol(a1)+1,1);
+  GEN V2 = Flxq_powers(phi2, n2, T, p);
+  GEN phi3 = Flx_FlxqV_eval(phi1, V2, T, p);
+  GEN Sphi = FlxY_FlxqV_evalx(S1, V2, T, p);
+  GEN aphi = FlxY_FlxqV_evalx(a1, V2, T, p);
   long n = brent_kung_optpow(degpol(D->S)-1,2,1);
-  GEN V = FlxqXQ_powers(S2, n, D->S,D->T,D->p);
-  GEN S3 = FlxqX_FlxqXQV_eval(Sphi, V, D->S,D->T,D->p);
-  GEN aphi = FlxY_Flxq_evalx(a1,phi2,D->T,D->p);
-  GEN aS = FlxqX_FlxqXQV_eval(aphi,V,D->S,D->T,D->p);
-  GEN a3 = FlxqXQ_mul(aS,a2,D->S,D->T,D->p);
+  GEN V = FlxqXQ_powers(S2, n, D->S, T, p);
+  GEN S3 = FlxqX_FlxqXQV_eval(Sphi, V, D->S, T, p);
+  GEN aS = FlxqX_FlxqXQV_eval(aphi, V, D->S, T, p);
+  GEN a3 = FlxqXQ_mul(aS, a2, D->S, T, p);
   return mkvec3(phi3, S3, a3);
 }
 
diff --git a/src/basemath/FlxqE.c b/src/basemath/FlxqE.c
index 963ebbf..47eabde 100644
--- a/src/basemath/FlxqE.c
+++ b/src/basemath/FlxqE.c
@@ -572,13 +572,13 @@ _can5_iter(void *E, GEN f, GEN q)
   pari_sp av = avma;
   struct _can_mul D;
   ulong p = *(ulong*)E;
-  long i;
+  long i, vT = fetch_var();
   GEN N, P, d, V, fs;
-  D.q = q; D.T = ZX_Z_sub(monomial(gen_1,p,MAXVARN),gen_1);
+  D.q = q; D.T = ZX_Z_sub(monomial(gen_1,p,vT),gen_1);
   D.p = p;
-  fs = mkvec2(_shift(f, 1, p, MAXVARN), gen_1);
+  fs = mkvec2(_shift(f, 1, p, vT), gen_1);
   N = gel(gen_powu(fs,p-1,(void*)&D,_can5_sqr,_can5_mul),1);
-  N = simplify_shallow(FpXQX_red(N,polcyclo(p,MAXVARN),q));
+  N = simplify_shallow(FpXQX_red(N,polcyclo(p,vT),q));
   P = FpX_mul(N,f,q);
   P = RgX_deflate(P, p);
   d = RgX_splitting(N, p);
@@ -586,7 +586,7 @@ _can5_iter(void *E, GEN f, GEN q)
   gel(V,1) = ZX_mulu(gel(d,1), p);
   for(i=2; i<= (long)p; i++)
     gel(V,i) = ZX_mulu(RgX_shift_shallow(gel(d,p+2-i), 1), p);
-  return gerepilecopy(av, mkvec2(ZX_sub(f,P),V));
+  (void)delete_var(); return gerepilecopy(av, mkvec2(ZX_sub(f,P),V));
 }
 
 static GEN
@@ -707,10 +707,11 @@ _lift_iter(void *E, GEN x2, GEN q)
 {
   struct _lift_iso *d = (struct _lift_iso *) E;
   ulong p = d->p;
+  long n = lg(d->phi)-2;
   GEN TN = FpXT_red(d->T, q), XN = FpXV_red(d->Xm, q);
   GEN y2 = ZpXQ_frob(x2, XN, TN, q, p);
-  GEN xp = FpXQ_powers(x2, p, TN, q);
-  GEN yp = FpXQ_powers(y2, p, TN, q);
+  GEN xp = FpXQ_powers(x2, n, TN, q);
+  GEN yp = FpXQ_powers(y2, n, TN, q);
   GEN V  = FpM_FpXQV_bilinear(d->phi,xp,yp,TN,q);
   return mkvec3(V,xp,yp);
 }
@@ -966,7 +967,7 @@ zx_is_pcyc(GEN T)
 }
 
 static GEN
-Flxq_ellcard_Harley(GEN a4, GEN a6, GEN T, ulong p)
+Flxq_ellcard_Kohel(GEN a4, GEN a6, GEN T, ulong p)
 {
   pari_sp av = avma, av2;
   pari_timer ti;
@@ -1023,6 +1024,155 @@ Flxq_ellcard_Harley(GEN a4, GEN a6, GEN T, ulong p)
   return gerepileupto(av, subii(addis(powuu(p,n),1),t));
 }
 
+static void
+liftcurve(GEN J, GEN T, GEN q, ulong p, long N, GEN *A4, GEN *A6)
+{
+  pari_sp av = avma;
+  GEN r = ZpXQ_inv(Z_ZX_sub(utoi(1728),J),T,utoi(p),N);
+  GEN g = FpXQ_mul(J,r,T,q);
+  *A4 = FpX_mulu(g,3,q);
+  *A6 = FpX_mulu(g,2,q);
+  gerepileall(av,2,A4,A6);
+}
+
+static GEN
+getc5(GEN H, GEN A40, GEN A60, GEN A41, GEN A61, GEN T, GEN q, ulong p, long N)
+{
+  long d = lg(H)-1;
+  GEN s1 = gel(H,d-1), s2 = gel(H,d-2), s3 = d<5 ? pol_0(varn(T)): gel(H,d-3);
+  GEN s12 = FpXQ_sqr(s1,T,q);
+  GEN h2 = ZX_sub(ZX_shifti(s2,1),s12); /*2*s2-s1^2*/
+  GEN h3 = ZX_sub(FpXQ_mul(ZX_add(h2,s2),s1,T,q),ZX_mulu(s3,3));
+                                        /*3*s2*s1-s1^3-3s3*/
+  GEN alpha= ZX_sub(ZX_mulu(h2,30), ZX_mulu(A40,5*p-6)); /* 30*h2+A40*(6-5*p)*/
+  GEN beta = ZX_sub(ZX_sub(ZX_mulu(FpXQ_mul(A40,s1,T,q),42),ZX_mulu(A60,14*p-15)),
+                    ZX_mulu(h3,70)); /* 42*A40*s1-A60*(14*p-15)-70*h3 */
+  GEN u2 = FpXQ_mul(FpXQ_mul(A41,beta,T,q),
+                    ZpXQ_inv(FpXQ_mul(A61,alpha,T,q),T,utoi(p),N),T,q);
+  return u2;
+}
+
+static GEN
+ZpXQX_liftrootmod_vald(GEN f, GEN H, long v, GEN T, GEN p, long e)
+{
+  pari_sp av = avma, av2, lim;
+  GEN pv = p, q, qv, W, df, Tq, fr, dfr;
+  ulong mask;
+  pari_timer ti;
+  if (e <= v+1) return H;
+  df = RgX_deriv(f);
+  if (v) { pv = powiu(p,v); qv = mulii(pv,p); df = ZXX_Z_divexact(df, pv); }
+  else qv = p;
+  mask = quadratic_prec_mask(e-v);
+  Tq = FpXT_red(T, qv); dfr = FpXQX_red(df, Tq, p);
+  if (DEBUGLEVEL) timer_start(&ti);
+  W = FpXQXQ_inv(FpXQX_rem(dfr, H, Tq, p), H, Tq, p); /* 1/f'(a) mod (T,p) */
+  if (DEBUGLEVEL) timer_printf(&ti,"FpXQXQ_inv");
+  q = p;
+  av2 = avma; lim = stack_lim(av2, 2);
+  for (;;)
+  {
+    GEN u, fa, qv, q2v, Tq2, fadH;
+    GEN H2 = H, q2 = q;
+    q = sqri(q);
+    if (mask & 1) q = diviiexact(q,p);
+    mask >>= 1;
+    if (v) { qv = mulii(q, pv); q2v = mulii(q2, pv); }
+    else { qv = q; q2v = q2; }
+    Tq2 = FpXT_red(T, q2v); Tq = FpXT_red(T, qv);
+    fr = FpXQX_red(f, Tq, qv);
+    fa = FpXQX_rem(fr, H, Tq, qv);
+    fa = ZXX_Z_divexact(fa, q2v);
+    fadH = FpXQXQ_mul(RgX_deriv(H),fa,H,Tq2,q2);
+    H = FpXX_add(H, gmul(FpXQXQ_mul(W, fadH, H, Tq2, q2v), q2), qv);
+    if (mask == 1) return gerepileupto(av, H);
+    dfr = FpXQX_rem(FpXQX_red(df, Tq, q),H,Tq,q);
+    u = ZXX_Z_divexact(ZXX_Z_add_shallow(FpXQXQ_mul(W,dfr,H,Tq,q),gen_m1),q2);
+    W = gsub(W,gmul(FpXQXQ_mul(u,W,H2,Tq2,q2),q2));
+    if (low_stack(lim, stack_lim(av2,2)))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"ZpXQX_liftroot, e = %ld", e);
+      gerepileall(av2, 3, &H, &W, &q);
+    }
+  }
+}
+
+static GEN
+get_H1(GEN A41, GEN A61, GEN T2, ulong p)
+{
+  GEN q = utoi(p), T = FpXT_red(T2,q);
+  GEN pol = FpXQ_elldivpol(FpX_red(A41,q),FpX_red(A61,q),p,T,q);
+  return FqX_normalize(RgX_deflate(pol,p),T,q);
+}
+
+static GEN
+Flxq_ellcard_Harley(GEN a4, GEN a6, GEN T, ulong p)
+{
+  pari_sp av = avma, av2;
+  pari_timer ti;
+  long n = get_Flx_degree(T), N = (n+5)/2;
+  GEN q = powuu(p, N);
+  GEN T2, j, t;
+  GEN J1,A40,A41,A60,A61, sqx,Xm;
+  GEN pol, h1, H;
+  GEN c2, tc2, c2p, Nc2, Np;
+  long ispcyc = DEBUGVAR && zx_is_pcyc(get_Flx_mod(T));
+  timer_start(&ti);
+  if (!ispcyc)
+  {
+    T2 = Flx_canonlift(get_Flx_mod(T),N,p);
+    if (DEBUGLEVEL) timer_printf(&ti,"Teich");
+  } else
+    T2 = Flx_to_ZX(get_Flx_mod(T));
+  T2 = FpX_get_red(T2, q); T = ZXT_to_FlxT(T2, p);
+  av2 = avma;
+  if (DEBUGLEVEL) timer_printf(&ti,"Barrett");
+  if (!ispcyc)
+  {
+    Xm = FpXQ_powers(monomial(gen_1,n,get_FpX_var(T2)),p-1,T2,q);
+    if (DEBUGLEVEL) timer_printf(&ti,"Xm");
+  } else
+    Xm = cgetg(1,t_VEC);
+  if (DEBUGLEVEL) timer_printf(&ti,"Xm");
+  j = Flxq_ellj(a4,a6,T,p);
+  sqx = Flxq_powers(Flxq_lroot(polx_Flx(T[1]), T, p), p-1, T, p);
+  J1 = lift_isogeny(polmodular_ZM(p), Flx_to_ZX(j), N, Xm, T2,sqx,T,p);
+  if (DEBUGLEVEL) timer_printf(&ti,"Lift isogeny");
+  liftcurve(J1,T2,q,p,N,&A41,&A61);
+  A40 = ZpXQ_frob(A41, Xm, T2, q, p);
+  A60 = ZpXQ_frob(A61, Xm, T2, q, p);
+  if (DEBUGLEVEL) timer_printf(&ti,"liftcurve");
+  pol = FpXQ_elldivpol(A40,A60,p,T2,q);
+  if (DEBUGLEVEL) timer_printf(&ti,"p-division");
+  h1 = get_H1(A41,A61,T2,p);
+  H = ZpXQX_liftrootmod_vald(pol,h1,1,T2,utoi(p),N);
+  q = diviuexact(q,p); N--;
+  if (DEBUGLEVEL) timer_printf(&ti,"kernel");
+  c2 = getc5(H,A40,A60,A41,A61,T2,q,p,N);
+  if (DEBUGLEVEL) timer_printf(&ti,"c^2");
+  if (!ispcyc)
+  {
+    c2p = Flx_to_ZX(Flxq_inv(ZX_to_Flx(c2,p),T,p));
+    tc2 = Teichmuller_lift(c2p,Xm, T2,sqx,T,p,N);
+    if (DEBUGLEVEL) timer_printf(&ti,"teichmuller");
+    c2 = FpX_rem(FpX_mul(tc2,c2,q),T2,q);
+  }
+  c2 = gerepileupto(av2, c2);
+  q = powuu(p, N);
+  Nc2 = (ispcyc? ZpXQ_sqrtnorm_pcyc: ZpXQ_sqrtnorm)(c2, T2, q, utoi(p), N);
+  if (DEBUGLEVEL) timer_printf(&ti,"Norm");
+  Np = get_norm(a4,a6,T,p,N);
+  if (ispcyc)
+  {
+    GEN Ncpi = utoi(Fl_inv(umodiu(Nc2,p), p));
+    GEN tNc2 = Zp_sqrtnlift(gen_1, subss(p,1), Ncpi, utoi(p), N);
+    if (DEBUGLEVEL) timer_printf(&ti,"Teichmuller/Fp");
+    Nc2 = Fp_mul(Nc2,tNc2,q);
+  }
+  t = Fp_center(Fp_mul(Nc2,Np,q),q,shifti(q,-1));
+  return gerepileupto(av, subii(addis(powuu(p,n),1),t));
+}
+
 /***************************************************************************/
 /*                                                                         */
 /*                          Shanks Mestre                                  */
@@ -1039,7 +1189,7 @@ closest_lift(GEN a, GEN b, GEN h)
 static GEN
 FlxqE_find_order(GEN f, GEN h, GEN bound, GEN B, GEN a4, GEN T, ulong p)
 {
-  pari_sp av = avma, av1, lim;
+  pari_sp av = avma, av1;
   pari_timer Ti;
   long s = itos( gceil(gsqrt(gdiv(bound,B),DEFAULTPREC)) ) >> 1;
   GEN tx, ti;
@@ -1062,13 +1212,13 @@ FlxqE_find_order(GEN f, GEN h, GEN bound, GEN B, GEN a4, GEN T, ulong p)
   }
   tx = cgetg(s+1,t_VECSMALL);
   /* Baby Step/Giant Step */
-  av1 = avma; lim = stack_lim(av1,3);
+  av1 = avma;
   for (i=1; i<=s; i++)
   { /* baby steps */
     tx[i] = hash_GEN(gel(P, 1));
     P = FlxqE_add(P, F, a4, T, p); /* h.f + i.F */
     if (ell_is_inf(P)) return gerepileupto(av, addii(h, mului(i,B)));
-    if (low_stack(lim, stack_lim(av1,3)))
+    if (gc_needed(av1,3))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"[ellap3] baby steps, i=%ld",i);
       P = gerepileupto(av1,P);
@@ -1081,7 +1231,7 @@ FlxqE_find_order(GEN f, GEN h, GEN bound, GEN B, GEN a4, GEN T, ulong p)
   ti = vecsmall_indexsort(tx); /* = permutation sorting tx */
   tx = perm_mul(tx,ti);
   if (DEBUGLEVEL) timer_printf(&Ti, "[ellap3] sorting");
-  av1 = avma; lim = stack_lim(av1,3);
+  av1 = avma;
   for (P=fg, i=1; ; i++)
   {
     long k = hash_GEN(gel(P,1));
@@ -1102,7 +1252,7 @@ FlxqE_find_order(GEN f, GEN h, GEN bound, GEN B, GEN a4, GEN T, ulong p)
       }
     }
     P = FlxqE_add(P,fg,a4,T,p);
-    if (low_stack(lim, stack_lim(av1,3)))
+    if (gc_needed(av1,3))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"[ellap3] giants steps, i=%ld",i);
       P = gerepileupto(av1,P);
@@ -1115,7 +1265,7 @@ Flx_next(GEN t, ulong p)
 {
   long i;
   for(i=2;;i++)
-    if ((ulong)t[i]==p-1)
+    if (uel(t,i)==p-1)
       t[i]=0;
     else
     {
@@ -1172,14 +1322,38 @@ Flxq_ellcard_naive(GEN a4, GEN a6, GEN T, ulong p)
   return a;
 }
 
+/* assume T irreducible mod p, m = (q-1)/(p-1) */
+static int
+Flxq_kronecker(GEN x, GEN m, GEN T, ulong p)
+{
+  pari_sp av;
+  ulong z;
+  if (lgpol(x) == 0) return 0;
+  av = avma;
+  z = Flxq_pow(x, m, T, p)[2];
+  avma = av; return krouu(z, p);
+}
+
+/* Find x such that kronecker(u = x^3+a4x+a6, p) is KRO.
+ * Return point [x*u,u^2] on E (KRO=1) / E^twist (KRO=-1) */
+static GEN
+Flxq_ellpoint(long KRO, GEN a4, GEN a6, GEN m, long n, long vn, GEN T, ulong p)
+{
+  for(;;)
+  {
+    GEN x = random_Flx(n,vn,p);
+    GEN u = Flx_add(a6, Flxq_mul(Flx_add(a4, Flxq_sqr(x,T,p), p), x, T,p), p);
+    if (Flxq_kronecker(u, m,T,p) == KRO)
+      return mkvec2(Flxq_mul(u,x, T,p), Flxq_sqr(u, T,p));
+  }
+}
+
 static GEN
 Flxq_ellcard_Shanks(GEN a4, GEN a6, GEN q, GEN T, ulong p)
 {
   pari_sp av = avma;
-  long vn = get_Flx_var(T);
-  long i, twistp, twistpold=0;
-  GEN h,f, ta4, u, x, A, B;
-  long n = get_Flx_degree(T);
+  long vn = get_Flx_var(T), n = get_Flx_degree(T), KRO = -1;
+  GEN h,f, ta4, A, B, m;
   GEN q1p = addsi(1, q), q2p = shifti(q1p, 1);
   GEN bound = addis(sqrti(gmul2n(q,4)), 1); /* ceil( 4sqrt(q) ) */
   /* once #E(Flxq) is know mod B >= bound, it is completely determined */
@@ -1190,42 +1364,30 @@ Flxq_ellcard_Shanks(GEN a4, GEN a6, GEN q, GEN T, ulong p)
   case 1:  A = gen_0; B = gen_2; break;
   default: A = gen_1; B = gen_2; break; /* 0 */
   }
-  h = closest_lift(A, B, q1p);
+  m = diviuexact(subiu(powuu(p,n), 1), p-1);
   for(;;)
   {
-    do
-    { /* look for points alternatively on E and its quadratic twist E' */
-      x = random_Flx(n,vn,p);
-      u = Flx_add(a6, Flxq_mul(Flx_add(a4, Flxq_sqr(x, T, p), p), x , T, p), p);
-      twistp = Flxq_issquare(u, T, p);
-    } while (twistp == twistpold);
-    twistpold = twistp;
+    h = closest_lift(A, B, q1p);
     /* [ux, u^2] is on E_u: y^2 = x^3 + c4 u^2 x + c6 u^3
-     * E_u isomorphic to E (resp. E') iff twistp = 1 (resp. -1)
+     * E_u isomorphic to E (resp. E') iff KRO = 1 (resp. -1)
      * #E(F_p) = p+1 - a_p, #E'(F_p) = p+1 + a_p
      *
      * #E_u(Flxq) = A (mod B),  h is close to #E_u(Flxq) */
+    KRO = -KRO;
+    f = Flxq_ellpoint(KRO, a4,a6, m,n,vn, T,p);
 
-    f = mkvec2(Flxq_mul(u, x, T, p), Flxq_sqr(u, T, p));
     ta4 = Flxq_mul(a4, gel(f,2), T, p); /* a4 for E_u */
     h = FlxqE_find_order(f, h, bound, B, ta4,T,p);
     h = FlxqE_order(f, h, ta4, T, p);
     /* h | #E_u(Flxq) = A (mod B) */
-    if (B == gen_1)
-      B = h;
-    else
-      A = Z_chinese_all(A, gen_0, B, h, &B);
-
-    i = (cmpii(B, bound) < 0);
-    /* If we are not done, update A mod B for the _next_ curve, isomorphic to
+    A = Z_chinese_all(A, gen_0, B, h, &B);
+    if (cmpii(B, bound) >= 0) break;
+    /* not done, update A mod B for the _next_ curve, isomorphic to
      * the quadratic twist of this one */
-    if (i) A = remii(subii(q2p,A), B); /* #E(Fq)+#E'(Fq) = 2q+2 */
-
-    /* h = A mod B, closest lift to p+1 */
-    h = closest_lift(A, B, q1p);
-    if (!i) break;
+    A = remii(subii(q2p,A), B); /* #E(Fq)+#E'(Fq) = 2q+2 */
   }
-  return gerepileuptoint(av, twistp? h: subii(shifti(q1p,1),h));
+  h = closest_lift(A, B, q1p);
+  return gerepileuptoint(av, KRO == 1? h: subii(q2p,h));
 }
 
 static GEN
@@ -1249,40 +1411,59 @@ F3xq_ellcard(GEN a2, GEN a6, GEN T)
       if (umodiu(t, 3)!=1) t = negi(t);
       return Flx_equal1(a2) || Flxq_issquare(a2,T,3) ? subii(q1,t): addii(q1,t);
     }
-    else return Flxq_ellcard_Harley(mkvec(a2), a6, T, 3);
+    else return Flxq_ellcard_Kohel(mkvec(a2), a6, T, 3);
   }
 }
 
 static GEN
-Flxq_ellcard_Satoh(GEN a4, GEN a6, GEN T, ulong p)
+Flxq_ellcard_Satoh(GEN a4, GEN a6, GEN j, GEN T, ulong p)
 {
   long n = get_Flx_degree(T);
   if (n <= 2)
     return utoi(Flxq_ellcard_naive(a4, a6, T, p));
   else
   {
-    GEN q1 = addis(powuu(p, get_Flx_degree(T)), 1), t;
-    GEN j = Flxq_ellj(a4,a6,T,p);
-    if (Flx_equal1(Flxq_powu(j, p*p-1, T, p)))
-    {
-      GEN sk, sA4, u;
-      GEN P = Flxq_minpoly(j, T, p);
-      long dP = degpol(P); /* dP <= 2 */
-      GEN q = powuu(p,dP);
-      GEN k = mkvecsmall3(T[1], 1728%p, p-1);
-      GEN kj = Flx_shift(k, 1), k2j = Flxq_mul(kj, k, P, p);
-      GEN A4 = Flx_triple(kj,p), A6 = Flx_double(k2j,p);
-      GEN tP = addis(q, 1 - Flxq_ellcard_naive(A4, A6, P, p));
-      t = elltrace_extension(tP, n/dP, q);
-      sk = Flx_Fl_add(Flx_neg(j,p),1728%p,p);
-      sA4 = Flx_triple(Flxq_mul(sk,j,T,p),p);
-      u = Flxq_div(a4,sA4, T, p);
-      return Flxq_is2npower(u, 2, T, p) ? subii(q1,t): addii(q1,t);
+    GEN jp = Flxq_powu(j, p, T, p);
+    GEN s = Flx_add(j, jp, p);
+    if (degpol(s) <= 0)
+    { /* it is assumed j not in F_p */
+      GEN m = Flxq_mul(j, jp, T, p);
+      if (degpol(m) <= 0)
+      {
+        GEN q = sqru(p);
+        GEN q1 = addis(powuu(p, get_Flx_degree(T)), 1);
+        GEN sk = Flx_Fl_add(Flx_neg(j, p), 1728%p, p);
+        GEN sA4 = Flx_triple(Flxq_mul(sk, j, T, p), p);
+        GEN u = Flxq_div(a4, sA4, T, p);
+        ulong ns = lgpol(s) ? Fl_neg(s[2], p): 0UL;
+        GEN P = mkvecsmall4(T[1], m[2], ns, 1L);
+        GEN A4, A6, t, tP;
+        Flxq_ellj_to_a4a6(polx_Flx(T[1]), P, p, &A4, &A6);
+        tP = addis(q, 1 - Flxq_ellcard_naive(A4, A6, P, p));
+        t = elltrace_extension(tP, n>>1, q);
+        return Flxq_is2npower(u, 2, T, p) ? subii(q1,t): addii(q1,t);
+      }
     }
+    if (p<=7 || p==13 ) return Flxq_ellcard_Kohel(a4, a6, T, p);
     else return Flxq_ellcard_Harley(a4, a6, T, p);
   }
 }
 
+static GEN
+Flxq_ellcard_Kedlaya(GEN a4, GEN a6, GEN T, ulong p)
+{
+  pari_sp av = avma;
+  GEN H = mkpoln(4, gen_1, gen_0, Flx_to_ZX(a4), Flx_to_ZX(a6));
+  GEN Tp = Flx_to_ZX(get_Flx_mod(T));
+  long n = degpol(Tp), e = ((p < 16 ? n+1: n)>>1)+1;
+  GEN M = ZlXQX_hyperellpadicfrobenius(H, Tp, p, e);
+  GEN N = ZpXQM_prodFrobenius(M, Tp, utoi(p), e);
+  GEN q = powuu(p, e);
+  GEN tp = Fq_add(gcoeff(N,1,1), gcoeff(N,2,2), Tp, q);
+  GEN t = Fp_center(typ(tp)==t_INT ? tp: leading_term(tp), q, shifti(q,-1));
+  return gerepileupto(av, subii(addis(powuu(p, n), 1), t));
+}
+
 GEN
 Flxq_ellj(GEN a4, GEN a6, GEN T, ulong p)
 {
@@ -1305,6 +1486,24 @@ Flxq_ellj(GEN a4, GEN a6, GEN T, ulong p)
   }
 }
 
+void
+Flxq_ellj_to_a4a6(GEN j, GEN T, ulong p, GEN *pt_a4, GEN *pt_a6)
+{
+  ulong zagier = 1728 % p;
+  if (lgpol(j)==0)
+    { *pt_a4 = pol0_Flx(T[1]); *pt_a6 =pol1_Flx(T[1]); }
+  else if (lgpol(j)==1 && uel(j,2) == zagier)
+    { *pt_a4 = pol1_Flx(T[1]); *pt_a6 =pol0_Flx(T[1]); }
+  else
+  {
+    GEN k = Flx_Fl_add(Flx_neg(j, p), zagier, p);
+    GEN kj = Flxq_mul(k, j, T, p);
+    GEN k2j = Flxq_mul(kj, k, T, p);
+    *pt_a4 = Flx_triple(kj, p);
+    *pt_a6 = Flx_double(k2j, p);
+  }
+}
+
 static GEN
 F3xq_ellcardj(GEN a4, GEN a6, GEN T, GEN q, long n)
 {
@@ -1415,10 +1614,14 @@ Flxq_ellcard(GEN a4, GEN a6, GEN T, ulong p)
     r = Fp_ffellcard(utoi(Flx_eval(a4,0,p)),utoi(Flx_eval(a6,0,p)),q,n,utoi(p));
   else if (degpol(J=Flxq_ellj(a4,a6,T,p))<=0)
     r = Flxq_ellcardj(a4,a6,lgpol(J)?J[2]:0,T,q,p,n);
-  else if (p <= 7 || p==13)
-    r = Flxq_ellcard_Satoh(a4,a6,T,p);
+  else if (p <= 7)
+    r = Flxq_ellcard_Satoh(a4, a6, J, T, p);
   else if (cmpis(q,100)<0)
     r = utoi(Flxq_ellcard_naive(a4, a6, T, p));
+  else if (p <= 13 || (7*p <= (ulong)10*n && (BITS_IN_LONG==64 || p <= 31)))
+    r = Flxq_ellcard_Satoh(a4, a6, J, T, p);
+  else if (p <= (ulong)2*n)
+    r = Flxq_ellcard_Kedlaya(a4, a6, T, p);
   else if (expi(q)<=62)
     r = Flxq_ellcard_Shanks(a4, a6, q, T, p);
   else
diff --git a/src/basemath/Flxq_log.c b/src/basemath/Flxq_log.c
index e688dce..9168612 100644
--- a/src/basemath/Flxq_log.c
+++ b/src/basemath/Flxq_log.c
@@ -198,7 +198,7 @@ Flxq_log_cubic(struct Flxq_log_rel *r, GEN C, GEN R, ulong p)
 static GEN
 Flxq_log_find_rel(GEN b, long r, GEN T, ulong p, GEN *g, long *e)
 {
-  pari_sp av = avma, lim = stack_lim(av,2);
+  pari_sp av = avma;
   while (1)
   {
     GEN M;
@@ -216,7 +216,7 @@ Flxq_log_find_rel(GEN b, long r, GEN T, ulong p, GEN *g, long *e)
         gerepileall(av,2,g,&rel); return rel;
       }
     }
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"Flxq_log_find_rel");
       *g = gerepilecopy(av, *g);
@@ -391,6 +391,18 @@ Flxq_log_rec(GEN W, GEN a, long r, GEN T, ulong p, GEN m)
   }
 }
 
+static int
+Flxq_log_use_index_cubic(GEN m, GEN T0, ulong p)
+{
+  pari_sp av = avma;
+  long n = get_Flx_degree(T0), r, nb;
+  GEN cost = smooth_best(p, n, &r, &nb);
+  GEN cost_rho = sqrti(shifti(m,2));
+  int use = (cost && gcmp(cost,cost_rho)<0);
+  avma = av;
+  return use;
+}
+
 static GEN
 Flxq_log_index_cubic(GEN a0, GEN b0, GEN m, GEN T0, ulong p)
 {
@@ -689,7 +701,20 @@ Flxq_log_index_Coppersmith(GEN a0, GEN b0, GEN m, GEN T0, ulong p)
 GEN
 Flxq_log_index(GEN a, GEN b, GEN m, GEN T, ulong p)
 {
-  if (p==3 || (p==5 && degpol(T)>41))
+  long d = get_Flx_degree(T);
+  if (p==3 || (p==5 && d>41))
     return Flxq_log_index_Coppersmith(a, b, m, T, p);
   else    return Flxq_log_index_cubic(a, b, m, T, p);
 }
+
+int
+Flxq_log_use_index(GEN m, GEN T, ulong p)
+{
+  long d = get_Flx_degree(T);
+  if (p==3 || (p==5 && d>41))
+    return 1;
+  else if (d<=4 || d==6)
+    return 0;
+  else
+    return Flxq_log_use_index_cubic(m, T, p);
+}
diff --git a/src/basemath/FpE.c b/src/basemath/FpE.c
index 59c6ed2..ba85515 100644
--- a/src/basemath/FpE.c
+++ b/src/basemath/FpE.c
@@ -18,197 +18,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 
 /***********************************************************************/
 /**                                                                   **/
-/**                              Fle                                  **/
-/**                                                                   **/
-/***********************************************************************/
-static GEN
-Fle_dbl_slope(GEN P, ulong a4, ulong p, ulong *slope)
-{
-  ulong x, y, Qx, Qy;
-  if (ell_is_inf(P) || !P[2]) return ellinf();
-  x = P[1]; y = P[2];
-  *slope = Fl_div(Fl_add(Fl_triple(Fl_sqr(x,p), p), a4, p),
-                  Fl_double(y, p), p);
-  Qx = Fl_sub(Fl_sqr(*slope, p), Fl_double(x, p), p);
-  Qy = Fl_sub(Fl_mul(*slope, Fl_sub(x, Qx, p), p), y, p);
-  return mkvecsmall2(Qx, Qy);
-}
-
-GEN
-Fle_dbl(GEN P, ulong a4, ulong p)
-{
-  ulong slope;
-  return Fle_dbl_slope(P,a4,p,&slope);
-}
-
-static GEN
-Fle_add_slope(GEN P, GEN Q, ulong a4, ulong p, ulong *slope)
-{
-  ulong Px, Py, Qx, Qy, Rx, Ry;
-  if (ell_is_inf(P)) return Q;
-  if (ell_is_inf(Q)) return P;
-  Px = P[1]; Py = P[2];
-  Qx = Q[1]; Qy = Q[2];
-  if (Px==Qx)
-    return Py==Qy ? Fle_dbl_slope(P, a4, p, slope): ellinf();
-  *slope = Fl_div(Fl_sub(Py, Qy, p), Fl_sub(Px, Qx, p), p);
-  Rx = Fl_sub(Fl_sub(Fl_sqr(*slope, p), Px, p), Qx, p);
-  Ry = Fl_sub(Fl_mul(*slope, Fl_sub(Px, Rx, p), p), Py, p);
-  return mkvecsmall2(Rx, Ry);
-}
-
-GEN
-Fle_add(GEN P, GEN Q, ulong a4, ulong p)
-{
-  ulong slope;
-  return Fle_add_slope(P,Q,a4,p,&slope);
-}
-
-static long
-Fle_dbl_inplace(GEN P, ulong a4, ulong p)
-{
-  ulong x, y, slope;
-  if (!P[2]) return 1;
-  x = P[1]; y = P[2];
-  slope = Fl_div(Fl_add(Fl_triple(Fl_sqr(x,p), p), a4, p),
-                 Fl_double(y, p), p);
-  P[1] = Fl_sub(Fl_sqr(slope, p), Fl_double(x, p), p);
-  P[2] = Fl_sub(Fl_mul(slope, Fl_sub(x, P[1], p), p), y, p);
-  return 0;
-}
-
-static long
-Fle_add_inplace(GEN P, GEN Q, ulong a4, ulong p)
-{
-  ulong Px, Py, Qx, Qy, slope;
-  if (ell_is_inf(Q)) return 0;
-  Px = P[1]; Py = P[2];
-  Qx = Q[1]; Qy = Q[2];
-  if (Px==Qx)
-    return Py==Qy ? Fle_dbl_inplace(P, a4, p): 1;
-  slope = Fl_div(Fl_sub(Py, Qy, p), Fl_sub(Px, Qx, p), p);
-  P[1] = Fl_sub(Fl_sub(Fl_sqr(slope, p), Px, p), Qx, p);
-  P[2] = Fl_sub(Fl_mul(slope, Fl_sub(Px, P[1], p), p), Py, p);
-  return 0;
-}
-
-static GEN
-Fle_neg(GEN P, ulong p)
-{
-  if (ell_is_inf(P)) return P;
-  return mkvecsmall2(P[1], Fl_neg(P[2], p));
-}
-
-GEN
-Fle_sub(GEN P, GEN Q, ulong a4, ulong p)
-{
-  pari_sp av = avma;
-  ulong slope;
-  return gerepileupto(av, Fle_add_slope(P, Fle_neg(Q, p), a4, p, &slope));
-}
-
-struct _Fle
-{
-  ulong a4,a6;
-  ulong p;
-};
-
-static GEN
-_Fle_dbl(void *E, GEN P)
-{
-  struct _Fle *ell = (struct _Fle *) E;
-  return Fle_dbl(P, ell->a4, ell->p);
-}
-
-static GEN
-_Fle_add(void *E, GEN P, GEN Q)
-{
-  struct _Fle *ell=(struct _Fle *) E;
-  return Fle_add(P, Q, ell->a4, ell->p);
-}
-
-static GEN
-_Fle_mulu(void *E, GEN P, ulong n)
-{
-  pari_sp av = avma;
-  struct _Fle *e=(struct _Fle *) E;
-  if (!n || ell_is_inf(P)) return ellinf();
-  if (n==1) return zv_copy(P);
-  if (n==2) return Fle_dbl(P,e->a4, e->p);
-  return gerepileupto(av, gen_powu(P, n, (void*)e, &_Fle_dbl, &_Fle_add));
-}
-
-GEN
-Fle_mulu(GEN P, ulong n, ulong a4, ulong p)
-{
-  struct _Fle E;
-  E.a4= a4; E.p = p;
-  return _Fle_mulu(&E, P, n);
-}
-
-static GEN
-_Fle_mul(void *E, GEN P, GEN n)
-{
-  pari_sp av = avma;
-  struct _Fle *e=(struct _Fle *) E;
-  long s = signe(n);
-  if (!s || ell_is_inf(P)) return ellinf();
-  if (s<0) P = Fle_neg(P, e->p);
-  if (is_pm1(n)) return s>0? zv_copy(P): P;
-  return gerepileupto(av, gen_pow(P, n, (void*)e, &_Fle_dbl, &_Fle_add));
-}
-
-GEN
-Fle_mul(GEN P, GEN n, ulong a4, ulong p)
-{
-  struct _Fle E;
-  E.a4 = a4; E.p = p;
-  return _Fle_mul(&E, P, n);
-}
-
-/* Finds a random non-singular point on E */
-
-GEN
-random_Fle(ulong a4, ulong a6, ulong p)
-{
-  ulong x, x2, y, rhs;
-  do
-  {
-    x   = random_Fl(p); /*  x^3+a4*x+a6 = x*(x^2+a4)+a6  */
-    x2  = Fl_sqr(x, p);
-    rhs = Fl_add(Fl_mul(x, Fl_add(x2, a4, p), p), a6, p);
-  } while ((!rhs && !Fl_add(Fl_triple(x2,p),a4,p))
-          || krouu(rhs, p) < 0);
-  y = Fl_sqrt(rhs, p);
-  return mkvecsmall2(x, y);
-}
-
-static GEN
-_Fle_rand(void *E)
-{
-  struct _Fle *e=(struct _Fle *) E;
-  return random_Fle(e->a4, e->a6, e->p);
-}
-
-static const struct bb_group Fle_group={_Fle_add,_Fle_mul,_Fle_rand,hash_GEN,zv_equal,ell_is_inf,NULL};
-
-GEN
-Fle_order(GEN z, GEN o, ulong a4, ulong p)
-{
-  pari_sp av = avma;
-  struct _Fle e;
-  e.a4=a4;
-  e.p=p;
-  return gerepileuptoint(av, gen_order(z, o, (void*)&e, &Fle_group));
-}
-
-/***********************************************************************/
-/**                                                                   **/
 /**                              FpE                                  **/
 /**                                                                   **/
 /***********************************************************************/
 
-/* Theses functions deal with point over elliptic curves over Fp defined
+/* These functions deal with point over elliptic curves over Fp defined
  * by an equation of the form y^2=x^3+a4*x+a6.
  * Most of the time a6 is omitted since it can be recovered from any point
  * on the curve.
@@ -417,9 +231,19 @@ FpE_order(GEN z, GEN o, GEN a4, GEN p)
 {
   pari_sp av = avma;
   struct _FpE e;
-  e.a4=a4;
-  e.p=p;
-  return gerepileuptoint(av, gen_order(z, o, (void*)&e, &FpE_group));
+  GEN r;
+  if (lgefint(p) == 3)
+  {
+    ulong pp = p[2];
+    r = Fle_order(ZV_to_Flv(z, pp), o, umodiu(a4,pp), pp);
+  }
+  else
+  {
+    e.a4 = a4;
+    e.p = p;
+    r = gen_order(z, o, (void*)&e, &FpE_group);
+  }
+  return gerepileuptoint(av, r);
 }
 
 GEN
@@ -427,9 +251,19 @@ FpE_log(GEN a, GEN b, GEN o, GEN a4, GEN p)
 {
   pari_sp av = avma;
   struct _FpE e;
-  e.a4=a4;
-  e.p=p;
-  return gerepileuptoint(av, gen_PH_log(a, b, o, (void*)&e, &FpE_group));
+  GEN r;
+  if (lgefint(p) == 3)
+  {
+    ulong pp = p[2];
+    r = Fle_log(ZV_to_Flv(a,pp), ZV_to_Flv(b,pp), o, umodiu(a4,pp), pp);
+  }
+  else
+  {
+    e.a4 = a4;
+    e.p = p;
+    r = gen_PH_log(a, b, o, (void*)&e, &FpE_group);
+  }
+  return gerepileuptoint(av, r);
 }
 
 /***********************************************************************/
@@ -592,6 +426,152 @@ FpE_tatepairing(GEN P, GEN Q, GEN m, GEN a4, GEN p)
 
 /***********************************************************************/
 /**                                                                   **/
+/**                   CM by principal order                           **/
+/**                                                                   **/
+/***********************************************************************/
+
+/* is jn/jd = J (mod p) */
+static int
+is_CMj(long J, GEN jn, GEN jd, GEN p)
+{ return remii(subii(mulis(jd,J), jn), p) == gen_0; }
+#ifndef LONG_IS_64BIT
+/* is jn/jd = -(2^32 a + b) (mod p) */
+static int
+u2_is_CMj(ulong a, ulong b, GEN jn, GEN jd, GEN p)
+{
+  GEN mJ = uu32toi(a,b);
+  return remii(addii(mulii(jd,mJ), jn), p) == gen_0;
+}
+#endif
+
+static long
+Fp_ellj_get_CM(GEN jn, GEN jd, GEN p)
+{
+#define CHECK(CM,J) if (is_CMj(J,jn,jd,p)) return CM;
+  CHECK(-3,  0);
+  CHECK(-4,  1728);
+  CHECK(-7,  -3375);
+  CHECK(-8,  8000);
+  CHECK(-11, -32768);
+  CHECK(-12, 54000);
+  CHECK(-16, 287496);
+  CHECK(-19, -884736);
+  CHECK(-27, -12288000);
+  CHECK(-28, 16581375);
+  CHECK(-43, -884736000);
+#ifdef LONG_IS_64BIT
+  CHECK(-67, -147197952000);
+  CHECK(-163, -262537412640768000);
+#else
+  if (u2_is_CMj(0x00000022UL,0x45ae8000UL,jn,jd,p)) return -67;
+  if (u2_is_CMj(0x03a4b862UL,0xc4b40000UL,jn,jd,p)) return -163;
+#endif
+#undef CHECK
+  return 0;
+}
+
+/***********************************************************************/
+/**                                                                   **/
+/**                            issupersingular                        **/
+/**                                                                   **/
+/***********************************************************************/
+
+/* assume x reduced mod p, monic. Return one root, or NULL if irreducible */
+static GEN
+FqX_quad_root(GEN x, GEN T, GEN p)
+{
+  GEN b = gel(x,3), c = gel(x,2);
+  GEN D = Fq_sub(Fq_sqr(b, T, p), Fq_mulu(c,4, T, p), T, p);
+  GEN s = Fq_sqrt(D,T, p);
+  if (!s) return NULL;
+  return Fq_Fp_mul(Fq_sub(s, b, T, p), shifti(addis(p, 1),-1),T, p);
+}
+
+/*
+ * pol is the modular polynomial of level 2 modulo p.
+ *
+ * (T, p) defines the field FF_{p^2} in which j_prev and j live.
+ */
+static long
+path_extends_to_floor(GEN j_prev, GEN j, GEN T, GEN p, GEN Phi2, ulong max_len)
+{
+  pari_sp ltop = avma;
+  GEN Phi2_j;
+  ulong mult, d;
+
+  /* A path made its way to the floor if (i) its length was cut off
+   * before reaching max_path_len, or (ii) it reached max_path_len but
+   * only has one neighbour. */
+  for (d = 1; d < max_len; ++d) {
+    GEN j_next;
+
+    Phi2_j = FqX_div_by_X_x(FqXY_evalx(Phi2, j, T, p), j_prev, T, p, NULL);
+    j_next = FqX_quad_root(Phi2_j, T, p);
+    if (!j_next)
+    { /* j is on the floor */
+      avma = ltop;
+      return 1;
+    }
+
+    j_prev = j; j = j_next;
+    if (gc_needed(ltop, 2))
+      gerepileall(ltop, 2, &j, &j_prev);
+  }
+
+  /* Check that we didn't end up at the floor on the last step (j will
+   * point to the last element in the path. */
+  Phi2_j = FqX_div_by_X_x(FqXY_evalx(Phi2, j, T, p), j_prev, T, p, NULL);
+  mult = FqX_nbroots(Phi2_j, T, p);
+  avma = ltop;
+  return mult == 0;
+}
+
+static int
+jissupersingular(GEN j, GEN S, GEN p)
+{
+  long max_path_len = expi(p)+1;
+  GEN Phi2 = FpXX_red(polmodular_ZXX(2,0,1), p);
+  GEN Phi2_j = FqXY_evalx(Phi2, j, S, p);
+  GEN roots = FqX_roots(Phi2_j, S, p);
+  long nbroots = lg(roots)-1;
+  int res = 1;
+
+  /* Every node in a supersingular L-volcano has L + 1 neighbours. */
+  /* Note: a multiple root only occur when j has CM by sqrt(-15). */
+  if (nbroots==0 || (nbroots==1 && FqX_is_squarefree(Phi2_j, S, p)))
+    res = 0;
+  else {
+    long i, l = lg(roots);
+    for (i = 1; i < l; ++i) {
+      if (path_extends_to_floor(j, gel(roots, i), S, p, Phi2, max_path_len)) {
+        res = 0;
+        break;
+      }
+    }
+  }
+  /* If none of the paths reached the floor, then the j-invariant is
+   * supersingular. */
+  return res;
+}
+
+int
+Fp_elljissupersingular(GEN j, GEN p)
+{
+  pari_sp ltop = avma;
+  long CM;
+  if (cmpiu(p, 5) <= 0) return signe(j) == 0; /* valid if p <= 5 */
+  CM = Fp_ellj_get_CM(j, gen_1, p);
+  if (CM < 0) return krosi(CM, p) < 0; /* valid if p > 3 */
+  else
+  {
+    GEN S = init_Fq(p, 2, fetch_var());
+    int res = jissupersingular(j, S, p);
+    (void)delete_var(); avma = ltop; return res;
+  }
+}
+
+/***********************************************************************/
+/**                                                                   **/
 /**                            Cardinal                               **/
 /**                                                                   **/
 /***********************************************************************/
@@ -635,11 +615,11 @@ _fix(GEN x, long k)
   if (lgefint(y) < k) { GEN p1 = cgeti(k); affii(y,p1); *x = (long)p1; }
 }
 
-/* Return the lift of a (mod b), which is closest to h */
+/* Return the lift of a (mod b), which is closest to c */
 static GEN
-closest_lift(GEN a, GEN b, GEN h)
+closest_lift(GEN a, GEN b, GEN c)
 {
-  return addii(a, mulii(b, diviiround(subii(h,a), b)));
+  return addii(a, mulii(b, diviiround(subii(c,a), b)));
 }
 
 static long
@@ -653,24 +633,61 @@ get_table_size(GEN pordmin, GEN B)
   return itos(t) >> 1;
 }
 
+/* Find x such that kronecker(u = x^3+c4x+c6, p) is KRO.
+ * Return point [x*u,u^2] on E (KRO=1) / E^twist (KRO=-1) */
+static GEN
+Fp_ellpoint(long KRO, ulong *px, GEN c4, GEN c6, GEN p)
+{
+  ulong x = *px;
+  GEN u;
+  for(;;)
+  {
+    x++; /* u = x^3 + c4 x + c6 */
+    u = modii(addii(c6, mului(x, addii(c4, sqru(x)))), p);
+    if (kronecker(u,p) == KRO) break;
+  }
+  *px = x;
+  return mkvec2(modii(mului(x,u),p), Fp_sqr(u,p));
+}
+static GEN
+Fl_ellpoint(long KRO, ulong *px, ulong c4, ulong c6, ulong p)
+{
+  ulong t, u, x = *px;
+  for(;;)
+  {
+    if (++x >= p) pari_err_PRIME("ellap",utoi(p));
+    t = Fl_add(c4, Fl_sqr(x,p), p);
+    u = Fl_add(c6, Fl_mul(x, t, p), p);
+    if (krouu(u,p) == KRO) break;
+  }
+  *px = x;
+  return mkvecsmall2(Fl_mul(x,u,p), Fl_sqr(u,p));
+}
+
+static GEN ap_j1728(GEN a4,GEN p);
 /* compute a_p using Shanks/Mestre + Montgomery's trick. Assume p > 457 */
 static GEN
 Fp_ellcard_Shanks(GEN c4, GEN c6, GEN p)
 {
   pari_timer T;
-  long *tx, *ty, *ti, pfinal, i, j, s, KRO, KROold, nb;
+  long *tx, *ty, *ti, pfinal, i, j, s, KRO, nb;
   ulong x;
   pari_sp av = avma, av2;
-  GEN p1, P, h, mfh, F,f, fh,fg, pordmin, u, v, p1p, p2p, A, B, a4, pts;
+  GEN p1, P, mfh, h, F,f, fh,fg, pordmin, u, v, p1p, p2p, A, B, a4, pts;
   tx = NULL;
   ty = ti = NULL; /* gcc -Wall */
 
+  if (!signe(c6)) {
+    GEN ap = ap_j1728(c4, p);
+    return gerepileuptoint(av, subii(addiu(p,1), ap));
+  }
+
   if (DEBUGLEVEL) timer_start(&T);
   /* once #E(Fp) is know mod B >= pordmin, it is completely determined */
   pordmin = addis(sqrti(gmul2n(p,4)), 1); /* ceil( 4sqrt(p) ) */
   p1p = addsi(1, p);
   p2p = shifti(p1p, 1);
-  x = 0; u = c6; KRO = kronecker(u, p); KROold = - KRO;
+  x = 0; KRO = 0;
   /* how many 2-torsion points ? */
   switch(FpX_nbroots(mkpoln(4, gen_1, gen_0, c4, c6), p))
   {
@@ -678,32 +695,29 @@ Fp_ellcard_Shanks(GEN c4, GEN c6, GEN p)
     case 1:  A = gen_0; B = gen_2; break;
     default: A = gen_1; B = gen_2; break; /* 0 */
   }
-  h = closest_lift(A, B, p1p);
   for(;;)
   {
-    long CODE;
-    while (!KRO || KRO == KROold)
-    { /* look for points alternatively on E and its quadratic twist E' */
-      x++; /* u = x^3 + c4 x + c6 */
-      u = modii(addii(c6, mului(x, addii(c4, sqru(x)))), p);
-      KRO = kronecker(u, p);
+    h = closest_lift(A, B, p1p);
+    if (!KRO) /* first time, initialize */
+    {
+      KRO = kronecker(c6,p);
+      f = mkvec2(gen_0, Fp_sqr(c6,p));
+    }
+    else
+    {
+      KRO = -KRO;
+      f = Fp_ellpoint(KRO, &x, c4,c6,p);
     }
-    KROold = KRO;
     /* [ux, u^2] is on E_u: y^2 = x^3 + c4 u^2 x + c6 u^3
      * E_u isomorphic to E (resp. E') iff KRO = 1 (resp. -1)
      * #E(F_p) = p+1 - a_p, #E'(F_p) = p+1 + a_p
      *
      * #E_u(Fp) = A (mod B),  h is close to #E_u(Fp) */
-
-    f = cgetg(3,t_VEC);
-    gel(f,1) = modii(mului(x,u), p);
-    gel(f,2) = modii(sqri(u),    p);
     a4 = modii(mulii(c4, gel(f,2)), p); /* c4 for E_u */
     fh = FpE_mul(f, h, a4, p);
     if (ell_is_inf(fh)) goto FOUND;
 
     s = get_table_size(pordmin, B);
-    CODE = evaltyp(t_VECSMALL) | evallg(s+1);
     /* look for h s.t f^h = 0 */
     if (!tx)
     { /* first time: initialize */
@@ -712,7 +726,7 @@ Fp_ellcard_Shanks(GEN c4, GEN c6, GEN p)
       ti = ty + (s+1);
     }
     F = FpE_mul(f,B,a4,p);
-    *tx = CODE;
+    *tx = evaltyp(t_VECSMALL) | evallg(s+1);
 
     /* F = B.f */
     P = gcopy(fh);
@@ -855,22 +869,15 @@ Fp_ellcard_Shanks(GEN c4, GEN c6, GEN p)
 FOUND: /* found a point of exponent h on E_u */
     h = FpE_order(f, h, a4, p);
     /* h | #E_u(Fp) = A (mod B) */
-    if (B == gen_1)
-      B = h;
-    else
-      A = Z_chinese_all(A, gen_0, B, h, &B);
-
-    i = (cmpii(B, pordmin) < 0);
-    /* If we are not done, update A mod B for the _next_ curve, isomorphic to
+    A = Z_chinese_all(A, gen_0, B, h, &B);
+    if (cmpii(B, pordmin) >= 0) break;
+    /* not done: update A mod B for the _next_ curve, isomorphic to
      * the quadratic twist of this one */
-    if (i) A = remii(subii(p2p,A), B); /* #E(Fp)+#E'(Fp) = 2p+2 */
-
-    /* h = A mod B, closest lift to p+1 */
-    h = closest_lift(A, B, p1p);
-    if (!i) break;
+    A = remii(subii(p2p,A), B); /* #E(Fp)+#E'(Fp) = 2p+2 */
   }
   if (tx) killblock(tx);
-  return gerepileuptoint(av, KRO==1? h: subii(shifti(p1p,1),h));
+  h = closest_lift(A, B, p1p);
+  return gerepileuptoint(av, KRO==1? h: subii(p2p,h));
 }
 
 typedef struct
@@ -881,55 +888,91 @@ typedef struct
 static int
 compare_multiples(multiple *a, multiple *b) { return a->x > b->x? 1:a->x<b->x?-1:0; }
 
+/* find x such that h := a + b x is closest to c and return h:
+ * x = round((c-a) / b) = floor( (2(c-a) + b) / 2b )
+ * Assume 0 <= a < b < c  and b + 2c < 2^BIL */
+static ulong
+uclosest_lift(ulong a, ulong b, ulong c)
+{
+  ulong x = (b + ((c-a) << 1)) / (b << 1);
+  return a + b * x;
+}
+
 static long
-sclosest_lift(long A, long B, ulong p2p)
+Fle_dbl_inplace(GEN P, ulong a4, ulong p)
 {
-  return A + B * (((ulong)(p2p + B - (A << 1))) / (B << 1));
+  ulong x, y, slope;
+  if (!P[2]) return 1;
+  x = P[1]; y = P[2];
+  slope = Fl_div(Fl_add(Fl_triple(Fl_sqr(x,p), p), a4, p),
+                 Fl_double(y, p), p);
+  P[1] = Fl_sub(Fl_sqr(slope, p), Fl_double(x, p), p);
+  P[2] = Fl_sub(Fl_mul(slope, Fl_sub(x, P[1], p), p), y, p);
+  return 0;
 }
 
-/* assume p > 99 and e has good reduction at p. Should use Montgomery.
- * See Fp_ellcard_Shanks() */
+static long
+Fle_add_inplace(GEN P, GEN Q, ulong a4, ulong p)
+{
+  ulong Px, Py, Qx, Qy, slope;
+  if (ell_is_inf(Q)) return 0;
+  Px = P[1]; Py = P[2];
+  Qx = Q[1]; Qy = Q[2];
+  if (Px==Qx)
+    return Py==Qy ? Fle_dbl_inplace(P, a4, p): 1;
+  slope = Fl_div(Fl_sub(Py, Qy, p), Fl_sub(Px, Qx, p), p);
+  P[1] = Fl_sub(Fl_sub(Fl_sqr(slope, p), Px, p), Qx, p);
+  P[2] = Fl_sub(Fl_mul(slope, Fl_sub(Px, P[1], p), p), Py, p);
+  return 0;
+}
+
+/* assume 99 < p < 2^(BIL-1) - 2^((BIL+1)/2) and e has good reduction at p.
+ * Should use Barett reduction + multi-inverse. See Fp_ellcard_Shanks() */
 static long
 Fl_ellcard_Shanks(ulong c4, ulong c6, ulong p)
 {
   GEN f, fh, fg, ftest, F;
-  ulong x, u, cp4, p1p, p2p, h;
-  long pordmin,A,B;
-  long i, s, KRO, KROold, l, r, m;
+  ulong i, l, r, s, h, x, cp4, p1p, p2p, pordmin,A,B;
+  long KRO;
   pari_sp av = avma;
   multiple *table;
 
-  pordmin = (long)(1 + 4*sqrt((double)p));
+  if (!c6) {
+    GEN ap = ap_j1728(utoi(c4), utoipos(p));
+    avma = av; return p+1 - itos(ap);
+  }
+
+  pordmin = (ulong)(1 + 4*sqrt((double)p));
   p1p = p+1;
   p2p = p1p << 1;
-  x = 0; u = c6; KRO = krouu(u, p); KROold = -KRO;
-
-  switch(Flx_nbroots(mkvecsmalln(5,0, c6,c4,0,1), p))
+  x = 0; KRO = 0;
+  switch(Flx_nbroots(mkvecsmall5(0L, c6,c4,0L,1L), p))
   {
     case 3:  A = 0; B = 4; break;
     case 1:  A = 0; B = 2; break;
     default: A = 1; B = 2; break; /* 0 */
   }
-  h = sclosest_lift(A, B, p2p);
   for(;;)
-  {
-    while (!KRO || KRO == KROold)
+  { /* see comments in Fp_ellcard_Shanks */
+    h = uclosest_lift(A, B, p1p);
+    if (!KRO) /* first time, initialize */
+    {
+      KRO = krouu(c6,p); /* != 0 */
+      f = mkvecsmall2(0, Fl_sqr(c6,p));
+    }
+    else
     {
-      ulong t;
-      if (++x >= p) pari_err_PRIME("ellap",utoi(p));
-      t = Fl_add(c4, Fl_mul(x,x,p), p);
-      u = Fl_add(c6, Fl_mul(x, t, p), p);
-      KRO = krouu(u,p);
+      KRO = -KRO;
+      f = Fl_ellpoint(KRO, &x, c4,c6,p);
     }
-    KROold = KRO;
-    f = mkvecsmall2(Fl_mul(x, u, p), Fl_mul(u, u, p));
     cp4 = Fl_mul(c4, f[2], p);
     fh = Fle_mulu(f, h, cp4, p);
-    s = (long) (sqrt(((double)pordmin)/B) / 2);
+    if (ell_is_inf(fh)) goto FOUND;
+
+    s = (ulong) (sqrt(((double)pordmin)/B) / 2);
     if (!s) s = 1;
     table = (multiple *) stack_malloc((s+1) * sizeof(multiple));
     F = Fle_mulu(f, B, cp4, p);
-    if (ell_is_inf(fh)) goto FOUND;
     for (i=0; i < s; i++)
     {
       table[i].x = fh[1];
@@ -948,39 +991,33 @@ Fl_ellcard_Shanks(ulong c4, ulong c6, ulong p)
       l=0; r=s;
       while (l<r)
       {
-        m = (l+r) >> 1;
-        if (table[m].x < (ulong) ftest[1]) l=m+1; else r=m;
+        ulong m = (l+r) >> 1;
+        if (table[m].x < uel(ftest,1)) l=m+1; else r=m;
       }
-      if (r < s && table[r].x == (ulong) ftest[1]) break;
+      if (r < s && table[r].x == uel(ftest,1)) break;
       if (Fle_add_inplace(ftest, fg, cp4, p))
         pari_err_PRIME("ellap",utoi(p));
     }
     h += table[r].i * B;
-    if (table[r].y == (ulong) ftest[2]) i = -i;
-    h += s * i * B;
-
-FOUND:
-    h = itou(Fle_order(f, utoi(h), cp4, p));
-    if (B == 1) B = h;
+    if (table[r].y == uel(ftest,2))
+      h -= s * i * B;
     else
+      h += s * i * B;
+FOUND:
+    h = itou(Fle_order(f, utoipos(h), cp4, p));
+    /* h | #E_u(Fp) = A (mod B) */
     {
       GEN C;
-      A = itos( Z_chinese_all(gen_0, modss(A,B), utoipos(h), utoipos(B), &C) );
-      if (is_bigint(C)) { h = A; break; }
-      B = itos(C);
-    }
-
-    i = (B < pordmin);
-    if (i)
-    {
-      A = (p2p - A) % B;
-      if ((A << 1) > B) A -= B;
+      A = itou( Z_chinese_all(gen_0, utoi(A), utoipos(h), utoipos(B), &C) );
+      if (cmpiu(C, pordmin) >= 0) { /* uclosest_lift could overflow */
+        h = itou( closest_lift(utoi(A), C, utoipos(p1p)) );
+        break;
+      }
+      B = itou(C);
     }
-    /* h = A mod B, closest lift to p+1 */
-    h = sclosest_lift(A, B, p2p);
-    avma = av; if (!i) break;
+    A = (p2p - A) % B; avma = av;
   }
-  return KRO==1? h: 2*p1p-h;
+  avma = av; return KRO==1? h: p2p-h;
 }
 
 /** ellap from CM (original code contributed by Mark Watkins) **/
@@ -1063,19 +1100,6 @@ ap_cm(int CM, long A6B, GEN a6, GEN p)
   if (kronecker(mulis(a6,A6B), p) < 0) s = -s;
   return s > 0? a: negi(a);
 }
-/* is jn/jd = J (mod p) */
-static int
-is_CMj(long J, GEN jn, GEN jd, GEN p)
-{ return remii(subii(mulis(jd,J), jn), p) == gen_0; }
-#ifndef LONG_IS_64BIT
-/* is jn/jd = -(2^32 a + b) (mod p) */
-static int
-u2_is_CMj(ulong a, ulong b, GEN jn, GEN jd, GEN p)
-{
-  GEN mJ = uu32toi(a,b);
-  return remii(addii(mulii(jd,mJ), jn), p) == gen_0;
-}
-#endif
 static GEN
 ec_ap_cm(int CM, GEN a4, GEN a6, GEN p)
 {
@@ -1097,40 +1121,6 @@ ec_ap_cm(int CM, GEN a4, GEN a6, GEN p)
     default: return NULL;
   }
 }
-long
-Fl_elltrace_CM(int CM, ulong a4, ulong a6, ulong p)
-{
-  pari_sp av = avma;
-  GEN a;
-  if (p < 127) return p+1-Fl_ellcard_naive(a4, a6, p);
-  a = ec_ap_cm(CM, utoi(a4), utoi(a6), utoipos(p));
-  avma = av; return itos(a);
-}
-static GEN
-CM_ellap(GEN a4, GEN a6, GEN jn, GEN jd, GEN p)
-{
-#define CHECK(CM,J) if (is_CMj(J,jn,jd,p)) return ec_ap_cm(CM,a4,a6,p);
-  if (!signe(a4)) return ap_j0(a6,p);
-  if (!signe(a6)) return ap_j1728(a4,p);
-  CHECK(-7,  -3375);
-  CHECK(-8,  8000);
-  CHECK(-12, 54000);
-  CHECK(-11, -32768);
-  CHECK(-16, 287496);
-  CHECK(-19, -884736);
-  CHECK(-27, -12288000);
-  CHECK(-28, 16581375);
-  CHECK(-43, -884736000);
-#ifdef LONG_IS_64BIT
-  CHECK(-67, -147197952000);
-  CHECK(-163, -262537412640768000);
-#else
-  if (u2_is_CMj(0x00000022UL,0x45ae8000UL,jn,jd,p)) return ec_ap_cm(-67,a4,a6,p);
-  if (u2_is_CMj(0x03a4b862UL,0xc4b40000UL,jn,jd,p)) return ec_ap_cm(-163,a4,a6,p);
-#endif
-#undef CHECK
-  return NULL;
-}
 
 static GEN
 Fp_ellj_nodiv(GEN a4, GEN a6, GEN p)
@@ -1151,10 +1141,18 @@ Fp_ellj(GEN a4, GEN a6, GEN p)
 static GEN /* Only compute a mod p, so assume p>=17 */
 Fp_ellcard_CM(GEN a4, GEN a6, GEN p)
 {
-  pari_sp  av = avma;
-  GEN j = Fp_ellj_nodiv(a4, a6, p);
-  GEN a = CM_ellap(a4, a6, gel(j,1), gel(j,2), p);
-  return a ? gerepileupto(av, subii(addis(p,1),a)): NULL;
+  pari_sp av = avma;
+  GEN a;
+  if (!signe(a4)) a = ap_j0(a6,p);
+  else if (!signe(a6)) a = ap_j1728(a4,p);
+  else
+  {
+    GEN j = Fp_ellj_nodiv(a4, a6, p);
+    long CM = Fp_ellj_get_CM(gel(j,1), gel(j,2), p);
+    if (!CM) { avma = av; return NULL; }
+    a = ec_ap_cm(CM,a4,a6,p);
+  }
+  return gerepileuptoint(av, subii(addis(p,1),a));
 }
 
 GEN
@@ -1167,7 +1165,7 @@ Fp_ellcard(GEN a4, GEN a6, GEN p)
   { GEN a = Fp_ellcard_CM(a4,a6,p); if (a) return a; }
   if (lp >= 56)
   { GEN a = Fp_ellcard_SEA(a4, a6, p, 0); if (a) return a; }
-  if (lp <= BITS_IN_LONG-3)
+  if (lp <= BITS_IN_LONG-2)
     return utoi(Fl_ellcard_Shanks(umodiu(a4,pp), umodiu(a6,pp), pp));
   if (lp >= 90) pari_err_PACKAGE("seadata");
   return Fp_ellcard_Shanks(a4, a6, p);
@@ -1176,14 +1174,24 @@ Fp_ellcard(GEN a4, GEN a6, GEN p)
 long
 Fl_elltrace(ulong a4, ulong a6, ulong p)
 {
-  pari_sp av = avma;
-  long lp = expu(p), t;
-  if (lp < 7)
-    return p+1-Fl_ellcard_naive(a4, a6, p);
-  if (lp <= minss(56, BITS_IN_LONG-2))
-    return p+1-Fl_ellcard_Shanks(a4, a6, p);
-  t = itos(subui(p, Fp_ellcard(utoi(a4), utoi(a6), utoi(p)))) + 1;
-  avma = av; return t;
+  pari_sp av;
+  long lp;
+  GEN a;
+  if (p < 127) return p+1-Fl_ellcard_naive(a4, a6, p);
+  lp = expu(p);
+  if (lp <= minss(56, BITS_IN_LONG-2)) return p+1-Fl_ellcard_Shanks(a4, a6, p);
+  av = avma; a = subui(p+1, Fp_ellcard(utoi(a4), utoi(a6), utoipos(p)));
+  avma = av; return itos(a);
+}
+long
+Fl_elltrace_CM(long CM, ulong a4, ulong a6, ulong p)
+{
+  pari_sp av;
+  GEN a;
+  if (!CM) return Fl_elltrace(a4,a6,p);
+  if (p < 127) return p+1-Fl_ellcard_naive(a4, a6, p);
+  av = avma; a = ec_ap_cm(CM, utoi(a4), utoi(a6), utoipos(p));
+  avma = av; return itos(a);
 }
 
 static GEN
@@ -1614,7 +1622,7 @@ FpXQE_tatepairing(GEN P, GEN Q, GEN m, GEN a4, GEN T, GEN p)
 
 /***********************************************************************/
 /**                                                                   **/
-/**                           Point counting                          **/
+/**                           issupersingular                         **/
 /**                                                                   **/
 /***********************************************************************/
 
@@ -1633,11 +1641,55 @@ FpXQ_ellj(GEN a4, GEN a6, GEN T, GEN p)
   }
 }
 
+int
+FpXQ_elljissupersingular(GEN j, GEN T, GEN p)
+{
+  pari_sp ltop = avma;
+
+  /* All supersingular j-invariants are in FF_{p^2}, so we first check
+   * whether j is in FF_{p^2}.  If d is odd, then FF_{p^2} is not a
+   * subfield of FF_{p^d} so the j-invariants are all in FF_p.  Hence
+   * the j-invariants are in FF_{p^{2 - e}}. */
+  ulong d = get_FpX_degree(T);
+  GEN S;
+  int res;
+
+  if (degpol(j) <= 0) return Fp_elljissupersingular(constant_term(j), p);
+  if (cmpiu(p, 5) <= 0) return 0; /* j != 0*/
+
+  /* Set S so that FF_p[T]/(S) is isomorphic to FF_{p^2}: */
+  if (d == 2)
+    S = T;
+  else { /* d > 2 */
+    /* We construct FF_{p^2} = FF_p[t]/((T - j)(T - j^p)) which
+     * injects into FF_{p^d} via the map T |--> j. */
+    GEN j_pow_p = FpXQ_pow(j, p, T, p);
+    GEN j_sum = FpX_add(j, j_pow_p, p), j_prod;
+    long var = varn(T);
+    if (degpol(j_sum) > 0) { avma = ltop; return 0; /* j not in Fp^2 */ }
+    j_prod = FpXQ_mul(j, j_pow_p, T, p);
+    if (degpol(j_prod) > 0 ) { avma = ltop; return 0; /* j not in Fp^2 */ }
+    j_sum = constant_term(j_sum); j_prod = constant_term(j_prod);
+    S = mkpoln(3, gen_1, Fp_neg(j_sum, p), j_prod);
+    setvarn(S, var);
+    j = pol_x(var);
+  }
+  res = jissupersingular(j, S, p);
+  avma = ltop;
+  return res;
+}
+
+/***********************************************************************/
+/**                                                                   **/
+/**                           Point counting                          **/
+/**                                                                   **/
+/***********************************************************************/
+
 GEN
 elltrace_extension(GEN t, long n, GEN q)
 {
   pari_sp av = avma;
-  GEN v = RgX_to_RgV(RgXQ_powu(pol_x(0), n, mkpoln(3,gen_1,negi(t),q)),2);
+  GEN v = RgX_to_RgC(RgXQ_powu(pol_x(0), n, mkpoln(3,gen_1,negi(t),q)),2);
   GEN te = addii(shifti(gel(v,1),1), mulii(t,gel(v,2)));
   return gerepileuptoint(av, te);
 }
diff --git a/src/basemath/FpV.c b/src/basemath/FpV.c
index abf25d8..8d9ee5d 100644
--- a/src/basemath/FpV.c
+++ b/src/basemath/FpV.c
@@ -47,6 +47,19 @@ FpC_center(GEN z, GEN p, GEN pov2)
   return x;
 }
 
+/* assume 0 <= u < p and ps2 = p>>1 */
+INLINE void
+Fp_center_inplace(GEN u, GEN p, GEN ps2)
+{ if (absi_cmp(u,ps2) > 0) subiiz(u,p,u); }
+
+void
+FpC_center_inplace(GEN z, GEN p, GEN ps2)
+{
+  long i,l = lg(z);
+  for (i=1; i<l; i++)
+    Fp_center_inplace(gel(z,i), p, ps2);
+}
+
 GEN
 Flv_center(GEN z, ulong p, ulong ps2)
 {
@@ -74,6 +87,12 @@ FpM_center(GEN z, GEN p, GEN pov2)
   return x;
 }
 
+void
+FpM_center_inplace(GEN z, GEN p, GEN pov2)
+{
+  long i, l = lg(z);
+  for (i=1; i<l; i++) FpC_center_inplace(gel(z,i), p, pov2);
+}
 GEN
 Flm_center(GEN z, ulong p, ulong ps2)
 {
@@ -104,6 +123,16 @@ FpV_add(GEN x, GEN y, GEN p)
   for (i = 1; i < lx; i++) gel(z, i) = Fp_add(gel(x, i), gel(y, i), p);
   return z;
 }
+GEN
+FpM_add(GEN x, GEN y, GEN p)
+{
+  long lx = lg(x), j;
+  GEN z;
+  if (lx == 1) return cgetg(1, t_MAT);
+  z = cgetg(lx, t_MAT);
+  for (j = 1; j < lx; j++) gel(z,j) = FpC_add(gel(x,j), gel(y,j), p);
+  return z;
+}
 
 GEN
 Flv_add(GEN x, GEN y, ulong p)
@@ -190,6 +219,15 @@ Flm_Fl_add(GEN x, ulong y, ulong p)
   return z;
 }
 
+GEN
+Flm_add(GEN x, GEN y, ulong p)
+{
+  long i, l = lg(x);
+  GEN z = cgetg(l,t_MAT);
+  for (i = 1; i < l; i++) gel(z,i) = Flv_add(gel(x,i),gel(y,i),p);
+  return z;
+}
+
 /********************************************************************/
 /**                                                                **/
 /**                           MULTIPLICATION                       **/
@@ -221,6 +259,20 @@ Flc_Fl_div_inplace(GEN x, ulong y, ulong p)
 {
   Flc_Fl_mul_inplace(x, Fl_inv(y, p), p);
 }
+GEN
+FpM_Fp_mul(GEN X, GEN c, GEN p) {
+  long i, j, h, l = lg(X);
+  GEN A = cgetg(l, t_MAT);
+  if (l == 1) return A;
+  h = lgcols(X);
+  for (j=1; j<l; j++)
+  {
+    GEN a = cgetg(h, t_COL), x = gel(X, j);
+    for (i = 1; i < h; i++) gel(a,i) = Fp_mul(gel(x,i), c, p);
+    gel(A,j) = a;
+  }
+  return A;
+}
 
 /* x *= y */
 void
@@ -331,22 +383,29 @@ zm_mul(GEN x, GEN y)
 static ulong
 Flmrow_Flc_mul_SMALL(GEN x, GEN y, ulong p, long lx, long i)
 {
-  ulong c = ucoeff(x,i,1) * y[1];
+  ulong c = ucoeff(x,i,1) * uel(y,1);
   long k;
   for (k = 2; k < lx; k++) {
-    c += ucoeff(x,i,k) * y[k];
+    c += ucoeff(x,i,k) * uel(y,k);
     if (c & HIGHBIT) c %= p;
   }
   return c % p;
 }
+
 static ulong
-Flmrow_Flc_mul(GEN x, GEN y, ulong p, long lx, long i)
-{
-  ulong c = Fl_mul(ucoeff(x,i,1), y[1], p);
-  long k;
-  for (k = 2; k < lx; k++)
-    c = Fl_add(c, Fl_mul(ucoeff(x,i,k), y[k], p), p);
-  return c;
+Flmrow_Flc_mul_i(GEN x, GEN y, ulong p, ulong pi, long lx, long i)
+{
+  ulong l0, l1, v1, h0, h1;
+  long k = 1;
+  LOCAL_OVERFLOW;
+  LOCAL_HIREMAINDER;
+  l1 = mulll(ucoeff(x,i,k), uel(y,k)); h1 = hiremainder; v1 = 0;
+  while (++k < lx) {
+    l0 = mulll(ucoeff(x,i,k), uel(y,k)); h0 = hiremainder;
+    l1 = addll(l0, l1); h1 = addllx(h0, h1); v1 += overflow;
+  }
+  if (v1 == 0) return remll_pre(h1, l1, p, pi);
+  else return remlll_pre(v1, h1, l1, p, pi);
 }
 
 static GEN
@@ -387,11 +446,11 @@ Flm_Flc_mul_i_SMALL(GEN x, GEN y, long lx, long l, ulong p)
   return z;
 }
 static GEN
-Flm_Flc_mul_i(GEN x, GEN y, long lx, long l, ulong p)
+Flm_Flc_mul_i(GEN x, GEN y, long lx, long l, ulong p, ulong pi)
 {
   GEN z = cgetg(l,t_VECSMALL);
   long i;
-  for (i=1; i<l; i++) z[i] = Flmrow_Flc_mul(x, y, p, lx, i);
+  for (i = 1; i < l; i++) z[i] = Flmrow_Flc_mul_i(x, y, p, pi, lx, i);
   return z;
 }
 INLINE GEN
@@ -420,7 +479,7 @@ FpM_mul(GEN x, GEN y, GEN p)
   if (lgefint(p) == 3)
   {
     pari_sp av = avma;
-    ulong pp = (ulong)p[2];
+    ulong pp = uel(p,2);
     if (pp == 2)
     {
       x = ZM_to_F2m(x);
@@ -456,8 +515,9 @@ Flm_mul(GEN x, GEN y, ulong p)
     for (j=1; j<ly; j++)
       gel(z,j) = Flm_Flc_mul_i_SMALL(x, gel(y,j), lx, l, p);
   } else {
+    ulong pi = get_Fl_red(p);
     for (j=1; j<ly; j++)
-      gel(z,j) = Flm_Flc_mul_i(x, gel(y,j), lx, l, p);
+      gel(z,j) = Flm_Flc_mul_i(x, gel(y,j), lx, l, p, pi);
   }
   return z;
 }
@@ -518,7 +578,7 @@ FpM_powu(GEN x, ulong n, GEN p)
   if (lgefint(p) == 3)
   {
     pari_sp av = avma;
-    ulong pp = (ulong)p[2];
+    ulong pp = uel(p,2);
     GEN z;
     if (pp == 2)
       z = F2m_to_ZM(F2m_powu(ZM_to_F2m(x),n));
@@ -568,20 +628,60 @@ FpV_dotsquare(GEN x, GEN p)
   for (i=2; i<lx; i++) c = addii(c, sqri(gel(x,i)));
   return gerepileuptoint(av, modii(c,p));
 }
+
+INLINE ulong
+Flv_dotproduct_SMALL(GEN x, GEN y, ulong p, long lx)
+{
+  ulong c = uel(x,1) * uel(y,1);
+  long k;
+  for (k = 2; k < lx; k++) {
+    c += uel(x,k) * uel(y,k);
+    if (c & HIGHBIT) c %= p;
+  }
+  return c % p;
+}
+
+INLINE ulong
+Flv_dotproduct_i(GEN x, GEN y, ulong p, ulong pi, long lx)
+{
+  ulong l0, l1, v1, h0, h1;
+  long i = 1;
+  LOCAL_OVERFLOW;
+  LOCAL_HIREMAINDER;
+  l1 = mulll(uel(x,i), uel(y,i)); h1 = hiremainder; v1 = 0;
+  while (++i < lx) {
+    l0 = mulll(uel(x,i), uel(y,i)); h0 = hiremainder;
+    l1 = addll(l0, l1); h1 = addllx(h0, h1); v1 += overflow;
+  }
+  if (v1 == 0) return remll_pre(h1, l1, p, pi);
+  else return remlll_pre(v1, h1, l1, p, pi);
+}
+
 ulong
 Flv_dotproduct(GEN x, GEN y, ulong p)
 {
-  long i, lx = lg(x);
-  ulong c;
+  long lx = lg(x);
   if (lx == 1) return 0;
-  c = Fl_mul(x[1], y[1], p);
-  for (i=2; i<lx; i++) c = Fl_add(c, Fl_mul(x[i], y[i], p), p);
-  return c;
+  if (SMALL_ULONG(p))
+    return Flv_dotproduct_SMALL(x, y, p, lx);
+  else
+    return Flv_dotproduct_i(x, y, p, get_Fl_red(p), lx);
+}
+
+ulong
+Flv_dotproduct_pre(GEN x, GEN y, ulong p, ulong pi)
+{
+  long lx = lg(x);
+  if (lx == 1) return 0;
+  if (SMALL_ULONG(p))
+    return Flv_dotproduct_SMALL(x, y, p, lx);
+  else
+    return Flv_dotproduct_i(x, y, p, pi, lx);
 }
+
 ulong
-F2v_dotproduct(GEN x0, GEN y0)
+F2v_dotproduct(GEN x, GEN y)
 {
-  GEN x = x0, y = y0;
   long i, lx = lg(x);
   ulong c;
   if (lx == 2) return 0;
@@ -615,8 +715,21 @@ Flm_Flc_mul(GEN x, GEN y, ulong p)
   else if (SMALL_ULONG(p))
     return Flm_Flc_mul_i_SMALL(x, y, lx, l, p);
   else
-    return Flm_Flc_mul_i(x, y, lx, l, p);
+    return Flm_Flc_mul_i(x, y, lx, l, p, get_Fl_red(p));
 }
+
+GEN
+Flm_Flc_mul_pre(GEN x, GEN y, ulong p, ulong pi)
+{
+  long l, lx = lg(x);
+  if (lx==1) return cgetg(1,t_VECSMALL);
+  l = lgcols(x);
+  if (SMALL_ULONG(p))
+    return Flm_Flc_mul_i_SMALL(x, y, lx, l, p);
+  else
+    return Flm_Flc_mul_i(x, y, lx, l, p, pi);
+}
+
 GEN
 F2m_F2c_mul(GEN x, GEN y)
 {
@@ -765,6 +878,14 @@ ZM_to_Flm(GEN x, ulong p)
   for (j=1; j<n; j++) gel(y,j) = ZV_to_Flv(gel(x,j), p);
   return y;
 }
+GEN
+ZMV_to_FlmV(GEN z, ulong m)
+{
+  long i, l = lg(z);
+  GEN x = cgetg(l,t_VEC);
+  for (i=1; i<l; i++) gel(x,i) = ZM_to_Flm(gel(z,i), m);
+  return x;
+}
 
 /*                          TO INTMOD                        */
 static GEN
@@ -933,7 +1054,7 @@ gen_FpM_Wiedemann(void *E, GEN (*f)(void*, GEN), GEN B, GEN p)
   if (ZV_equal0(B)) return zerocol(n);
   while (++col <= n)
   {
-    pari_sp btop = avma, av, lim;
+    pari_sp btop = avma, av;
     long i, lQ;
     GEN V, Q, M, W = B;
     GEN b = cgetg(m+2, t_POL);
@@ -941,12 +1062,12 @@ gen_FpM_Wiedemann(void *E, GEN (*f)(void*, GEN), GEN B, GEN p)
     gel(b, 2) = gel(W, col);
     for (i = 3; i<m+2; i++)
       gel(b, i) = cgeti(lgefint(p));
-    av = avma; lim = stack_lim(av,1);
+    av = avma;
     for (i = 3; i<m+2; i++)
     {
       W = f(E, W);
       affii(gel(W, col),gel(b, i));
-      if (low_stack(lim, stack_lim(av,2)))
+      if (gc_needed(av,1))
       {
         if (DEBUGMEM>1) pari_warn(warnmem,"Wiedemann: first loop, %ld",i);
         W = gerepileupto(av, W);
@@ -959,12 +1080,12 @@ gen_FpM_Wiedemann(void *E, GEN (*f)(void*, GEN), GEN B, GEN p)
     W = B; lQ =lg(Q);
     if (DEBUGLEVEL) err_printf("Wiedemann: deg. minpoly: %ld\n",lQ-3);
     V = FpC_Fp_mul(W, gel(Q, lQ-2), p);
-    av = avma; lim = stack_lim(av,1);
+    av = avma;
     for (i = lQ-3; i > 1; i--)
     {
       W = f(E, W);
       V = ZC_lincomb(gen_1, gel(Q,i), V, W);
-      if (low_stack(lim, stack_lim(av,2)))
+      if (gc_needed(av,1))
       {
         if (DEBUGMEM>1) pari_warn(warnmem,"Wiedemann: second loop, %ld",i);
         gerepileall(av, 2, &V, &W);
@@ -1059,7 +1180,7 @@ FpV_FpMs_mul(GEN B, GEN M, GEN p) { return FpV_red(ZV_zMs_mul(B, M), p); }
 GEN
 ZlM_gauss(GEN a, GEN b, ulong p, long e, GEN C)
 {
-  pari_sp av = avma, lim = stack_lim(av, 2), av2;
+  pari_sp av = avma, av2;
   GEN xi, xb, pi = gen_1, P;
   long i;
   if (!C) {
@@ -1074,7 +1195,7 @@ ZlM_gauss(GEN a, GEN b, ulong p, long e, GEN C)
   {
     pi = muliu(pi, p); /* = p^(i-1) */
     b = ZM_Z_divexact(ZM_sub(b, ZM_nm_mul(a, xi)), P);
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"ZlM_gauss. i=%ld",i);
       gerepileall(av2,3, &pi,&b,&xb);
@@ -1109,7 +1230,7 @@ GEN
 gen_ZpM_Dixon(void *E, GEN (*f)(void*, GEN), GEN B, GEN p, long e)
 {
   struct wrapper_modp_s W;
-  pari_sp av = avma, lim = stack_lim(av, 2);
+  pari_sp av = avma;
   GEN xb, xi, pi = gen_1;
   long i;
   W.E = E;
@@ -1122,7 +1243,7 @@ gen_ZpM_Dixon(void *E, GEN (*f)(void*, GEN), GEN B, GEN p, long e)
   {
     pi = mulii(pi, p); /* = p^(i-1) */
     B = ZC_Z_divexact(ZC_sub(B, f(E, xi)), p);
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"gen_ZpM_Dixon. i=%ld",i);
       gerepileall(av,3, &pi,&B,&xb);
@@ -1138,7 +1259,7 @@ gen_ZpM_Dixon(void *E, GEN (*f)(void*, GEN), GEN B, GEN p, long e)
 static GEN
 vecprow(GEN A, GEN prow)
 {
-  return mkvec2(vecpermute(prow,gel(A,1)), gel(A,2));
+  return mkvec2(vecsmallpermute(prow,gel(A,1)), gel(A,2));
 }
 
 /* Solve the equation MX = A. Return either a solution as a t_COL,
diff --git a/src/basemath/FpX.c b/src/basemath/FpX.c
index 2138102..a058ccb 100644
--- a/src/basemath/FpX.c
+++ b/src/basemath/FpX.c
@@ -52,7 +52,7 @@ get_FpX_degree(GEN T) { return typ(T)==t_VEC? degpol(gel(T,2)): degpol(T); }
 static ulong
 to_Flx(GEN *P, GEN *Q, GEN p)
 {
-  ulong pp = (ulong)p[2];
+  ulong pp = uel(p,2);
   *P = ZX_to_Flx(*P, pp);
   *Q = ZX_to_Flx(*Q, pp); return pp;
 }
@@ -60,7 +60,7 @@ to_Flx(GEN *P, GEN *Q, GEN p)
 static ulong
 to_Flxq(GEN *P, GEN *T, GEN p)
 {
-  ulong pp = (ulong)p[2];
+  ulong pp = uel(p,2);
   if (P) *P = ZX_to_Flx(*P, pp);
   *T = ZXT_to_FlxT(*T, pp); return pp;
 }
@@ -325,6 +325,29 @@ FpX_Fp_mul_to_monic(GEN y,GEN x,GEN p)
 }
 
 static GEN
+_FpX_sqr(void * E, GEN x) { return FpX_sqr(x, (GEN) E); }
+
+static GEN
+_FpX_mul(void * E, GEN x, GEN y) { return FpX_mul(x, y, (GEN) E); }
+
+GEN
+FpX_powu(GEN x, ulong n, GEN p)
+{
+  if (n==0) return pol_1(varn(x));
+  return gen_powu(x, n, (void *)p, _FpX_sqr, _FpX_mul);
+}
+
+GEN
+FpX_halve(GEN y, GEN p)
+{
+  GEN z;
+  long i, l;
+  z = cgetg_copy(y, &l); z[1] = y[1];
+  for(i=2; i<l; i++) gel(z,i) = Fp_halve(gel(y,i), p);
+  return z;
+}
+
+static GEN
 FpX_divrem_basecase(GEN x, GEN y, GEN p, GEN *pr)
 {
   long vx, dx, dy, dz, i, j, sx, lr;
@@ -438,6 +461,30 @@ FpX_div_by_X_x(GEN a, GEN x, GEN p, GEN *r)
   return z;
 }
 
+static GEN
+_FpX_divrem(void * E, GEN x, GEN y, GEN *r) { return FpX_divrem(x, y, (GEN) E, r); }
+static GEN
+_FpX_add(void * E, GEN x, GEN y) { return FpX_add(x, y, (GEN) E); }
+
+static struct bb_ring FpX_ring = { _FpX_add,_FpX_mul,_FpX_sqr };
+
+GEN
+FpX_digits(GEN x, GEN T, GEN p)
+{
+  pari_sp av = avma;
+  long d = degpol(T), n = (lgpol(x)+d-1)/d;
+  GEN z = gen_digits(x,T,n,(void *)p, &FpX_ring, _FpX_divrem);
+  return gerepileupto(av, z);
+}
+
+GEN
+FpX_fromdigits(GEN x, GEN T, GEN p)
+{
+  pari_sp av = avma;
+  GEN z = gen_fromdigits(x,T,(void *)p, &FpX_ring);
+  return gerepileupto(av, z);
+}
+
 long
 FpX_valrem(GEN x, GEN t, GEN p, GEN *py)
 {
@@ -458,7 +505,7 @@ FpX_valrem(GEN x, GEN t, GEN p, GEN *py)
 static GEN
 FpX_halfgcd_basecase(GEN a, GEN b, GEN p)
 {
-  pari_sp av=avma, lim = stack_lim(av,2);
+  pari_sp av=avma;
   GEN u,u1,v,v1;
   long vx = varn(a);
   long n = lgpol(a)>>1;
@@ -470,7 +517,7 @@ FpX_halfgcd_basecase(GEN a, GEN b, GEN p)
     a = b; b = r; swap(u,u1); swap(v,v1);
     u1 = FpX_sub(u1, FpX_mul(u, q, p), p);
     v1 = FpX_sub(v1, FpX_mul(v, q ,p), p);
-    if (low_stack(lim,stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"FpX_halfgcd (d = %ld)",degpol(b));
       gerepileall(av,6, &a,&b,&u1,&v1,&u,&v);
@@ -580,11 +627,11 @@ FpX_halfgcd(GEN x, GEN y, GEN p)
 static GEN
 FpX_gcd_basecase(GEN a, GEN b, GEN p)
 {
-  pari_sp av = avma, av0=avma, lim = stack_lim(av0,2);
+  pari_sp av = avma, av0=avma;
   while (signe(b))
   {
     GEN c;
-    if (low_stack(lim,stack_lim(av0,2)))
+    if (gc_needed(av0,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"FpX_gcd (d = %ld)",degpol(b));
       gerepileall(av0,2, &a,&b);
@@ -648,7 +695,7 @@ FpX_gcd_check(GEN x, GEN y, GEN p)
 static GEN
 FpX_extgcd_basecase(GEN a, GEN b, GEN p, GEN *ptu, GEN *ptv)
 {
-  pari_sp av=avma, lim = stack_lim(av,2);
+  pari_sp av=avma;
   GEN u,v,d,d1,v1;
   long vx = varn(a);
   d = a; d1 = b;
@@ -659,7 +706,7 @@ FpX_extgcd_basecase(GEN a, GEN b, GEN p, GEN *ptu, GEN *ptv)
     v = FpX_sub(v,FpX_mul(q,v1,p),p);
     u=v; v=v1; v1=u;
     u=r; d=d1; d1=u;
-    if (low_stack(lim,stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"FpX_extgcd (d = %ld)",degpol(d));
       gerepileall(av,5, &d,&d1,&u,&v,&v1);
@@ -818,7 +865,7 @@ GEN
 FpX_resultant(GEN a, GEN b, GEN p)
 {
   long da,db,dc;
-  pari_sp av, lim;
+  pari_sp av;
   GEN c,lb, res = gen_1;
 
   if (!signe(a) || !signe(b)) return gen_0;
@@ -830,7 +877,7 @@ FpX_resultant(GEN a, GEN b, GEN p)
     if (both_odd(da,db)) res = subii(p, res);
   }
   if (!da) return gen_1; /* = res * a[2] ^ db, since 0 <= db <= da = 0 */
-  av = avma; lim = stack_lim(av,2);
+  av = avma;
   while (db)
   {
     lb = gel(b,db+2);
@@ -840,7 +887,7 @@ FpX_resultant(GEN a, GEN b, GEN p)
 
     if (both_odd(da,db)) res = subii(p, res);
     if (!equali1(lb)) res = Fp_mul(res, Fp_powu(lb, da - dc, p), p);
-    if (low_stack(lim,stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"FpX_resultant (da = %ld)",da);
       gerepileall(av,3, &a,&b,&res);
@@ -863,7 +910,6 @@ FpX_disc(GEN x, GEN p)
   return gerepileuptoint(av, D);
 }
 
-static GEN _FpX_mul(void *p,GEN a,GEN b){return FpX_mul(a,b,(GEN)p);}
 GEN
 FpXV_prod(GEN V, GEN p)
 {
@@ -1239,7 +1285,7 @@ FpXQ_div(GEN x,GEN y,GEN T,GEN p)
 }
 
 struct _FpXQ {
-  GEN T, p, mg, aut;
+  GEN T, p, aut;
 };
 
 static GEN
@@ -1355,6 +1401,19 @@ FpXQ_matrix_pow(GEN y, long n, long m, GEN P, GEN l)
 }
 
 GEN
+FpX_Frobenius(GEN T, GEN p)
+{
+  return FpXQ_pow(pol_x(get_FpX_var(T)), p, T, p);
+}
+
+GEN
+FpX_matFrobenius(GEN T, GEN p)
+{
+  long n = get_FpX_degree(T);
+  return FpXQ_matrix_pow(FpX_Frobenius(T, p), n, n, T, p);
+}
+
+GEN
 FpX_FpXQV_eval(GEN Q, GEN x, GEN T, GEN p)
 {
   struct _FpXQ D;
@@ -1380,6 +1439,26 @@ FpX_FpXQ_eval(GEN Q, GEN x, GEN T, GEN p)
 }
 
 GEN
+FpXC_FpXQV_eval(GEN P, GEN x, GEN T, GEN p)
+{
+  long i, l = lg(P);
+  GEN res = cgetg(l, t_COL);
+  for (i=1; i<l; i++)
+    gel(res,i) = FpX_FpXQV_eval(gel(P,i), x, T, p);
+  return res;
+}
+
+GEN
+FpXM_FpXQV_eval(GEN Q, GEN x, GEN T, GEN p)
+{
+  long i, l = lg(Q);
+  GEN y = cgetg(l, t_MAT);
+  for (i=1; i<l; i++)
+    gel(y,i) = FpXC_FpXQV_eval(gel(Q,i), x, T, p);
+  return y;
+}
+
+GEN
 FpXQ_autpowers(GEN aut, long f, GEN T, GEN p)
 {
   pari_sp av = avma;
@@ -1425,13 +1504,14 @@ static GEN
 FpXQ_autsum_mul(void *E, GEN x, GEN y)
 {
   struct _FpXQ *D = (struct _FpXQ*)E;
+  GEN T = D->T, p = D->p;
   GEN phi1 = gel(x,1), a1 = gel(x,2);
   GEN phi2 = gel(y,1), a2 = gel(y,2);
   ulong d = brent_kung_optpow(maxss(degpol(phi1),degpol(a1)),2,1);
-  GEN V2 = FpXQ_powers(phi2,d,D->T,D->p);
-  GEN phi3 = FpX_FpXQV_eval(phi1,V2,D->T,D->p);
-  GEN aphi = FpX_FpXQV_eval(a1,V2,D->T,D->p);
-  GEN a3 = FpXQ_mul(aphi,a2,D->T,D->p);
+  GEN V1 = FpXQ_powers(phi1, d, T, p);
+  GEN phi3 = FpX_FpXQV_eval(phi2, V1, T, p);
+  GEN aphi = FpX_FpXQV_eval(a2, V1, T, p);
+  GEN a3 = FpXQ_mul(a1, aphi, T, p);
   return mkvec2(phi3, a3);
 }
 static GEN
@@ -1446,6 +1526,33 @@ FpXQ_autsum(GEN x, ulong n, GEN T, GEN p)
   return gen_powu(x,n,(void*)&D,FpXQ_autsum_sqr,FpXQ_autsum_mul);
 }
 
+static GEN
+FpXQM_autsum_mul(void *E, GEN x, GEN y)
+{
+  struct _FpXQ *D = (struct _FpXQ*)E;
+  GEN T = D->T, p = D->p;
+  GEN phi1 = gel(x,1), a1 = gel(x,2);
+  GEN phi2 = gel(y,1), a2 = gel(y,2);
+  long g = lg(a2)-1, dT = get_FpX_degree(T);
+  ulong d = brent_kung_optpow(dT-1, g*g+1, 1);
+  GEN V1 = FpXQ_powers(phi1, d, T, p);
+  GEN phi3 = FpX_FpXQV_eval(phi2, V1, T, p);
+  GEN aphi = FpXM_FpXQV_eval(a2, V1, T, p);
+  GEN a3 = FqM_mul(a1, aphi, T, p);
+  return mkvec2(phi3, a3);
+}
+static GEN
+FpXQM_autsum_sqr(void *E, GEN x)
+{ return FpXQM_autsum_mul(E, x, x); }
+
+GEN
+FpXQM_autsum(GEN x, ulong n, GEN T, GEN p)
+{
+  struct _FpXQ D;
+  D.T = FpX_get_red(T, p); D.p = p;
+  return gen_powu(x, n, (void*)&D, FpXQM_autsum_sqr, FpXQM_autsum_mul);
+}
+
 static long
 bounded_order(GEN p, GEN b, long k)
 {
@@ -1519,7 +1626,7 @@ FpXQ_issquare(GEN x, GEN T, GEN p)
   if (lg(x) == 2 || equalui(2, p)) return 1;
   if (lg(x) == 3) return Fq_issquare(gel(x,2), T, p);
   /* Ng = g^((q-1)/(p-1)) */
-  av = avma; res = kronecker(FpX_resultant(T,x,p), p) == 1;
+  av = avma; res = kronecker(FpXQ_norm(x,T,p), p) == 1;
   avma = av; return res;
 }
 int
@@ -1536,29 +1643,6 @@ Fq_issquare(GEN x, GEN T, GEN p)
   return (T && ! odd(get_FpX_degree(T))) || Fp_issquare(x, p);
 }
 
-static GEN
-famat_Z_gcd(GEN M, GEN n)
-{
-  pari_sp av=avma;
-  long i, j, l=lgcols(M);
-  GEN F=cgetg(3,t_MAT);
-  gel(F,1)=cgetg(l,t_COL);
-  gel(F,2)=cgetg(l,t_COL);
-  for (i=1, j=1; i<l; i++)
-  {
-    GEN p = gcoeff(M,i,1);
-    GEN e = gminsg(Z_pval(n,p),gcoeff(M,i,2));
-    if (signe(e))
-    {
-      gcoeff(F,j,1)=p;
-      gcoeff(F,j,2)=e;
-      j++;
-    }
-  }
-  setlg(gel(F,1),j); setlg(gel(F,2),j);
-  return gerepilecopy(av,F);
-}
-
 /* discrete log in FpXQ for a in Fp^*, g in FpXQ^* of order ord */
 GEN
 Fp_FpXQ_log(GEN a, GEN g, GEN o, GEN T, GEN p)
@@ -1623,10 +1707,11 @@ _FpXQ_easylog(void *E, GEN a, GEN g, GEN ord)
 
 static const struct bb_group FpXQ_star={_FpXQ_mul,_FpXQ_pow,_FpXQ_rand,hash_GEN,ZX_equal,ZX_equal1,_FpXQ_easylog};
 
-const struct bb_group *get_FpXQ_star(void **E, GEN T, GEN p)
+const struct bb_group *
+get_FpXQ_star(void **E, GEN T, GEN p)
 {
   struct _FpXQ *e = (struct _FpXQ *) stack_malloc(sizeof(struct _FpXQ));
-  e->T = T; e->p  = p; e->aut =  FpXQ_pow(pol_x(get_FpX_var(T)), p, T, p);
+  e->T = T; e->p  = p; e->aut =  FpX_Frobenius(T, p);
   *E = (void*)e; return &FpXQ_star;
 }
 
@@ -1651,20 +1736,35 @@ FpXQ_order(GEN a, GEN ord, GEN T, GEN p)
 GEN
 FpXQ_log(GEN a, GEN g, GEN ord, GEN T, GEN p)
 {
+  pari_sp av=avma;
   if (lgefint(p)==3)
   {
-    pari_sp av=avma;
     ulong pp = to_Flxq(&a, &T, p);
     GEN z = Flxq_log(a, ZX_to_Flx(g, pp), ord, T, pp);
-    return gerepileuptoint(av,z);
+    return gerepileuptoleaf(av, z);
   }
   else
   {
     void *E;
     const struct bb_group *S = get_FpXQ_star(&E,T,p);
     GEN z = gen_PH_log(a,g,ord,E,S);
-    return z? z: cgetg(1,t_VEC);
+    return gerepileuptoleaf(av, z);
+  }
+}
+GEN
+Fq_log(GEN a, GEN g, GEN ord, GEN T, GEN p)
+{
+  if (!T) return Fp_log(a,g,ord,p);
+  if (typ(g) == t_INT)
+  {
+    if (typ(a) == t_POL)
+    {
+      if (degpol(a)) return cgetg(1,t_VEC);
+      a = gel(a,2);
+    }
+    return Fp_log(a,g,ord,p);
   }
+  return typ(a) == t_INT? Fp_FpXQ_log(a,g,ord,T,p): FpXQ_log(a,g,ord,T,p);
 }
 
 GEN
@@ -1734,13 +1834,13 @@ GEN
 FpXQ_charpoly(GEN x, GEN T, GEN p)
 {
   pari_sp ltop=avma;
-  long v;
+  long vT, v = fetch_var();
   GEN R;
   T = leafcopy(get_FpX_mod(T));
-  v = varn(T); setvarn(T, MAXVARN);
-  x = leafcopy(x); setvarn(x, MAXVARN);
-  R = FpX_FpXY_resultant(T, deg1pol_shallow(gen_1,FpX_neg(x,p),v),p);
-  return gerepileupto(ltop,R);
+  vT = varn(T); setvarn(T, v);
+  x = leafcopy(x); setvarn(x, v);
+  R = FpX_FpXY_resultant(T, deg1pol_shallow(gen_1,FpX_neg(x,p),vT),p);
+  (void)delete_var(); return gerepileupto(ltop,R);
 }
 
 GEN
@@ -1766,9 +1866,9 @@ FpXQ_conjvec(GEN x, GEN T, GEN p)
   pari_sp av=avma;
   long i;
   long n = get_FpX_degree(T), v = varn(x);
-  GEN M = FpXQ_matrix_pow(FpXQ_pow(pol_x(v),p,T,p),n,n,T,p);
+  GEN M = FpX_matFrobenius(T, p);
   GEN z = cgetg(n+1,t_COL);
-  gel(z,1) = RgX_to_RgV(x,n);
+  gel(z,1) = RgX_to_RgC(x,n);
   for (i=2; i<=n; i++) gel(z,i) = FpM_FpC_mul(M,gel(z,i-1),p);
   gel(z,1) = x;
   for (i=2; i<=n; i++) gel(z,i) = RgV_to_RgX(gel(z,i),v);
@@ -1785,7 +1885,7 @@ gener_FpXQ_i(GEN T, GEN p, GEN p_1, GEN Lp, GEN Lq)
 {
   pari_sp av;
   long vT = varn(T), f = degpol(T), l = lg(Lq);
-  GEN F = FpXQ_pow(pol_x(vT), p, T, p); /* Frobenius */
+  GEN F = FpX_Frobenius(T, p);
   int p_is_2 = is_pm1(p_1);
   for (av = avma;; avma = av)
   {
diff --git a/src/basemath/FpXX.c b/src/basemath/FpXX.c
index 5811b1d..0e0ff80 100644
--- a/src/basemath/FpXX.c
+++ b/src/basemath/FpXX.c
@@ -26,7 +26,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 static ulong
 to_FlxqX(GEN P, GEN Q, GEN T, GEN p, GEN *pt_P, GEN *pt_Q, GEN *pt_T)
 {
-  ulong pp = (ulong)p[2];
+  ulong pp = uel(p,2);
   long v = get_FpX_var(T);
   *pt_P = ZXX_to_FlxX(P, pp, v);
   if (pt_Q) *pt_Q = ZXX_to_FlxX(Q, pp, v);
@@ -207,6 +207,10 @@ ZXX_mul_Kronecker(GEN x, GEN y, long n)
 { return ZX_mul(ZXX_to_Kronecker(x,n), ZXX_to_Kronecker(y,n)); }
 
 GEN
+ZXX_sqr_Kronecker(GEN x, long n)
+{ return ZX_sqr(ZXX_to_Kronecker(x,n)); }
+
+GEN
 FpXQX_red(GEN z, GEN T, GEN p)
 {
   long i, l = lg(z);
@@ -255,10 +259,11 @@ static GEN
 FpXY_FpY_mulspec(GEN x, GEN y, GEN T, GEN p, long lx, long ly)
 {
   pari_sp av = avma;
-  GEN z = RgXY_swapspec(x,get_FpX_degree(T)-1,MAXVARN,lx);
-  z = FpXX_FpX_mulspec(z,y,p,MAXVARN,ly);
+  long v = fetch_var();
+  GEN z = RgXY_swapspec(x,get_FpX_degree(T)-1,v,lx);
+  z = FpXX_FpX_mulspec(z,y,p,v,ly);
   z = RgXY_swapspec(z+2,lx+ly+3,get_FpX_var(T),lgpol(z));
-  return gerepilecopy(av,z);
+  (void)delete_var(); return gerepilecopy(av,z);
 }
 
 static GEN
@@ -733,12 +738,53 @@ FpXQX_rem(GEN x, GEN y, GEN T, GEN p)
   }
 }
 
+/* x + y*z mod p */
+INLINE GEN
+Fq_addmul(GEN x, GEN y, GEN z, GEN T, GEN p)
+{
+  pari_sp av;
+  if (!signe(y) || !signe(z)) return Fq_red(x, T, p);
+  if (!signe(x)) return Fq_mul(z,y, T, p);
+  av = avma;
+  return gerepileupto(av, Fq_add(x, Fq_mul(y, z, T, p), T, p));
+}
+
+GEN
+FpXQX_div_by_X_x(GEN a, GEN x, GEN T, GEN p, GEN *r)
+{
+  long l = lg(a)-1, i;
+  GEN z = cgetg(l, t_POL);
+  z[1] = evalsigne(1) | evalvarn(0);
+  gel(z, l-1) = gel(a,l);
+  for (i=l-2; i>1; i--) /* z[i] = a[i+1] + x*z[i+1] */
+    gel(z, i) = Fq_addmul(gel(a,i+1), x, gel(z,i+1), T, p);
+  if (r) *r = Fq_addmul(gel(a,2), x, gel(z,2), T, p);
+  return z;
+}
+
 struct _FpXQX { GEN T,p; };
+
 static GEN _FpXQX_mul(void *data, GEN a,GEN b)
 {
   struct _FpXQX *d=(struct _FpXQX*)data;
   return FpXQX_mul(a,b,d->T,d->p);
 }
+
+static GEN _FpXQX_sqr(void *data, GEN a)
+{
+  struct _FpXQX *d=(struct _FpXQX*)data;
+  return FpXQX_sqr(a, d->T, d->p);
+}
+
+GEN
+FpXQX_powu(GEN x, ulong n, GEN T, GEN p)
+{
+  struct _FpXQX D;
+  if (n==0) return pol_1(varn(x));
+  D.T = T; D.p = p;
+  return gen_powu(x, n, (void *)&D, _FpXQX_sqr, _FpXQX_mul);
+}
+
 GEN
 FpXQXV_prod(GEN V, GEN T, GEN p)
 {
@@ -760,6 +806,45 @@ FpXQXV_prod(GEN V, GEN T, GEN p)
   }
 }
 
+static GEN
+_FpXQX_divrem(void * E, GEN x, GEN y, GEN *r)
+{
+  struct _FpXQX *d = (struct _FpXQX *) E;
+  return FpXQX_divrem(x, y, d->T, d->p, r);
+}
+
+static GEN
+_FpXQX_add(void * E, GEN x, GEN y)
+{
+  struct _FpXQX *d = (struct _FpXQX *) E;
+  return FpXX_add(x, y, d->p);
+}
+
+static struct bb_ring FpXQX_ring = { _FpXQX_add, _FpXQX_mul, _FpXQX_sqr };
+
+GEN
+FpXQX_digits(GEN x, GEN B, GEN T, GEN p)
+{
+  pari_sp av = avma;
+  long d = degpol(B), n = (lgpol(x)+d-1)/d;
+  GEN z;
+  struct _FpXQX D;
+  D.T = T; D.p = p;
+  z = gen_digits(x, B, n, (void *)&D, &FpXQX_ring, _FpXQX_divrem);
+  return gerepileupto(av, z);
+}
+
+GEN
+FpXQX_fromdigits(GEN x, GEN B, GEN T, GEN p)
+{
+  pari_sp av = avma;
+  struct _FpXQX D;
+  GEN z;
+  D.T = T; D.p = p;
+  z = gen_fromdigits(x,B,(void *)&D, &FpXQX_ring);
+  return gerepileupto(av, z);
+}
+
 /* Q an FpXY (t_POL with FpX coeffs), evaluate at X = x */
 GEN
 FpXY_evalx(GEN Q, GEN x, GEN p)
@@ -781,14 +866,12 @@ FpXY_evaly(GEN Q, GEN y, GEN p, long vx)
   pari_sp av = avma;
   long i, lb = lg(Q);
   GEN z;
-  if (lb == 2) return pol_0(vx);
-  z = gel(Q, lb-1);
-  if (lb == 3) return typ(z)==t_INT? scalar_ZX(z, vx): ZX_copy(z);
-  if (!signe(y)) {
+  if (!signe(Q)) return pol_0(vx);
+  if (lb == 3 || !signe(y)) {
     z = gel(Q, 2);
     return typ(z)==t_INT? scalar_ZX(z, vx): ZX_copy(z);
   }
-
+  z = gel(Q, lb-1);
   if (typ(z) == t_INT) z = scalar_ZX_shallow(z, vx);
   for (i=lb-2; i>=2; i--) z = Fq_add(gel(Q,i), FpX_Fp_mul(z, y, p), NULL, p);
   return gerepileupto(av, z);
@@ -802,16 +885,26 @@ FpXY_eval(GEN Q, GEN y, GEN x, GEN p)
 }
 
 GEN
-FpXY_FpXQ_evalx(GEN P, GEN x, GEN T, GEN p)
+FpXY_FpXQV_evalx(GEN P, GEN x, GEN T, GEN p)
 {
   long i, lP = lg(P);
   GEN res = cgetg(lP,t_POL);
   res[1] = P[1];
   for(i=2; i<lP; i++)
-    gel(res,i) = FpX_FpXQ_eval(gel(P,i), x, T, p);
+    gel(res,i) = typ(gel(P,i))==t_INT? icopy(gel(P,i)):
+                                       FpX_FpXQV_eval(gel(P,i), x, T, p);
   return FlxX_renormalize(res, lP);
 }
 
+GEN
+FpXY_FpXQ_evalx(GEN P, GEN x, GEN T, GEN p)
+{
+  pari_sp av = avma;
+  long n = brent_kung_optpow(get_FpX_degree(T)-1,lgpol(P),1);
+  GEN xp = FpXQ_powers(x, n, T, p);
+  return gerepileupto(av, FpXY_FpXQV_evalx(P, xp, T, p));
+}
+
 /*******************************************************************/
 /*                                                                 */
 /*                       (Fp[X]/T(X))[Y] / S(Y)                    */
@@ -1020,25 +1113,31 @@ FpXQX_FpXQXQ_eval(GEN Q, GEN x, GEN S, GEN T, GEN p)
 }
 
 static GEN
-FpXQXQ_autpow_sqr(void * T, GEN x)
+FpXQXQ_autpow_sqr(void * E, GEN x)
 {
-  FpXQXQ_muldata *D = (FpXQXQ_muldata *)T;
+  FpXQXQ_muldata *D = (FpXQXQ_muldata *)E;
+  GEN T = D->T, p = D->p;
   GEN phi = gel(x,1), S = gel(x,2);
-  GEN phi2 = FpX_FpXQ_eval(phi,phi,D->T,D->p);
-  GEN Sphi = FpXY_FpXQ_evalx(S,phi,D->T,D->p);
-  GEN S2 = FpXQX_FpXQXQ_eval(Sphi, S, D->S,D->T,D->p);
+  long n = brent_kung_optpow(get_FpX_degree(T)-1,lgpol(S)+1,1);
+  GEN V = FpXQ_powers(phi, n, T, p);
+  GEN phi2 = FpX_FpXQV_eval(phi, V, T, p);
+  GEN Sphi = FpXY_FpXQV_evalx(S, V, T, p);
+  GEN S2 = FpXQX_FpXQXQ_eval(Sphi, S, D->S, T, p);
   return mkvec2(phi2, S2);
 }
 
 static GEN
-FpXQXQ_autpow_mul(void * T, GEN x, GEN y)
+FpXQXQ_autpow_mul(void * E, GEN x, GEN y)
 {
-  FpXQXQ_muldata *D = (FpXQXQ_muldata *)T;
+  FpXQXQ_muldata *D = (FpXQXQ_muldata *)E;
+  GEN T = D->T, p = D->p;
   GEN phi1 = gel(x,1), S1 = gel(x,2);
   GEN phi2 = gel(y,1), S2 = gel(y,2);
-  GEN phi3 = FpX_FpXQ_eval(phi1,phi2,D->T,D->p);
-  GEN Sphi = FpXY_FpXQ_evalx(S1,phi2,D->T,D->p);
-  GEN S3 = FpXQX_FpXQXQ_eval(Sphi, S2, D->S,D->T,D->p);
+  long n = brent_kung_optpow(get_FpX_degree(T)-1, lgpol(S1)+1, 1);
+  GEN V = FpXQ_powers(phi2, n, T, p);
+  GEN phi3 = FpX_FpXQV_eval(phi1, V, T, p);
+  GEN Sphi = FpXY_FpXQV_evalx(S1, V, T, p);
+  GEN S3 = FpXQX_FpXQXQ_eval(Sphi, S2, D->S, T, p);
   return mkvec2(phi3, S3);
 }
 
@@ -1051,19 +1150,22 @@ FpXQXQV_autpow(GEN aut, long n, GEN S, GEN T, GEN p)
 }
 
 static GEN
-FpXQXQ_autsum_mul(void * T, GEN x, GEN y)
+FpXQXQ_autsum_mul(void *E, GEN x, GEN y)
 {
-  FpXQXQ_muldata *D = (FpXQXQ_muldata *)T;
+  FpXQXQ_muldata *D = (FpXQXQ_muldata *) E;
+  GEN T = D->T, p = D->p;
   GEN phi1 = gel(x,1), S1 = gel(x,2), a1 = gel(x,3);
   GEN phi2 = gel(y,1), S2 = gel(y,2), a2 = gel(y,3);
-  GEN phi3 = FpX_FpXQ_eval(phi1,phi2,D->T,D->p);
-  GEN Sphi = FpXY_FpXQ_evalx(S1,phi2,D->T,D->p);
+  long n2 = brent_kung_optpow(get_FpX_degree(T)-1, lgpol(S1)+lgpol(a1)+1, 1);
+  GEN V2 = FpXQ_powers(phi2, n2, T, p);
+  GEN phi3 = FpX_FpXQV_eval(phi1, V2, T, p);
+  GEN Sphi = FpXY_FpXQV_evalx(S1, V2, T, p);
+  GEN aphi = FpXY_FpXQV_evalx(a1, V2, T, p);
   long n = brent_kung_optpow(degpol(D->S)-1,2,1);
-  GEN V = FpXQXQ_powers(S2, n, D->S,D->T,D->p);
-  GEN S3 = FpXQX_FpXQXQV_eval(Sphi, V, D->S,D->T,D->p);
-  GEN aphi = FpXY_FpXQ_evalx(a1,phi2,D->T,D->p);
-  GEN aS = FpXQX_FpXQXQV_eval(aphi,V,D->S,D->T,D->p);
-  GEN a3 = FpXQXQ_mul(aS,a2,D->S,D->T,D->p);
+  GEN V = FpXQXQ_powers(S2, n, D->S, T, p);
+  GEN S3 = FpXQX_FpXQXQV_eval(Sphi, V, D->S, T, p);
+  GEN aS = FpXQX_FpXQXQV_eval(aphi, V, D->S, T, p);
+  GEN a3 = FpXQXQ_mul(aS,a2,D->S, T, p);
   return mkvec3(phi3, S3, a3);
 }
 
diff --git a/src/basemath/FpX_factor.c b/src/basemath/FpX_factor.c
index dc2e97c..b13fd0b 100644
--- a/src/basemath/FpX_factor.c
+++ b/src/basemath/FpX_factor.c
@@ -252,7 +252,7 @@ FpX_quad_factortype(GEN x, GEN p)
 GEN
 FpX_quad_root(GEN x, GEN p, int unknown)
 {
-  GEN s, u, D, b = gel(x,3), c = gel(x,2);
+  GEN s, D, b = gel(x,3), c = gel(x,2);
 
   if (equaliu(p, 2)) {
     if (!signe(b)) return c;
@@ -265,17 +265,11 @@ FpX_quad_root(GEN x, GEN p, int unknown)
   s = Fp_sqrt(D,p);
   /* p is not prime, go on and give e.g. maxord a chance to recover */
   if (!s) return NULL;
-  u = addis(shifti(p,-1), 1); /* = 1/2 */
-  return Fp_mul(u, subii(s,b), p);
+  return Fp_halve(Fp_sub(s,b, p), p);
 }
 static GEN
 FpX_otherroot(GEN x, GEN r, GEN p)
-{
-  GEN s = addii(gel(x,3), r);
-  if (!signe(s)) return s;
-  s = subii(p, s); if (signe(s) < 0) s = addii(s,p);
-  return s;
-}
+{ return Fp_neg(Fp_add(gel(x,3), r, p), p); }
 
 /* disc(x^2+bx+c) = b^2 - 4c */
 static ulong
@@ -285,13 +279,12 @@ Fl_disc_bc(ulong b, ulong c, ulong p)
 static ulong
 Flx_quad_root(GEN x, ulong p, int unknown)
 {
-  ulong s, u, b = x[3], c = x[2];
+  ulong s, b = x[3], c = x[2];
   ulong D = Fl_disc_bc(b, c, p);
   if (unknown && krouu(D,p) == -1) return p;
   s = Fl_sqrt(D,p);
   if (s==~0UL) return p;
-  u = (p>>1)+1;
-  return Fl_mul(u, Fl_sub(s,b, p), p);
+  return Fl_halve(Fl_sub(s,b, p), p);
 }
 static ulong
 Flx_otherroot(GEN x, ulong r, ulong p)
@@ -304,8 +297,8 @@ struct split_t { GEN todo, done; };
 static void
 split_init(struct split_t *S, long max)
 {
-  S->done = vectrunc_init(max);
   S->todo = vectrunc_init(max);
+  S->done = vectrunc_init(max);
 }
 #if 0
 /* move todo[i] to done */
@@ -362,8 +355,8 @@ FpX_roots_i(GEN f, GEN p)
   if (ZX_valrem(f, &f)) split_add_done(&S, gen_0);
   switch(degpol(f))
   {
-    case 0: return S.done;
-    case 1: split_add_done(&S, subii(p, gel(f,2))); return S.done;
+    case 0: return ZC_copy(S.done);
+    case 1: split_add_done(&S, subii(p, gel(f,2))); return ZC_copy(S.done);
     case 2: {
       GEN s, r = FpX_quad_root(f, p, 1);
       if (r) {
@@ -380,7 +373,7 @@ FpX_roots_i(GEN f, GEN p)
   if (lg(a) < 3) pari_err_PRIME("rootmod",p);
   a = FpX_Fp_sub_shallow(a, gen_1, p); /* a = x^(p-1) - 1 mod f */
   a = FpX_gcd(f,a, p);
-  if (!degpol(a)) return S.done;
+  if (!degpol(a)) return ZC_copy(S.done);
   split_add(&S, FpX_normalize(a,p));
 
   q = shifti(p,-1);
@@ -420,9 +413,58 @@ FpX_roots_i(GEN f, GEN p)
     }
   }
 }
+
+/* Assume f is normalized */
+static ulong
+Flx_cubic_root(GEN ff, ulong p)
+{
+  GEN f = Flx_normalize(ff,p);
+  ulong pi = get_Fl_red(p);
+  ulong a = f[4], b=f[3], c=f[2], p3 = p%3==1 ? (2*p+1)/3 :(p+1)/3;
+  ulong t = Fl_mul_pre(a, p3, p, pi), t2 = Fl_sqr_pre(t, p, pi);
+  ulong A = Fl_sub(b, Fl_triple(t2, p), p);
+  ulong B = Fl_add(Fl_mul_pre(t, Fl_sub(Fl_double(t2, p), b, p), p ,pi), c, p);
+  ulong A3 =  Fl_mul_pre(A, p3, p, pi);
+  ulong A32 = Fl_sqr_pre(A3, p, pi), A33 = Fl_mul_pre(A3, A32, p, pi);
+  ulong S = Fl_neg(B,p), P = Fl_neg(A3,p);
+  ulong D = Fl_add(Fl_sqr_pre(S, p, pi), Fl_double(Fl_double(A33, p), p), p);
+  ulong s = Fl_sqrt_pre(D, p, pi), vS1, vS2;
+  if (s!=~0UL)
+  {
+    ulong S1 = S==s ? S: Fl_halve(Fl_sub(S, s, p), p);
+    if (p%3==2) /* 1 solutions */
+      vS1 = Fl_powu_pre(S1, (2*p-1)/3, p, pi);
+    else
+    {
+      vS1 = Fl_sqrtl_pre(S1, 3, p, pi);
+      if (vS1==~0UL) return p; /*0 solutions*/
+      /*3 solutions*/
+    }
+    vS2 = P? Fl_mul_pre(P, Fl_inv(vS1, p), p, pi): 0;
+    return Fl_sub(Fl_add(vS1,vS2, p), t, p);
+  }
+  else
+  {
+    pari_sp av = avma;
+    GEN S1 = mkvecsmall2(Fl_halve(S, p), Fl_halve(1UL, p));
+    GEN vS1 = Fl2_sqrtn_pre(S1, utoi(3), D, p, pi, NULL);
+    ulong Sa;
+    if (!vS1) return p; /*0 solutions, p%3==2*/
+    Sa = vS1[1];
+    if (p%3==1) /*1 solutions*/
+    {
+      ulong Fa = Fl2_norm_pre(vS1, D, p, pi);
+      if (Fa!=P)
+        Sa = Fl_mul(Sa, Fl_div(Fa, P, p),p);
+    }
+    avma = av;
+    return Fl_sub(Fl_double(Sa,p),t,p);
+  }
+}
+
 /* assume p > 2 prime */
 static ulong
-Flx_oneroot_i(GEN f, ulong p)
+Flx_oneroot_i(GEN f, ulong p, long fl)
 {
   GEN pol, a;
   ulong q;
@@ -433,12 +475,16 @@ Flx_oneroot_i(GEN f, ulong p)
   {
     case 1: return Fl_neg(f[2], p);
     case 2: return Flx_quad_root(f, p, 1);
+    case 3: if (p>3) return Flx_cubic_root(f, p); /*FALL THROUGH*/
   }
 
-  a = Flxq_powu(polx_Flx(f[1]), p - 1, f,p);
-  if (lg(a) < 3) pari_err_PRIME("rootmod",utoipos(p));
-  a = Flx_Fl_add(a, p-1, p); /* a = x^(p-1) - 1 mod f */
-  a = Flx_gcd(f,a, p);
+  if (!fl)
+  {
+    a = Flxq_powu(polx_Flx(f[1]), p - 1, f,p);
+    if (lg(a) < 3) pari_err_PRIME("rootmod",utoipos(p));
+    a = Flx_Fl_add(a, p-1, p); /* a = x^(p-1) - 1 mod f */
+    a = Flx_gcd(f,a, p);
+  } else a = f;
   da = degpol(a);
   if (!da) return p;
   a = Flx_normalize(a,p);
@@ -452,6 +498,7 @@ Flx_oneroot_i(GEN f, ulong p)
     {
       case 1: return Fl_neg(a[2], p);
       case 2: return Flx_quad_root(a, p, 0);
+      case 3: if (p>3) return Flx_cubic_root(a, p); /*FALL THROUGH*/
       default: {
         GEN b = Flx_Fl_add(Flxq_powu(pol,q, a,p), p-1, p);
         long db;
@@ -471,6 +518,7 @@ Flx_oneroot_i(GEN f, ulong p)
     }
   }
 }
+
 /* assume p > 2 prime */
 static GEN
 FpX_oneroot_i(GEN f, GEN p)
@@ -534,7 +582,22 @@ Flx_oneroot(GEN f, ulong p)
     case 3: avma = av; return p;
   }
   if (p == 2) return Flx_oneroot_mod_2(f);
-  r = Flx_oneroot_i(Flx_normalize(f, p), p);
+  r = Flx_oneroot_i(Flx_normalize(f, p), p, 0);
+  avma = av; return r;
+}
+
+ulong
+Flx_oneroot_split(GEN f, ulong p)
+{
+  pari_sp av = avma;
+  ulong r;
+  switch(lg(f))
+  {
+    case 2: return 0;
+    case 3: avma = av; return p;
+  }
+  if (p == 2) return Flx_oneroot_mod_2(f);
+  r = Flx_oneroot_i(Flx_normalize(f, p), p, 1);
   avma = av; return r;
 }
 
@@ -554,7 +617,7 @@ FpX_oneroot(GEN f, GEN pp) {
     if (p == 2)
       r = Flx_oneroot_mod_2(f);
     else
-      r = Flx_oneroot_i(f, p);
+      r = Flx_oneroot_i(f, p, 0);
     avma = av;
     return (r == p)? NULL: utoi(r);
   }
@@ -577,8 +640,7 @@ FpX_Berlekamp_ker(GEN u, GEN p)
 {
   pari_sp ltop=avma;
   long j,N = degpol(u);
-  GEN XP = FpXQ_pow(pol_x(varn(u)),p,u,p);
-  GEN Q  = FpXQ_matrix_pow(XP,N,N,u,p);
+  GEN Q  = FpX_matFrobenius(u, p);
   for (j=1; j<=N; j++)
     gcoeff(Q,j,j) = Fp_sub(gcoeff(Q,j,j), gen_1, p);
   return gerepileupto(ltop, FpM_ker(Q,p));
@@ -607,11 +669,10 @@ Flx_Berlekamp_ker(GEN u, ulong l)
 {
   pari_sp ltop=avma;
   long j,N = degpol(u);
-  GEN Q, XP;
+  GEN Q;
   pari_timer T;
   timer_start(&T);
-  XP = Flxq_powu(polx_Flx(u[1]),l,u,l);
-  Q  = Flxq_matrix_pow(XP,N,N,u,l);
+  Q  = Flx_matFrobenius(u, l);
   for (j=1; j<=N; j++)
     coeff(Q,j,j) = Fl_sub(coeff(Q,j,j),1,l);
   if(DEBUGLEVEL>=9) timer_printf(&T,"Berlekamp matrix");
@@ -621,15 +682,14 @@ Flx_Berlekamp_ker(GEN u, ulong l)
 }
 
 /* product of terms of degree 1 in factorization of f */
-static GEN
+GEN
 FpX_split_part(GEN f, GEN p)
 {
   long n = degpol(f);
   GEN z, X = pol_x(varn(f));
   if (n <= 1) return f;
   f = FpX_red(f, p);
-  z = FpXQ_pow(X, p, f, p);
-  z = FpX_sub(z, X, p);
+  z = FpX_sub(FpX_Frobenius(f, p), X, p);
   return FpX_gcd(z,f,p);
 }
 
@@ -648,13 +708,10 @@ FpX_is_totally_split(GEN f, GEN p)
 {
   long n=degpol(f);
   pari_sp av = avma;
-  GEN z;
   if (n <= 1) return 1;
   if (cmpui(n, p) > 0) return 0;
   f = FpX_red(f, p);
-  z = FpXQ_pow(pol_x(varn(f)), p, f, p);
-  avma = av;
-  return degpol(z) == 1 && gequal1(gel(z,3)) && !signe(gel(z,2)); /* x^p = x ? */
+  avma = av; return gequalX(FpX_Frobenius(f, p));
 }
 
 /* Flv_Flx( Flm_Flc_mul(x, Flx_Flv(y), p) ) */
@@ -717,9 +774,8 @@ Flx_nbfact_by_degree(GEN z, long *nb, ulong p)
   long lgg, d = 0, e = degpol(z);
   GEN D = zero_zv(e);
   pari_sp av = avma;
-  GEN g, w,  PolX = polx_Flx(z[1]);
-  GEN XP = Flxq_powu(PolX,p,z,p);
-  GEN MP = Flxq_matrix_pow(XP,e,e,z,p);
+  GEN g, w, PolX = polx_Flx(z[1]);
+  GEN MP = Flx_matFrobenius(z, p);
 
   w = PolX; *nb = 0;
   while (d < (e>>1))
@@ -758,11 +814,16 @@ Flx_nbroots(GEN f, ulong p)
 {
   long n = degpol(f);
   pari_sp av = avma;
-  GEN z, X;
+  GEN z;
   if (n <= 1) return n;
-  X = polx_Flx(f[1]);
-  z = Flxq_powu(X, p, f, p);
-  z = Flx_sub(z, X, p);
+  if (n == 2)
+  {
+    ulong D;
+    if (p==2) return (f[2]==0) + (f[2]!=f[3]);
+    D = Fl_sub(Fl_sqr(f[3], p), Fl_mul(Fl_mul(f[4], f[2], p), 4%p, p), p);
+    return 1 + krouu(D,p);
+  }
+  z = Flx_sub(Flx_Frobenius(f, p), polx_Flx(f[1]), p);
   z = Flx_gcd(z, f, p);
   avma = av; return degpol(z);
 }
@@ -801,7 +862,7 @@ Flx_try_pow(GEN w0, GEN pol, ulong p, GEN q, long r)
     w2 = Flxq_sqr(w,pol,p);
     if (Flx_equal1(w2)) break;
   }
-  return degpol(w)==0 && (ulong)w[2] == p-1 ? NULL: w;
+  return degpol(w)==0 && uel(w,2) == p-1 ? NULL: w;
 }
 
 /* INPUT:
@@ -1077,12 +1138,33 @@ static GEN
 Flx_roots_i(GEN f, ulong p)
 {
   GEN pol, g;
-  ulong q = p >> 1;
+  long v = Flx_valrem(f, &g);
+  ulong q;
   struct split_t S;
 
+  /* optimization: test for small degree first */
+  switch(degpol(g))
+  {
+    case 1: {
+      ulong r = p - g[2];
+      return v? mkvecsmall2(0, r): mkvecsmall(r);
+    }
+    case 2: {
+      ulong r = Flx_quad_root(g, p, 1), s;
+      if (r == p) return v? mkvecsmall(0): cgetg(1,t_VECSMALL);
+      s = Flx_otherroot(g,r, p);
+      if (r < s)
+        return v? mkvecsmall3(0, r, s): mkvecsmall2(r, s);
+      else if (r > s)
+        return v? mkvecsmall3(0, s, r): mkvecsmall2(s, r);
+      else
+        return v? mkvecsmall2(0, s): mkvecsmall(s);
+    }
+  }
+  q = p >> 1;
   split_init(&S, lg(f)-1);
   settyp(S.done, t_VECSMALL);
-  if (Flx_valrem(f, &g)) split_add_done(&S, (GEN)0);
+  if (v) split_add_done(&S, (GEN)0);
   if (! split_Flx_cut_out_roots(&S, g, p))
     return all_roots_mod_p(p, lg(S.done) == 1);
   pol = polx_Flx(f[1]);
@@ -1455,7 +1537,7 @@ FpX_factcantor_i(GEN f, GEN pp, long flag)
 
     /* here u is square-free (product of irred. of multiplicity e * k) */
     v=X;
-    S = du==1 ?  cgetg(1, t_VEC): FpXQ_powers(FpXQ_pow(v, pp, u, pp), du-1, u, pp);
+    S = du==1 ?  cgetg(1, t_VEC): FpXQ_powers(FpX_Frobenius(u, pp), du-1, u, pp);
     for (d=1; d <= du>>1; d++)
     {
       v = FpX_FpXQV_eval(v, S, u, pp);
@@ -1528,14 +1610,14 @@ factmod_aux(GEN f, GEN p, GEN (*Factor)(GEN,GEN,long), long flag)
   if (flag)
     for (j=1; j<nbfact; j++)
     {
-      gel(u,j) = utoi((ulong)t[j]);
-      gel(v,j) = utoi((ulong)E[j]);
+      gel(u,j) = utoi(uel(t,j));
+      gel(v,j) = utoi(uel(E,j));
     }
   else
     for (j=1; j<nbfact; j++)
     {
       gel(u,j) = FpX_to_mod(gel(t,j), p);
-      gel(v,j) = utoi((ulong)E[j]);
+      gel(v,j) = utoi(uel(E,j));
     }
   return gerepileupto(av, y);
 }
@@ -2133,7 +2215,7 @@ to_Fq_fact(GEN P, GEN E, GEN T, GEN p, pari_sp av)
   for (j=1; j<l; j++)
   {
     gel(u,j) = simplify_shallow(gel(P,j)); /* may contain pols of degree 0 */
-    gel(v,j) = utoi((ulong)E[j]);
+    gel(v,j) = utoi(uel(E,j));
   }
   y = gerepilecopy(av, mkmat2(u, v));
   u = gel(y,1);
@@ -2162,7 +2244,7 @@ GEN
 FlxqXQ_halfFrobenius(GEN a, GEN S, GEN T, ulong p)
 {
   long vT = get_Flx_var(T);
-  GEN xp = Flxq_powu(polx_Flx(vT), p, T, p);
+  GEN xp = Flx_Frobenius(T, p);
   GEN Xp = FlxqXQ_pow(polx_FlxX(varn(S), vT), utoi(p), S, T, p);
   GEN ap2 = FlxqXQ_pow(a,utoi(p>>1), S, T, p);
   GEN V = FlxqXQV_autsum(mkvec3(xp, Xp, ap2), get_Flx_degree(T), S, T, p);
@@ -2181,7 +2263,7 @@ FpXQXQ_halfFrobenius(GEN a, GEN S, GEN T, GEN p)
   }
   else
   {
-    GEN xp = FpXQ_pow(pol_x(get_FpX_var(T)), p, T, p);
+    GEN xp = FpX_Frobenius(T, p);
     GEN Xp = FpXQXQ_pow(pol_x(varn(S)), p, S, T, p);
     GEN ap2 = FpXQXQ_pow(a,shifti(p,-1), S, T, p);
     GEN V = FpXQXQV_autsum(mkvec3(xp,Xp,ap2), get_FpX_degree(T), S, T, p);
@@ -2195,7 +2277,7 @@ FlxqX_Frobenius(GEN S, GEN T, ulong p)
   pari_sp av = avma;
   long n = get_Flx_degree(T), vT = get_Flx_var(T);
   GEN X  = polx_FlxX(varn(S), vT);
-  GEN xp = Flxq_powu(polx_Flx(vT), p, T, p);
+  GEN xp = Flx_Frobenius(T, p);
   GEN Xp = FlxqXQ_pow(X, utoi(p), S, T, p);
   GEN Xq = gel(FlxqXQV_autpow(mkvec2(xp,Xp), n, S, T, p), 2);
   return gerepilecopy(av, Xq);
@@ -2207,7 +2289,7 @@ FpXQX_Frobenius(GEN S, GEN T, GEN p)
   pari_sp av = avma;
   long n = get_FpX_degree(T);
   GEN X  = pol_x(varn(S));
-  GEN xp = FpXQ_pow(pol_x(get_FpX_var(T)), p, T, p);
+  GEN xp = FpX_Frobenius(T, p);
   GEN Xp = FpXQXQ_pow(X, p, S, T, p);
   GEN Xq = gel(FpXQXQV_autpow(mkvec2(xp,Xp), n, S, T, p), 2);
   return gerepilecopy(av, Xq);
@@ -2455,7 +2537,7 @@ FqX_frob_deflate(GEN f, GEN T, GEN p)
 static GEN
 FqX_split_Trager(GEN A, GEN T, GEN p)
 {
-  GEN c, P, u, fa, n;
+  GEN c = NULL, P, u, fa, n;
   long lx, i, k;
 
   u = A;
@@ -2637,7 +2719,7 @@ F2xqX_quad_roots(GEN P, GEN T)
 static GEN
 FqX_quad_roots(GEN x, GEN T, GEN p)
 {
-  GEN s, u, D, nb, b = gel(x,3), c = gel(x,2);
+  GEN s, D, nb, b = gel(x,3), c = gel(x,2);
   if (equaliu(p, 2))
   {
     GEN f2 = ZXX_to_F2xX(x, get_FpX_var(T));
@@ -2645,13 +2727,12 @@ FqX_quad_roots(GEN x, GEN T, GEN p)
     return F2xC_to_ZXC(s);
   }
   D = Fq_sub(Fq_sqr(b,T,p), Fq_Fp_mul(c,utoi(4),T,p), T,p);
-  u = addis(shifti(p,-1), 1); /* = 1/2 */
   nb = Fq_neg(b,T,p);
   if (signe(D)==0)
-    return mkcol(Fq_Fp_mul(nb,u,T, p));
+    return mkcol(Fq_halve(nb,T, p));
   s = Fq_sqrt(D,T,p);
   if (!s) return cgetg(1, t_COL);
-  s = Fq_Fp_mul(Fq_add(s,nb,T,p),u,T, p);
+  s = Fq_halve(Fq_add(s,nb,T,p),T, p);
   return mkcol2(s,Fq_sub(nb,s,T,p));
 }
 
@@ -2763,6 +2844,27 @@ FqX_factor_i(GEN f, GEN T, GEN p)
   T = FpX_normalize(T, p);
   f = FqX_normalize(f, T, p);
   if (isabsolutepol(f)) return FpX_factorff_i(simplify_shallow(f), T, p);
+  if (degpol(f)==2)
+  {
+    long v = varn(f);
+    GEN r = FqX_quad_roots(f,T,p);
+    switch(lg(r)-1)
+    {
+    case 0:
+      return mkvec2(mkcolcopy(f), mkvecsmall(1));
+    case 1:
+      return mkvec2(mkcol(deg1pol_shallow(gen_1, Fq_neg(gel(r,1), T, p), v)),
+                    mkvecsmall(2));
+    case 2:
+      {
+        GEN f1 = deg1pol_shallow(gen_1, Fq_neg(gel(r,1), T, p), v);
+        GEN f2 = deg1pol_shallow(gen_1, Fq_neg(gel(r,2), T, p), v);
+        t = mkcol2(f1, f2); E = mkvecsmall2(1, 1);
+        sort_factor_pol(mkvec2(t, E), cmp_RgX);
+        return mkvec2(t, E);
+      }
+    }
+  }
 
   pg = itos_or_0(p);
   df2  = NULL; /* gcc -Wall */
diff --git a/src/basemath/Hensel.c b/src/basemath/Hensel.c
index 997a9f2..daee59a 100644
--- a/src/basemath/Hensel.c
+++ b/src/basemath/Hensel.c
@@ -288,11 +288,11 @@ MultiLift(GEN f, GEN a, GEN T, GEN p, long e0, long flag)
         else
           Td = FpX_red(T, peold);
         Tnew = FpX_red(T, penew);
-        ZpXQ_RecTreeLift(link, v, w, Td, Tnew, pd, peold, penew, f, lgpol(v),
+        ZpXQ_RecTreeLift(link, v, w, Td, Tnew, pd, peold, penew, f, lg(v)-2,
                          (flag == 0 && mask == 1));
       }
       else
-        ZpX_RecTreeLift(link, v, w, pd, peold, penew, f, lgpol(v),
+        ZpX_RecTreeLift(link, v, w, pd, peold, penew, f, lg(v)-2,
                         (flag == 0 && mask == 1));
       if (DEBUGLEVEL > 3) timer_printf(&Ti, "lifting to prec %ld", enew);
     }
@@ -361,7 +361,7 @@ bezout_lift_fact(GEN pol, GEN Q, GEN p, long e)
   link = gel(E,2);
   v    = gel(E,3);
   w    = gel(E,4);
-  BezoutPropagate(link, v, w, pe, NULL, pol, lgpol(v));
+  BezoutPropagate(link, v, w, pe, NULL, pol, lg(v)-2);
   E = cgetg(k+1, t_VEC);
   for (i = 1; i <= 2*k-2; i++)
   {
@@ -404,9 +404,47 @@ polhensellift(GEN pol, GEN L, GEN p, long N)
   return gerepilecopy(av, ZpX_liftfact(pol, L, T, p, N, powiu(p,N)));
 }
 
-/*************************************************************************/
-/*                             rootpadicfast                             */
-/*************************************************************************/
+static GEN
+ZpX_liftroots_full(GEN f, GEN S, GEN p, long e)
+{
+  long i, n = lg(S)-1;
+  GEN r = cgetg(n+1, typ(S));
+  pari_sp av = avma;
+  long v = varn(f);
+  GEN y, q;
+  for (i=1; i<=n; i++)
+    gel(r,i) = deg1pol(gen_1, Fp_neg(gel(S, i), p), v);
+  q = powiu(p, e);
+  y = ZpX_liftfact(f, r, NULL, p, e, q);
+  r = cgetg(n+1 ,t_COL);
+  for (i=1; i<=n; i++)
+    gel(r,i) = Fp_neg(gmael(y, i, 2), q);
+  return gerepileupto(av, r);
+}
+
+GEN
+ZpX_roots(GEN F, GEN p, long e)
+{
+  pari_sp av = avma;
+  long i, v = varn(F);
+  GEN y, r, q;
+  GEN f = FpX_normalize(F, p);
+  GEN g = FpX_normalize(FpX_split_part(f, p), p);
+  GEN S = FpX_roots(g, p);
+  long l = lg(S)-1, n = l < degpol(f)? l+1: l;
+  if (l==0) return cgetg(1, t_COL);
+  if (l==1) return mkcol(ZpX_liftroot(F,gel(S,1),p,e));
+  r = cgetg(n+1 ,t_COL);
+  for (i=1; i<=l; i++)
+    gel(r,i) = deg1pol_shallow(gen_1, Fp_neg(gel(S,i), p), v);
+  if (l < degpol(f)) gel(r, n) = FpX_div(f, g, p);
+  q = powiu(p, e);
+  y = ZpX_liftfact(F, r, NULL, p, e, q);
+  r = cgetg(l+1 ,t_COL);
+  for (i=1; i<=l; i++) gel(r,i) = Fp_neg(gmael(y,i,2), q);
+  return gerepileupto(av, r);
+}
+
 /* SPEC:
  * p is a t_INT > 1, e >= 1
  * f is a ZX with leading term prime to p.
@@ -438,21 +476,32 @@ ZpX_liftroot(GEN f, GEN a, GEN p, long e)
 }
 
 GEN
+ZpX_liftroots(GEN f, GEN S, GEN p, long e)
+{
+  long i, n = lg(S)-1, d = degpol(f);
+  GEN r;
+  if (n == d) return ZpX_liftroots_full(f, S, p, e);
+  r = cgetg(n+1, typ(S));
+  for (i=1; i <= n; i++)
+    gel(r,i) = ZpX_liftroot(f, gel(S,i), p, e);
+  return r;
+}
+
+GEN
 ZpXQX_liftroot_vald(GEN f, GEN a, long v, GEN T, GEN p, long e)
 {
-  pari_sp av = avma, av2, lim;
-  GEN pv = p, q, qv, W, df, Tq, fr, dfr;
+  pari_sp av = avma, av2;
+  GEN pv = p, q, W, df, Tq, fr, dfr;
   ulong mask;
   a = Fq_red(a, T, p);
   if (e <= v+1) return a;
   df = RgX_deriv(f);
-  if (v) { pv = powiu(p,v); qv = mulii(pv,p); df = ZXX_Z_divexact(df, pv); }
-  else qv = p;
+  if (v) { pv = powiu(p,v); df = ZXX_Z_divexact(df, pv); }
   mask = quadratic_prec_mask(e-v);
-  Tq = FpXT_red(T, qv); dfr = FpXQX_red(df, Tq, p);
+  Tq = FpXT_red(T, p); dfr = FpXQX_red(df, Tq, p);
   W = Fq_inv(FqX_eval(dfr, a, Tq, p), Tq, p); /* 1/f'(a) mod (T,p) */
   q = p;
-  av2 = avma; lim = stack_lim(av2, 2);
+  av2 = avma;
   for (;;)
   {
     GEN u, fa, qv, q2v, q2, Tq2;
@@ -470,7 +519,7 @@ ZpXQX_liftroot_vald(GEN f, GEN a, long v, GEN T, GEN p, long e)
     dfr = FpXQX_red(df, Tq, q);
     u = ZX_Z_divexact(FpX_Fp_sub(Fq_mul(W,FqX_eval(dfr,a,Tq,q),Tq,q),gen_1,q),q2);
     W = Fq_sub(W,ZX_Z_mul(Fq_mul(u,W,Tq2,q2),q2),Tq,q);
-    if (low_stack(lim, stack_lim(av2,2)))
+    if (gc_needed(av2,2))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"ZpXQX_liftroot, e = %ld", e);
       gerepileall(av2, 3, &a, &W, &q);
@@ -481,82 +530,18 @@ ZpXQX_liftroot_vald(GEN f, GEN a, long v, GEN T, GEN p, long e)
 GEN
 ZpXQX_liftroot(GEN f, GEN a, GEN T, GEN p, long e) { return ZpXQX_liftroot_vald(f,a,0,T,p,e); }
 
-/* Apply ZpX_liftroot to all roots in S and trace trick.
- * Elements of S must be distinct simple roots mod p for all p|q. */
-GEN
-ZpX_liftroots(GEN f, GEN S, GEN q, long e)
-{
-  long i, d, l = lg(S), n = l-1;
-  GEN y = cgetg(l, typ(S));
-  if (!n) return y;
-  for (i=1; i<n; i++)
-    gel(y,i) = ZpX_liftroot(f, gel(S,i), q, e);
-  d = degpol(f);
-  if (n != d) /* not totally split*/
-    gel(y,n) = ZpX_liftroot(f, gel(S,n), q, e);
-  else
-  { /* totally split: use trace trick */
-    pari_sp av = avma;
-    GEN z = gel(f, d+1);/* -trace(roots) */
-    for(i=1; i<n;i++) z = addii(z, gel(y,i));
-    z = modii(negi(z), powiu(q,e));
-    gel(y,n) = gerepileuptoint(av,z);
-  }
-  return y;
-}
-
-/* Same as ZpX_liftroot for the polynomial X^2-b */
-GEN
-Zp_sqrtlift(GEN b, GEN a, GEN p, long e)
-{
-  pari_sp ltop=avma;
-  GEN q, w;
-  ulong mask;
-
-  if (e == 1) return icopy(a);
-  mask = quadratic_prec_mask(e);
-  w = Fp_inv(modii(shifti(a,1), p), p);
-  q = p;
-  for(;;)
-  {
-    q = sqri(q);
-    if (mask & 1) q = diviiexact(q, p);
-    mask >>= 1;
-    if (lgefint(q) == 3)
-    {
-      ulong Q = (ulong)q[2];
-      ulong A = umodiu(a, Q);
-      ulong B = umodiu(b, Q);
-      ulong W = umodiu(w, Q);
-      A = Fl_sub(A, Fl_mul(W, Fl_sub(Fl_sqr(A,Q), B, Q), Q), Q);
-      a = utoi(A);
-      if (mask == 1) break;
-      W = Fl_sub(Fl_add(W,W,Q), Fl_mul(Fl_sqr(W,Q), Fl_add(A,A,Q),Q), Q);
-      w = utoi(W);
-    }
-    else
-    {
-      a = modii(subii(a, mulii(w, subii(Fp_sqr(a,q),b))), q);
-      if (mask == 1) break;
-      w = subii(shifti(w,1), Fp_mul(Fp_sqr(w,q), shifti(a,1),q));
-    }
-  }
-  return gerepileuptoint(ltop,a);
-}
-/* Same as ZpX_liftroot for the polynomial X^n-b
- * TODO: generalize to sparse polynomials. */
+/* Same as ZpX_liftroot for the polynomial X^n-b*/
 GEN
 Zp_sqrtnlift(GEN b, GEN n, GEN a, GEN p, long e)
 {
   pari_sp ltop=avma;
   GEN q, w, n_1;
   ulong mask;
-
-  if (equalii(n, gen_2)) return Zp_sqrtlift(b,a,p,e);
+  long pis2 = equalii(n, gen_2)? 1: 0;
   if (e == 1) return icopy(a);
   n_1 = subis(n,1);
   mask = quadratic_prec_mask(e);
-  w = Fp_inv(Fp_mul(n,Fp_pow(a,n_1,p), p), p);
+  w = Fp_inv(pis2 ? shifti(a,1): Fp_mul(n,Fp_pow(a,n_1,p), p), p);
   q = p;
   for(;;)
   {
@@ -565,7 +550,7 @@ Zp_sqrtnlift(GEN b, GEN n, GEN a, GEN p, long e)
     mask >>= 1;
     if (lgefint(q) == 3 && lgefint(n) == 3)
     {
-      ulong Q = (ulong)q[2], N = (ulong)n[2];
+      ulong Q = uel(q,2), N = uel(n,2);
       ulong A = umodiu(a, Q);
       ulong B = umodiu(b, Q);
       ulong W = umodiu(w, Q);
@@ -583,12 +568,31 @@ Zp_sqrtnlift(GEN b, GEN n, GEN a, GEN p, long e)
       a = modii(subii(a, mulii(w, subii(Fp_pow(a,n,q),b))), q);
       if (mask == 1) break;
       /* w += w - w^2 n a^(n-1)*/
-      w = subii(shifti(w,1), Fp_mul(Fp_sqr(w,q), mulii(n,Fp_pow(a,n_1,q)), q));
+      w = subii(shifti(w,1), Fp_mul(Fp_sqr(w,q),
+                           pis2? shifti(a,1): mulii(n,Fp_pow(a,n_1,q)), q));
     }
   }
   return gerepileuptoint(ltop,a);
 }
 
+
+/* Same as ZpX_liftroot for the polynomial X^2-b */
+GEN
+Zp_sqrtlift(GEN b, GEN a, GEN p, long e)
+{
+  return Zp_sqrtnlift(b, gen_2, a, p, e);
+}
+
+GEN
+Zp_sqrt(GEN x, GEN p, long e)
+{
+  pari_sp av = avma;
+  GEN z = Fp_sqrt(Fp_red(x, p), p);
+  if (!z) return NULL;
+  if (e > 1) z = Zp_sqrtlift(x, z, p, e);
+  return gerepileuptoint(av, z);
+}
+
 /* Compute (x-1)/(x+1)/p^k */
 static GEN
 ZpXQ_log_to_ath(GEN x, long k, GEN T, GEN p, long e, GEN pe)
@@ -687,13 +691,13 @@ gen_ZpX_Newton(GEN x, GEN p, long n, void *E,
                       GEN eval(void *E, GEN f, GEN q),
                       GEN invd(void *E, GEN V, GEN v, GEN q, long M))
 {
-  pari_sp ltop = avma, av, st_lim;
+  pari_sp ltop = avma, av;
   long N = 1, N2, M;
   long mask;
   GEN q = p;
   if (n == 1) return gcopy(x);
   mask = quadratic_prec_mask(n);
-  av = avma; st_lim = stack_lim(av, 1);
+  av = avma;
   while (mask > 1)
   {
     GEN qM, q2, v, V;
@@ -713,7 +717,7 @@ gen_ZpX_Newton(GEN x, GEN p, long n, void *E,
     v = eval(E, x, q);
     V = ZX_Z_divexact(gel(v,1), q2);
     x = FpX_sub(x, ZX_Z_mul(invd(E, V, v, qM, M), q2), q);
-    if (low_stack(st_lim, stack_lim(av, 1)))
+    if (gc_needed(av, 1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"gen_ZpX_Newton");
       gerepileall(av, 2, &x, &q);
@@ -798,3 +802,84 @@ ZpXQ_sqrtnlift(GEN a, GEN n, GEN x, GEN T, GEN p, long e)
   d.ai = ZpXQ_inv(ZX_Z_mul(a, n),T,p,(e+1)>>1);
   return gen_ZpX_Newton(x, p, e, &d, _sqrtn_eval, _sqrtn_invd);
 }
+
+GEN
+ZpXQ_sqrt(GEN a, GEN T, GEN p, long e)
+{
+  pari_sp av = avma;
+  GEN z = FpXQ_sqrt(FpX_red(a, p), T, p);
+  if (!z) return NULL;
+  if (e <= 1) return gerepileupto(av, z);
+  return gerepileupto(av, ZpXQ_sqrtnlift(a, gen_2, z, T, p, e));
+}
+
+GEN
+ZpX_ZpXQ_liftroot_ea(GEN P, GEN S, GEN T, GEN p, long n, void *E,
+                     int early(void *E, GEN x, GEN q))
+{
+  pari_sp ltop = avma, av;
+  long N, r;
+  long mask;
+  GEN q2, q, W, Q, Tq2, Tq, Pq;
+  pari_timer ti;
+  T = FpX_get_red(T, powiu(p, n));
+  if (n == 1) return gcopy(S);
+  mask = quadratic_prec_mask(n);
+  av = avma;
+  q2 = p; q = sqri(p); mask >>= 1; N = 2;
+  if (DEBUGLEVEL > 3) timer_start(&ti);
+  Tq = FpXT_red(T,q);
+  Tq2 = FpXT_red(Tq,q2);
+  Pq = FpX_red(P,q);
+  W = FpXQ_inv(FpX_FpXQ_eval(FpX_deriv(P,q2), S, Tq2, q2), Tq2, q2);
+  Q  = ZX_Z_divexact(FpX_FpXQ_eval(Pq, S, Tq, q), q2);
+  r = brent_kung_optpow(degpol(P), 4, 3);
+  for (;;)
+  {
+    GEN H, Sq, Wq, Spow, dP, qq, Pqq, Tqq;
+    H  = FpXQ_mul(W, Q, Tq2, q2);
+    Sq = FpX_sub(S, ZX_Z_mul(H, q2), q);
+    if (DEBUGLEVEL > 3)
+      timer_printf(&ti,"ZpX_ZpXQ_liftroot: lift to prec %ld",N);
+    if (mask==1 || (early && early(E, Sq, q)))
+      return gerepileupto(ltop, Sq);
+    qq = sqri(q); N <<= 1;
+    if (mask&1UL) { qq = diviiexact(qq, p); N--; }
+    mask >>= 1;
+    Pqq  = FpX_red(P, qq);
+    Tqq  = FpXT_red(T, qq);
+    Spow = FpXQ_powers(Sq, r, Tqq, qq);
+    Q  = ZX_Z_divexact(FpX_FpXQV_eval(Pqq, Spow, Tqq, qq), q);
+    dP = FpX_FpXQV_eval(FpX_deriv(Pq, q), FpXV_red(Spow, q), Tq, q);
+    Wq = ZX_Z_divexact(FpX_Fp_sub(FpXQ_mul(W, dP, Tq, q), gen_1, q), q2);
+    Wq = ZX_Z_mul(FpXQ_mul(W, Wq, Tq2, q2), q2);
+    Wq = FpX_sub(W, Wq, q);
+    S = Sq; W = Wq; q2 = q; q = qq; Tq2 = Tq; Tq = Tqq; Pq = Pqq;
+    if (gc_needed(av, 1))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"ZpX_ZpXQ_Newton");
+      gerepileall(av, 8, &S, &W, &Q, &Tq2, &Tq, &Pq, &q, &q2);
+    }
+  }
+}
+
+GEN
+ZpX_ZpXQ_liftroot(GEN P, GEN S, GEN T, GEN p, long n)
+{
+  return ZpX_ZpXQ_liftroot_ea(P, S, T, p, n, NULL, NULL);
+}
+
+GEN
+ZpX_Frobenius(GEN T, GEN p, long e)
+{
+  return ZpX_ZpXQ_liftroot(get_FpX_mod(T), FpX_Frobenius(T, p), T, p, e);
+}
+
+GEN
+ZpXQM_prodFrobenius(GEN M, GEN T, GEN p, long e)
+{
+  pari_sp av = avma;
+  GEN xp = ZpX_Frobenius(T, p, e);
+  GEN z = FpXQM_autsum(mkvec2(xp, M), get_FpX_degree(T), T, powiu(p,e));
+  return gerepilecopy(av, gel(z,2));
+}
diff --git a/src/basemath/QX_factor.c b/src/basemath/QX_factor.c
index 2efb912..2d24409 100644
--- a/src/basemath/QX_factor.c
+++ b/src/basemath/QX_factor.c
@@ -209,11 +209,11 @@ cmbf(GEN pol, GEN famod, GEN bound, GEN p, long a, long b,
         T1 = Fp_mul(lc, T1, pa);
         T2 = Fp_mul(lc2,T2, pa);
       }
-      trace1[i] = itou(diviiround(T1, pb));
-      trace2[i] = itou(diviiround(T2, pb));
+      uel(trace1,i) = itou(diviiround(T1, pb));
+      uel(trace2,i) = itou(diviiround(T2, pb));
     }
-    spa_b   = (ulong)  pa_b[2]; /* < 2^31 */
-    spa_bs2 = (ulong)pa_bs2[2]; /* < 2^31 */
+    spa_b   = uel(pa_b,2); /* < 2^31 */
+    spa_bs2 = uel(pa_bs2,2); /* < 2^31 */
   }
   degsofar[0] = 0; /* sentinel */
 
@@ -240,8 +240,8 @@ nextK:
       ulong t;
 
       /* d - 1 test */
-      for (t=trace1[ind[1]],i=2; i<=K; i++)
-        t = Fl_add(t, trace1[ind[i]], spa_b);
+      for (t=uel(trace1,ind[1]),i=2; i<=K; i++)
+        t = Fl_add(t, uel(trace1,ind[i]), spa_b);
       if (t > spa_bs2) t = spa_b - t;
       if (t > Sbound)
       {
@@ -249,8 +249,8 @@ nextK:
         goto NEXT;
       }
       /* d - 2 test */
-      for (t=trace2[ind[1]],i=2; i<=K; i++)
-        t = Fl_add(t, trace2[ind[i]], spa_b);
+      for (t=uel(trace2,ind[1]),i=2; i<=K; i++)
+        t = Fl_add(t, uel(trace2,ind[i]), spa_b);
       if (t > spa_bs2) t = spa_b - t;
       if (t > Sbound)
       {
@@ -302,8 +302,8 @@ nextK:
         else
         {
           gel(famod,k) = gel(famod,i);
-          trace1[k] = trace1[i];
-          trace2[k] = trace2[i];
+          uel(trace1,k) = uel(trace1,i);
+          uel(trace2,k) = uel(trace2,i);
           deg[k] = deg[i]; k++;
         }
       }
@@ -389,7 +389,7 @@ root_bound(GEN P0)
   /* P0 = lP x^d + Q, deg Q < d */
   Q = normalizepol_lg(Q, d+2);
   for (k=lg(Q)-1; k>1; k--) gel(Q,k) = absi(gel(Q,k));
-  k = (long)(cauchy_bound(P0) / LOG2);
+  k = (long)(fujiwara_bound(P0));
   for (  ; k >= 0; k--)
   {
     pari_sp av = avma;
@@ -529,7 +529,7 @@ LLL_cmbf(GEN P, GEN famod, GEN p, GEN pa, GEN bound, long a, long rec)
   double logp = log((double)itos(p)), LOGp2 = LOG2/logp;
   double b0 = log((double)dP*2) / logp, logBr;
   GEN lP, Br, Bnorm, Tra, T2, TT, CM_L, m, list, ZERO;
-  pari_sp av, av2, lim;
+  pari_sp av, av2;
   long ti_LLL = 0, ti_CF  = 0;
 
   lP = absi(leading_term(P));
@@ -543,7 +543,7 @@ LLL_cmbf(GEN P, GEN famod, GEN p, GEN pa, GEN bound, long a, long rec)
   Bnorm = dbltor(n0 * (C*C + N0*n0/4.) * 1.00001);
   ZERO = zeromat(n0, N0);
 
-  av = avma; lim = stack_lim(av, 1);
+  av = avma;
   TT = cgetg(n0+1, t_VEC);
   Tra  = cgetg(n0+1, t_MAT);
   for (i=1; i<=n0; i++)
@@ -665,7 +665,7 @@ AGAIN:
       if (DEBUGLEVEL>2) err_printf("LLL_cmbf: chk_factors failed");
     }
     CM_L = gerepilecopy(av2, CM_L);
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"LLL_cmbf");
       gerepileall(av, 5, &CM_L, &TT, &Tra, &famod, &pa);
@@ -792,10 +792,10 @@ pick_prime(GEN a, long fl, pari_timer *T)
 static GEN
 DDF_roots(GEN A)
 {
-  GEN p, Ap, lc, lcpol, z, pe, pes2, bound;
-  long i, m, e, lz, v = varn(A);
+  GEN p, lc, lcpol, z, pe, pes2, bound;
+  long i, m, e, lz;
   ulong pp;
-  pari_sp av, lim;
+  pari_sp av;
   pari_timer T;
 
   if (DEBUGLEVEL>2) timer_start(&T);
@@ -806,33 +806,16 @@ DDF_roots(GEN A)
   if (is_pm1(lc))
   { lc = NULL; lcpol = A; }
   else
-  { lc = absi(lc); lcpol = ZX_Z_mul(A, lc); }
-  Ap = Flx_normalize(ZX_to_Flx(A, pp), pp);
-  bound = root_bound(A);
-  if (lc) bound = mulii(lc, bound);
+  { lc = absi_shallow(lc); lcpol = ZX_Z_mul(A, lc); }
+  bound = root_bound(A); if (lc) bound = mulii(lc, bound);
   e = logint(addiu(shifti(bound, 1), 1), p, &pe);
   pes2 = shifti(pe, -1);
   if (DEBUGLEVEL>2) timer_printf(&T, "Root bound");
-
-  av = avma; lim = stack_lim(av,2);
-  z = Flx_roots(Ap, pp);
-  lz = lg(z)-1;
-  if (lz > (degpol(A) >> 2))
-  { /* many roots */
-    GEN Bp = Flx_div(Ap, Flv_roots_to_pol(z, pp, v), pp);
-    z = Flv_to_ZV(z);
-    z = shallowconcat(deg1_from_roots(z, v), Flx_to_ZX(Bp));
-    z = ZpX_liftfact(A, z, NULL, p, e, pe);
-  }
-  else
-  {
-    z = Flv_to_ZV(z);
-    z = ZpX_liftroots(A, z, p, e);
-    z = deg1_from_roots(z, v);
-  }
+  z = ZpX_roots(A, p, e); lz = lg(z);
+  z = deg1_from_roots(z, varn(A));
   if (DEBUGLEVEL>2) timer_printf(&T, "Hensel lift (mod %lu^%ld)", pp,e);
-
-  for (m=1, i=1; i <= lz; i++)
+  av = avma;
+  for (m=1, i=1; i < lz; i++)
   {
     GEN q, r, y = gel(z,i);
     if (lc) y = ZX_Z_mul(y, lc);
@@ -844,14 +827,14 @@ DDF_roots(GEN A)
     if (lc) {
       r = gdiv(r,lc);
       A = Q_primpart(A);
-      lc = absi( leading_term(A) );
+      lc = absi_shallow( leading_term(A) );
       if (is_pm1(lc)) lc = NULL; else lcpol = ZX_Z_mul(A, lc);
     }
     gel(z,m++) = r;
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"DDF_roots, m = %ld", m);
-      gerepileall(av, lc? 4:2, &z, &A, &lc, &lcpol);
+      gerepileall(av, lc? 3:1, &A, &lc, &lcpol);
 
     }
   }
@@ -1081,7 +1064,7 @@ ZX_gcd_all(GEN A, GEN B, GEN *Anew)
   GEN R, a, b, q, H, Hp, g, Ag, Bg;
   long m, n, valX, valA, vA = varn(A);
   ulong p;
-  pari_sp ltop, av, avlim;
+  pari_sp ltop, av;
   forprime_t S;
 
   if (!signe(A)) { if (Anew) *Anew = pol_0(vA); return ZX_copy(B); }
@@ -1101,7 +1084,7 @@ ZX_gcd_all(GEN A, GEN B, GEN *Anew)
     Bg = ZX_Z_mul(B,g);
   }
   init_modular(&S);
-  av = avma; avlim = stack_lim(av, 1);
+  av = avma;
   R = NULL;/*-Wall*/
   H = NULL;
   while ((p = u_forprime_next(&S)))
@@ -1133,7 +1116,7 @@ ZX_gcd_all(GEN A, GEN B, GEN *Anew)
       q = utoipos(p); n = m; continue;
     }
     if (DEBUGLEVEL>5) err_printf("gcd mod %lu (bound 2^%ld)\n", p,expi(q));
-    if (low_stack(avlim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"QX_gcd");
       gerepileall(av, 3, &H, &q, &Hp);
@@ -1312,11 +1295,11 @@ ZXQ_mul_by_X(GEN t, GEN T)
 static long
 BD_odd_iscyclo(GEN f)
 {
-  pari_sp av, lim;
+  pari_sp av;
   long d, e, n, bound;
   GEN t;
   f = RgX_deflate_max(f, &e);
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
   /* The original f is cyclotomic (= Phi_{ne}) iff the present one is Phi_n,
    * where all prime dividing e also divide n. If current f is Phi_n,
    * then n is odd and squarefree */
@@ -1341,7 +1324,7 @@ BD_odd_iscyclo(GEN f)
     t = ZXQ_mul_by_X(t, f);
     /* t = (X mod f(X))^d */
     if (degpol(t) == 0) break;
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"BD_odd_iscyclo");
       t = gerepilecopy(av, t);
@@ -1384,8 +1367,9 @@ long
 poliscyclo(GEN f)
 {
   pari_sp av = avma;
-  long d = degpol(f);
+  long d;
   if (typ(f) != t_POL) pari_err_TYPE("poliscyclo", f);
+  d = degpol(f);
   if (d <= 0 || !RgX_is_ZX(f)) return 0;
   if (!equali1(gel(f,d+2)) || !is_pm1(gel(f,2))) return 0;
   if (d == 1) return signe(gel(f,2)) > 0? 2: 1;
diff --git a/src/basemath/Qfb.c b/src/basemath/Qfb.c
index 5eb0d0c..ec293e7 100644
--- a/src/basemath/Qfb.c
+++ b/src/basemath/Qfb.c
@@ -304,6 +304,7 @@ qfi_1_by_disc(GEN D)
 {
   GEN b,c, y = cgetg(4,t_QFI);
   quadpoly_bc(D, mod2(D), &b,&c);
+  if (b == gen_m1) b = gen_1;
   gel(y,1) = gen_1;
   gel(y,2) = b;
   gel(y,3) = c; return y;
@@ -613,7 +614,7 @@ GEN
 redimagsl2(GEN q, GEN *U)
 {
   GEN Q = cgetg(4, t_QFI);
-  pari_sp av = avma, av2, lim = stack_lim(av, 1);
+  pari_sp av = avma, av2;
   GEN z, u1,u2,v1,v2, a = gel(q,1), b = gel(q,2), c = gel(q,3);
   long cmp;
   /* upper bound for size of final (a,b,c) */
@@ -634,7 +635,7 @@ redimagsl2(GEN q, GEN *U)
     swap(a,c); b = negi(b);
     z = u1; u1 = u2; u2 = negi(z);
     REDBU(a,&b,&c, u1,&u2);
-    if (low_stack(lim, stack_lim(av, 1))) {
+    if (gc_needed(av, 1)) {
       if (DEBUGMEM>1) pari_warn(warnmem, "redimagsl2");
       gerepileall(av2, 5, &a,&b,&c, &u1,&u2);
     }
@@ -685,9 +686,9 @@ redimag_1(pari_sp av, GEN a, GEN b, GEN c)
   { /* at most twice */
     long lb = lgefint(b); /* <= 3 after first loop */
     if (lb == 2) return redimag_1_b0(a[2],c[2]);
-    if (lb == 3 && (ulong)b[2] <= (ulong)LONG_MAX) break;
+    if (lb == 3 && uel(b,2) <= (ulong)LONG_MAX) break;
     REDB(a,&b,&c);
-    if ((ulong)a[2] <= (ulong)c[2])
+    if (uel(a,2) <= uel(c,2))
     { /* lg(b) <= 3 but may be too large for itos */
       long s = signe(b);
       avma = av;
@@ -952,9 +953,9 @@ static GEN
 qfr5_init(GEN x, struct qfr_data *S)
 {
   GEN d = gel(x,4);
-  long prec = realprec(d), l = nbits2prec(-expo(d));
-  if (l > prec) prec = l;
-  if (prec < LOWDEFAULTPREC) prec = LOWDEFAULTPREC;
+  long prec = realprec(d), l = -expo(d);
+  if (l < BITS_IN_LONG) l = BITS_IN_LONG;
+  prec = maxss(prec, nbits2prec(l));
   x = qfr_to_qfr5(x,prec);
 
   get_disc(x, S);
@@ -1307,12 +1308,12 @@ redrealsl2step(GEN A, GEN d, GEN rd)
   pari_sp ltop = avma;
   GEN N, V = gel(A,1), M = gel(A,2);
   GEN a = gel(V,1), b = gel(V,2), c = gel(V,3);
-  GEN ac = mpabs(c);
-  GEN r = addii(b, gmax(rd, ac));
-  GEN q = truedvmdii(r, shifti(ac, 1), NULL);
-  r = subii(mulii(shifti(q, 1), ac), b);
-  a = c; b = r;
-  c = truedvmdii(subii(sqri(r), d), shifti(c,2), NULL);
+  GEN C = mpabs(c);
+  GEN t = addii(b, gmax(rd, C));
+  GEN r, q = truedvmdii(t, shifti(C,1), &r);
+  b = subii(t, addii(r,b));
+  a = c;
+  c = truedivii(subii(sqri(b), d), shifti(c,2));
   if (signe(a) < 0) togglesign(q);
   N = mkmat2(gel(M,2),
              mkcol2(subii(mulii(q, gcoeff(M, 1, 2)), gcoeff(M, 1, 1)),
@@ -1323,22 +1324,22 @@ redrealsl2step(GEN A, GEN d, GEN rd)
 GEN
 redrealsl2(GEN V, GEN d, GEN rd)
 {
-  pari_sp ltop = avma, st_lim = stack_lim(ltop, 1);
+  pari_sp ltop = avma;
   GEN M, u1, u2, v1, v2;
   GEN a = gel(V,1), b = gel(V,2), c = gel(V,3);
   u1 = v2 = gen_1; v1 = u2 = gen_0;
   while (!ab_isreduced(a,b,rd))
   {
-    GEN ac = mpabs(c);
-    GEN r = addii(b, gmax(rd,ac));
-    GEN q = truedvmdii(r, shifti(ac, 1), NULL);
-    r = subii(mulii(shifti(q, 1), ac), b);
-    a = c; b = r;
-    c = truedvmdii(subii(sqri(r), d), shifti(c, 2), NULL);
+    GEN C = mpabs(c);
+    GEN t = addii(b, gmax(rd,C));
+    GEN r, q = truedvmdii(t, shifti(C,1), &r);
+    b = subii(t, addii(r,b));
+    a = c;
+    c = truedivii(subii(sqri(b), d), shifti(c,2));
     if (signe(a) < 0) togglesign(q);
     r = u1; u1 = v1; v1 = subii(mulii(q, v1), r);
     r = u2; u2 = v2; v2 = subii(mulii(q, v2), r);
-    if (low_stack(st_lim, stack_lim(ltop, 1)))
+    if (gc_needed(ltop, 1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"redrealsl2");
       gerepileall(ltop, 7, &a,&b,&c,&u1,&u2,&v1,&v2);
@@ -1349,9 +1350,45 @@ redrealsl2(GEN V, GEN d, GEN rd)
 }
 
 GEN
+qfbredsl2(GEN q, GEN S)
+{
+  GEN v, D, isD;
+  pari_sp av;
+  switch(typ(q))
+  {
+    case t_QFI:
+      if (S) pari_err_TYPE("qfbredsl2",S);
+      v = cgetg(3,t_VEC);
+      gel(v,1) = redimagsl2(q, &gel(v,2));
+      return v;
+    case t_QFR:
+      av = avma;
+      if (S) {
+        if (typ(S) != t_VEC || lg(S) != 3) pari_err_TYPE("qfbredsl2",S);
+        D = gel(S,1);
+        isD = gel(S,2);
+        if (typ(D) != t_INT || signe(D) <= 0 || typ(isD) != t_INT)
+          pari_err_TYPE("qfbredsl2",S);
+      }
+      else
+      {
+        D = qfb_disc(q);
+        isD = sqrtint(D);
+      }
+      v = redrealsl2(q,D,isD);
+      gel(v,1) = qfr3_to_qfr(gel(v,1), real_0(precision(gel(q,4))));
+      return gerepilecopy(av, v);
+
+    default:
+        pari_err_TYPE("qfbredsl2",q);
+        return NULL;
+  }
+}
+
+GEN
 qfrsolvep(GEN Q, GEN p)
 {
-  pari_sp ltop = avma, btop, st_lim;
+  pari_sp ltop = avma, btop;
   GEN N, P, P1, P2, M, rd, d = qfb_disc(Q);
   if (kronecker(d, p) < 0) { avma = ltop; return gen_0; }
   rd = sqrti(d);
@@ -1360,14 +1397,14 @@ qfrsolvep(GEN Q, GEN p)
   P1 = redrealsl2(P, d,rd);
   togglesign( gel(P,2) );
   P2 = redrealsl2(P, d,rd);
-  btop = avma; st_lim = stack_lim(btop, 1);
+  btop = avma;
   for(;;)
   {
     if (ZV_equal(gel(M,1), gel(P1,1))) { N = gel(P1,2); break; }
     if (ZV_equal(gel(M,1), gel(P2,1))) { N = gel(P2,2); break; }
     M = redrealsl2step(M, d,rd);
     if (ZV_equal(gel(M,1), gel(N,1))) { avma = ltop; return gen_0; }
-    if (low_stack(st_lim, stack_lim(btop, 1))) M = gerepileupto(btop, M);
+    if (gc_needed(btop, 1)) M = gerepileupto(btop, M);
   }
   return gerepilecopy(ltop, SL2_div_mul_e1(gel(M,2),N));
 }
@@ -1390,7 +1427,7 @@ qfbsolve(GEN Q,GEN n)
 long
 cornacchia(GEN d, GEN p, GEN *px, GEN *py)
 {
-  pari_sp av = avma, av2, lim;
+  pari_sp av = avma, av2;
   GEN a, b, c, L, r;
 
   if (typ(d) != t_INT) pari_err_TYPE("cornacchia", d);
@@ -1404,11 +1441,11 @@ cornacchia(GEN d, GEN p, GEN *px, GEN *py)
   if (!b) { avma = av; return 0; }
   if (absi_cmp(shifti(b,1), p) > 0) b = subii(b,p);
   a = p; L = sqrti(p);
-  av2 = avma; lim = stack_lim(av2, 1);
+  av2 = avma;
   while (absi_cmp(b, L) > 0)
   {
     r = remii(a, b); a = b; b = r;
-    if (low_stack(lim, stack_lim(av2, 1))) {
+    if (gc_needed(av2, 1)) {
       if (DEBUGMEM>1) pari_warn(warnmem,"cornacchia");
       gerepileall(av2, 2, &a,&b);
     }
@@ -1424,7 +1461,7 @@ cornacchia(GEN d, GEN p, GEN *px, GEN *py)
 long
 cornacchia2(GEN d, GEN p, GEN *px, GEN *py)
 {
-  pari_sp av = avma, av2, lim;
+  pari_sp av = avma, av2;
   GEN a, b, c, L, r, px4;
   long k;
 
@@ -1456,11 +1493,11 @@ cornacchia2(GEN d, GEN p, GEN *px, GEN *py)
   }
   if (mod2(b) != (k & 1)) b = subii(p,b);
   a = shifti(p,1); L = sqrti(px4);
-  av2 = avma; lim = stack_lim(av2, 1);
+  av2 = avma;
   while (cmpii(b, L) > 0)
   {
     r = remii(a, b); a = b; b = r;
-    if (low_stack(lim, stack_lim(av2, 1))) {
+    if (gc_needed(av2, 1)) {
       if (DEBUGMEM>1) pari_warn(warnmem,"cornacchia");
       gerepileall(av2, 2, &a,&b);
     }
diff --git a/src/basemath/RgV.c b/src/basemath/RgV.c
index e451de1..24d934d 100644
--- a/src/basemath/RgV.c
+++ b/src/basemath/RgV.c
@@ -49,23 +49,25 @@ RgM_zc_mul_i(GEN x, GEN y, long c, long l)
 {
   long i, j;
   pari_sp av;
-  GEN z = cgetg(l,t_COL), s;
+  GEN z = cgetg(l,t_COL);
 
   for (i=1; i<l; i++)
   {
-    av = avma; s = gmulgs(gcoeff(x,i,1),y[1]);
-    for (j=2; j<c; j++)
+    GEN s = NULL;
+    av = avma;
+    for (j=1; j<c; j++)
     {
       long t = y[j];
+      if (!t) continue;
+      if (!s) { s = gmulgs(gcoeff(x,i,j),t); continue; }
       switch(t)
       {
-        case  0: break;
         case  1: s = gadd(s, gcoeff(x,i,j)); break;
         case -1: s = gsub(s, gcoeff(x,i,j)); break;
         default: s = gadd(s, gmulgs(gcoeff(x,i,j), t)); break;
       }
     }
-    gel(z,i) = gerepileupto(av,s);
+    gel(z,i) = gerepileupto(av,s? s: gen_0);
   }
   return z;
 }
@@ -109,14 +111,14 @@ GEN
 RgV_dotsquare(GEN x)
 {
   long i, lx = lg(x);
-  pari_sp av = avma, lim = stack_lim(av,3);
+  pari_sp av = avma;
   GEN z;
   if (lx == 1) return gen_0;
   z = gsqr(gel(x,1));
   for (i=2; i<lx; i++)
   {
     z = gadd(z, gsqr(gel(x,i)));
-    if (low_stack(lim,stack_lim(av,3)))
+    if (gc_needed(av,3))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"RgV_dotsquare, i = %ld",i);
       z = gerepileupto(av, z);
@@ -129,7 +131,7 @@ RgV_dotsquare(GEN x)
 static GEN
 RgV_dotproduct_i(GEN x, GEN y, long lx)
 {
-  pari_sp av = avma, lim = stack_lim(av,3);
+  pari_sp av = avma;
   long i;
   GEN z;
   if (lx == 1) return gen_0;
@@ -137,7 +139,7 @@ RgV_dotproduct_i(GEN x, GEN y, long lx)
   for (i=2; i<lx; i++)
   {
     z = gadd(z, gmul(gel(x,i), gel(y,i)));
-    if (low_stack(lim,stack_lim(av,3)))
+    if (gc_needed(av,3))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"RgV_dotproduct, i = %ld",i);
       z = gerepileupto(av, z);
@@ -181,6 +183,25 @@ RgV_sumpart2(GEN v, long m, long n)
   p = gel(v,m); for (i=m+1; i<=n; i++) p = gadd(p, gel(v,i));
   return p;
 }
+GEN
+RgM_sumcol(GEN A)
+{
+  long i,j,m,l = lg(A);
+  GEN v;
+
+  if (l == 1) return cgetg(1,t_MAT);
+  if (l == 2) return gcopy(gel(A,1));
+  m = lgcols(A);
+  v = cgetg(m, t_COL);
+  for (i = 1; i < m; i++)
+  {
+    pari_sp av = avma;
+    GEN s = gcoeff(A,i,1);
+    for (j = 2; j < l; j++) s = gadd(s, gcoeff(A,i,j));
+    gel(v, i) = gerepileupto(av, s);
+  }
+  return v;
+}
 
 /*                    ADDITION SCALAR + MATRIX                     */
 /* x square matrix, y scalar; create the square matrix x + y*Id */
@@ -594,10 +615,11 @@ RgM_sqr(GEN x)
 {
   pari_sp av = avma;
   long j, lx = lg(x);
-  GEN z;
+  GEN z, ffx = NULL;
   if (lx == 1) return cgetg(1, t_MAT);
   if (lx != lgcols(x)) pari_err_OP("operation 'RgM_mul'", x,x);
   if (is_modular_sqr(x,&z)) return gerepileupto(av, z);
+  if (RgM_is_FFM(x, &ffx))  return FFM_mul(x, x, ffx);
   z = cgetg(lx, t_MAT);
   for (j=1; j<lx; j++) gel(z,j) = RgM_RgC_mul_i(x, gel(x,j), lx, lx);
   return z;
@@ -799,6 +821,20 @@ RgM_isidentity(GEN x)
   return 1;
 }
 
+long
+RgC_is_ei(GEN x)
+{
+  long i, j = 0, l = lg(x);
+  for (i = 1; i < l; i++)
+  {
+    GEN c = gel(x,i);
+    if (gequal0(c)) continue;
+    if (!gequal1(c) || j) return 0;
+    j = i;
+  }
+  return j;
+}
+
 int
 RgM_isdiagonal(GEN x)
 {
diff --git a/src/basemath/RgX.c b/src/basemath/RgX.c
index 8b21d07..f41d7e7 100644
--- a/src/basemath/RgX.c
+++ b/src/basemath/RgX.c
@@ -41,13 +41,13 @@ static GEN
 gen_RgXQ_eval_powers(GEN P, GEN V, long a, long n, void *E, const struct bb_algebra *ff,
                                            GEN cmul(void *E, GEN P, long a, GEN x))
 {
-  pari_sp av = avma, lim=stack_lim(av,2);
+  pari_sp av = avma;
   long i;
   GEN z = cmul(E,P,a,ff->one(E));
   for (i=1; i<=n; i++)
   {
     z = ff->add(E, z, cmul(E,P,a+i,gel(V,i+1)));
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
       z = gerepileupto(av, z);
   }
   return ff->red(E,z);
@@ -62,7 +62,7 @@ GEN
 gen_bkeval_powers(GEN P, long d, GEN V, void *E, const struct bb_algebra *ff,
                                      GEN cmul(void *E, GEN P, long a, GEN x))
 {
-  pari_sp av = avma, lim;
+  pari_sp av = avma;
   long l = lg(V)-1;
   GEN z, u;
 
@@ -71,13 +71,12 @@ gen_bkeval_powers(GEN P, long d, GEN V, void *E, const struct bb_algebra *ff,
   if (l<2) pari_err_DOMAIN("gen_RgX_bkeval_powers", "#powers", "<",gen_2,V);
   d -= l;
   z = gen_RgXQ_eval_powers(P,V,d+1,l-1,E,ff,cmul);
-  lim = stack_lim(av,2);
   while (d >= l-1)
   {
     d -= l-1;
     u = gen_RgXQ_eval_powers(P,V,d+1,l-2,E,ff,cmul);
     z = ff->add(E,u, ff->mul(E,z,gel(V,l)));
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
       z = gerepileupto(av, z);
   }
   u = gen_RgXQ_eval_powers(P,V,0,d,E,ff,cmul);
@@ -216,6 +215,24 @@ ZX_unscale(GEN P, GEN h)
   }
   return Q;
 }
+/* P a ZX. Return P(x << n), not memory clean */
+GEN
+ZX_unscale2n(GEN P, long n)
+{
+  long i, ni = n, l = lg(P);
+  GEN Q = cgetg(l, t_POL);
+  Q[1] = P[1];
+  if (l == 2) return Q;
+  gel(Q,2) = gel(P,2);
+  if (l == 3) return Q;
+  gel(Q,3) = shifti(gel(P,3), ni);
+  for (i=4; i<l; i++)
+  {
+    ni += n;
+    gel(Q,i) = shifti(gel(P,i), ni);
+  }
+  return Q;
+}
 /* P(h*X) / h, assuming h | P(0), i.e. the result is a ZX */
 GEN
 ZX_unscale_div(GEN P, GEN h)
@@ -299,20 +316,19 @@ RgX_inflate(GEN x0, long d)
 GEN
 RgX_translate(GEN P, GEN c)
 {
-  pari_sp av = avma, lim;
+  pari_sp av = avma;
   GEN Q, *R;
   long i, k, n;
 
   if (!signe(P) || gequal0(c)) return RgX_copy(P);
   Q = leafcopy(P);
   R = (GEN*)(Q+2); n = degpol(P);
-  lim = stack_lim(av, 2);
   if (gequal1(c))
   {
     for (i=1; i<=n; i++)
     {
       for (k=n-i; k<n; k++) R[k] = gadd(R[k], R[k+1]);
-      if (low_stack(lim, stack_lim(av,2)))
+      if (gc_needed(av,2))
       {
         if(DEBUGMEM>1) pari_warn(warnmem,"TR_POL(1), i = %ld/%ld", i,n);
         Q = gerepilecopy(av, Q); R = (GEN*)Q+2;
@@ -324,7 +340,7 @@ RgX_translate(GEN P, GEN c)
     for (i=1; i<=n; i++)
     {
       for (k=n-i; k<n; k++) R[k] = gsub(R[k], R[k+1]);
-      if (low_stack(lim, stack_lim(av,2)))
+      if (gc_needed(av,2))
       {
         if(DEBUGMEM>1) pari_warn(warnmem,"TR_POL(-1), i = %ld/%ld", i,n);
         Q = gerepilecopy(av, Q); R = (GEN*)Q+2;
@@ -336,7 +352,7 @@ RgX_translate(GEN P, GEN c)
     for (i=1; i<=n; i++)
     {
       for (k=n-i; k<n; k++) R[k] = gadd(R[k], gmul(c, R[k+1]));
-      if (low_stack(lim, stack_lim(av,2)))
+      if (gc_needed(av,2))
       {
         if(DEBUGMEM>1) pari_warn(warnmem,"TR_POL, i = %ld/%ld", i,n);
         Q = gerepilecopy(av, Q); R = (GEN*)Q+2;
@@ -350,20 +366,19 @@ RgX_translate(GEN P, GEN c)
 GEN
 ZX_translate(GEN P, GEN c)
 {
-  pari_sp av = avma, lim;
+  pari_sp av = avma;
   GEN Q, *R;
   long i, k, n;
 
   if (!signe(P) || !signe(c)) return ZX_copy(P);
   Q = leafcopy(P);
   R = (GEN*)(Q+2); n = degpol(P);
-  lim = stack_lim(av, 2);
   if (equali1(c))
   {
     for (i=1; i<=n; i++)
     {
       for (k=n-i; k<n; k++) R[k] = addii(R[k], R[k+1]);
-      if (low_stack(lim, stack_lim(av,2)))
+      if (gc_needed(av,2))
       {
         if(DEBUGMEM>1) pari_warn(warnmem,"ZX_translate(1), i = %ld/%ld", i,n);
         Q = gerepilecopy(av, Q); R = (GEN*)Q+2;
@@ -375,7 +390,7 @@ ZX_translate(GEN P, GEN c)
     for (i=1; i<=n; i++)
     {
       for (k=n-i; k<n; k++) R[k] = subii(R[k], R[k+1]);
-      if (low_stack(lim, stack_lim(av,2)))
+      if (gc_needed(av,2))
       {
         if(DEBUGMEM>1) pari_warn(warnmem,"ZX_translate(-1), i = %ld/%ld", i,n);
         Q = gerepilecopy(av, Q); R = (GEN*)Q+2;
@@ -387,7 +402,7 @@ ZX_translate(GEN P, GEN c)
     for (i=1; i<=n; i++)
     {
       for (k=n-i; k<n; k++) R[k] = addii(R[k], mulii(c, R[k+1]));
-      if (low_stack(lim, stack_lim(av,2)))
+      if (gc_needed(av,2))
       {
         if(DEBUGMEM>1) pari_warn(warnmem,"ZX_translate, i = %ld/%ld", i,n);
         Q = gerepilecopy(av, Q); R = (GEN*)Q+2;
@@ -400,14 +415,13 @@ ZX_translate(GEN P, GEN c)
 GEN
 RgXQX_translate(GEN P, GEN c, GEN T)
 {
-  pari_sp av = avma, lim;
+  pari_sp av = avma;
   GEN Q, *R;
   long i, k, n;
 
   if (!signe(P) || gequal0(c)) return RgX_copy(P);
   Q = leafcopy(P);
   R = (GEN*)(Q+2); n = degpol(P);
-  lim = stack_lim(av, 2);
   for (i=1; i<=n; i++)
   {
     for (k=n-i; k<n; k++)
@@ -415,7 +429,7 @@ RgXQX_translate(GEN P, GEN c, GEN T)
       pari_sp av2 = avma;
       R[k] = gerepileupto(av2, RgX_rem(gadd(R[k], gmul(c, R[k+1])), T));
     }
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"RgXQX_translate, i = %ld/%ld", i,n);
       Q = gerepilecopy(av, Q); R = (GEN*)Q+2;
@@ -548,7 +562,7 @@ RgV_to_RgX_reverse(GEN x, long v)
 
 /* return the (N-dimensional) vector of coeffs of p */
 GEN
-RgX_to_RgV(GEN x, long N)
+RgX_to_RgC(GEN x, long N)
 {
   long i, l;
   GEN z;
@@ -560,9 +574,9 @@ RgX_to_RgV(GEN x, long N)
   return z;
 }
 GEN
-Rg_to_RgV(GEN x, long N)
+Rg_to_RgC(GEN x, long N)
 {
-  return (typ(x) == t_POL)? RgX_to_RgV(x,N): scalarcol_shallow(x, N);
+  return (typ(x) == t_POL)? RgX_to_RgC(x,N): scalarcol_shallow(x, N);
 }
 
 /* vector of polynomials (in v) whose coeffs are given by the columns of x */
@@ -582,7 +596,7 @@ RgV_to_RgM(GEN v, long n)
 {
   long j, N = lg(v);
   GEN y = cgetg(N, t_MAT);
-  for (j=1; j<N; j++) gel(y,j) = Rg_to_RgV(gel(v,j), n);
+  for (j=1; j<N; j++) gel(y,j) = Rg_to_RgC(gel(v,j), n);
   return y;
 }
 GEN
@@ -590,7 +604,7 @@ RgXV_to_RgM(GEN v, long n)
 {
   long j, N = lg(v);
   GEN y = cgetg(N, t_MAT);
-  for (j=1; j<N; j++) gel(y,j) = RgX_to_RgV(gel(v,j), n);
+  for (j=1; j<N; j++) gel(y,j) = RgX_to_RgC(gel(v,j), n);
   return y;
 }
 
@@ -613,7 +627,7 @@ RgXX_to_RgM(GEN v, long n)
 {
   long j, N = lg(v)-1;
   GEN y = cgetg(N, t_MAT);
-  for (j=1; j<N; j++) gel(y,j) = Rg_to_RgV(gel(v,j+1), n);
+  for (j=1; j<N; j++) gel(y,j) = Rg_to_RgC(gel(v,j+1), n);
   return y;
 }
 
@@ -650,18 +664,36 @@ RgXY_swap(GEN x, long n, long w)
   setvarn(z, varn(x)); return z;
 }
 
+long
+RgXY_degreex(GEN bpol)
+{
+  long deg = 0, i;
+  if (!signe(bpol)) return -1;
+  for (i = 2; i < lg(bpol); ++i)
+    deg = maxss(deg, degpol(gel(bpol, i)));
+  return deg;
+}
+
 /* return (x % X^n). Shallow */
 GEN
-RgX_modXn_shallow(GEN a, long n)
+RgXn_red_shallow(GEN a, long n)
 {
   long i, L, l = lg(a);
   GEN  b;
   if (l == 2 || !n) return pol_0(varn(a));
-  if (n < 0) pari_err_DOMAIN("RgX_modXn", "n", "<", gen_0, stoi(n));
   L = n+2; if (L > l) L = l;
   b = cgetg(L, t_POL); b[1] = a[1];
   for (i=2; i<L; i++) gel(b,i) = gel(a,i);
-  return b;
+  return normalizepol_lg(b,L);
+}
+
+GEN
+RgXnV_red_shallow(GEN P, long n)
+{
+  long i, l = lg(P);
+  GEN Q = cgetg(l, t_VEC);
+  for (i=1; i<l; i++) gel(Q,i) = RgXn_red_shallow(gel(P,i), n);
+  return Q;
 }
 
 /* return (x * X^n). Shallow */
@@ -1130,7 +1162,7 @@ addmulXncopy(GEN x, GEN y, long d)
 
 /* return x * y mod t^n */
 static GEN
-RgX_mullow_basecase(GEN x, GEN y, long n)
+RgXn_mul_basecase(GEN x, GEN y, long n)
 {
   long i, lz = n+2, lx = lgpol(x), ly = lgpol(y);
   GEN z;
@@ -1151,19 +1183,19 @@ RgX_mullow_basecase(GEN x, GEN y, long n)
 }
 /* Mulders / Karatsuba product f*g mod t^n (Hanrot-Zimmermann variant) */
 GEN
-RgX_mullow(GEN f, GEN g, long n)
+RgXn_mul(GEN f, GEN g, long n)
 {
   pari_sp av = avma;
   GEN fe,fo, ge,go, l,h,m;
   long n0, n1;
   if (degpol(f) + degpol(g) < n) return RgX_mul(f,g);
-  if (n < 80) return RgX_mullow_basecase(f,g,n);
+  if (n < 80) return RgXn_mul_basecase(f,g,n);
   n0 = n>>1; n1 = n-n0;
   RgX_even_odd(f, &fe, &fo);
   RgX_even_odd(g, &ge, &go);
-  l = RgX_mullow(fe,ge,n1);
-  h = RgX_mullow(fo,go,n0);
-  m = RgX_sub(RgX_mullow(RgX_add(fe,fo),RgX_add(ge,go),n0), RgX_add(l,h));
+  l = RgXn_mul(fe,ge,n1);
+  h = RgXn_mul(fo,go,n0);
+  m = RgX_sub(RgXn_mul(RgX_add(fe,fo),RgX_add(ge,go),n0), RgX_add(l,h));
   /* n1-1 <= n0 <= n1, deg l,m <= n1-1, deg h <= n0-1
    * result is t^2 h(t^2) + t m(t^2) + l(t^2) */
   l = RgX_inflate(l,2); /* deg l <= 2n1 - 2 <= n-1 */
@@ -1269,7 +1301,7 @@ RgX_sqrspec_basecase(GEN x, long nx, long v)
 }
 /* return x^2 mod t^n */
 static GEN
-RgX_sqrlow_basecase(GEN x, long n)
+RgXn_sqr_basecase(GEN x, long n)
 {
   long i, lz = n+2, lx = lgpol(x);
   GEN z;
@@ -1285,18 +1317,18 @@ RgX_sqrlow_basecase(GEN x, long n)
 }
 /* Mulders / Karatsuba product f^2 mod t^n (Hanrot-Zimmermann variant) */
 GEN
-RgX_sqrlow(GEN f, long n)
+RgXn_sqr(GEN f, long n)
 {
   pari_sp av = avma;
   GEN fe,fo, l,h,m;
   long n0, n1;
   if (2*degpol(f) < n) return RgX_sqr(f);
-  if (n < 80) return RgX_sqrlow_basecase(f,n);
+  if (n < 80) return RgXn_sqr_basecase(f,n);
   n0 = n>>1; n1 = n-n0;
   RgX_even_odd(f, &fe, &fo);
-  l = RgX_sqrlow(fe,n1);
-  h = RgX_sqrlow(fo,n0);
-  m = RgX_sub(RgX_sqrlow(RgX_add(fe,fo),n0), RgX_add(l,h));
+  l = RgXn_sqr(fe,n1);
+  h = RgXn_sqr(fo,n0);
+  m = RgX_sub(RgXn_sqr(RgX_add(fe,fo),n0), RgX_add(l,h));
   /* n1-1 <= n0 <= n1, deg l,m <= n1-1, deg h <= n0-1
    * result is t^2 h(t^2) + t m(t^2) + l(t^2) */
   l = RgX_inflate(l,2); /* deg l <= 2n1 - 2 <= n-1 */
@@ -1383,6 +1415,20 @@ RgX_Rg_div(GEN x, GEN y) {
   return normalizepol_lg(z, lx);
 }
 GEN
+RgX_normalize(GEN x)
+{
+  GEN d = NULL;
+  long i, n = lg(x)-1;
+  for (i = n; i > 1; i--)
+  {
+    d = gel(x,i);
+    if (!gequal0(d)) break;
+  }
+  if (i == 1) return pol_0(varn(x));
+  if (i == n && isint1(d)) return x;
+  return normalizepol_lg(RgX_Rg_div(x, d), i+1);
+}
+GEN
 RgX_divs(GEN x, long y) {
   long i, lx;
   GEN z = cgetg_copy(x, &lx); z[1] = x[1];
@@ -1689,7 +1735,7 @@ int
 ZXQX_dvd(GEN x, GEN y, GEN T)
 {
   long dx, dy, dz, i, p, T_ismonic;
-  pari_sp av = avma, av2, lim;
+  pari_sp av = avma, av2;
   GEN y_lead;
 
   if (!signe(y)) pari_err_INV("ZXQX_dvd",y);
@@ -1707,7 +1753,7 @@ ZXQX_dvd(GEN x, GEN y, GEN T)
   for (i = 1; i <= dy; i++)
     if (!signe(gel(y,i))) gel(y,i) = NULL;
   dz = dx-dy; p = dz+1;
-  av2 = avma; lim = stack_lim(av2,1);
+  av2 = avma;
   for (;;)
   {
     GEN m, x0 = gel(x,0), y0 = y_lead, cx = content(x0);
@@ -1734,7 +1780,7 @@ ZXQX_dvd(GEN x, GEN y, GEN T)
     }
     do { x++; dx--; } while (dx >= 0 && !signe(gel(x,0)));
     if (dx < dy) break;
-    if (low_stack(lim,stack_lim(av2,1)))
+    if (gc_needed(av2,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"ZXQX_dvd dx = %ld >= %ld",dx,dy);
       gerepilecoeffs(av2,x,dx+1);
@@ -1748,7 +1794,7 @@ GEN
 RgXQX_pseudorem(GEN x, GEN y, GEN T)
 {
   long vx = varn(x), dx, dy, dz, i, lx, p;
-  pari_sp av = avma, av2, lim;
+  pari_sp av = avma, av2;
   GEN y_lead;
 
   if (!signe(y)) pari_err_INV("RgXQX_pseudorem",y);
@@ -1764,7 +1810,7 @@ RgXQX_pseudorem(GEN x, GEN y, GEN T)
   for (i = 1; i <= dy; i++)
     if (isexactzero(gel(y,i))) gel(y,i) = NULL;
   dz = dx-dy; p = dz+1;
-  av2 = avma; lim = stack_lim(av2,1);
+  av2 = avma;
   for (;;)
   {
     gel(x,0) = gneg(gel(x,0)); p--;
@@ -1781,7 +1827,7 @@ RgXQX_pseudorem(GEN x, GEN y, GEN T)
     }
     do { x++; dx--; } while (dx >= 0 && gequal0(gel(x,0)));
     if (dx < dy) break;
-    if (low_stack(lim,stack_lim(av2,1)))
+    if (gc_needed(av2,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"RgX_pseudorem dx = %ld >= %ld",dx,dy);
       gerepilecoeffs(av2,x,dx+1);
@@ -1817,7 +1863,7 @@ GEN
 RgXQX_pseudodivrem(GEN x, GEN y, GEN T, GEN *ptr)
 {
   long vx = varn(x), dx, dy, dz, i, iz, lx, lz, p;
-  pari_sp av = avma, av2, lim;
+  pari_sp av = avma, av2;
   GEN z, r, ypow, y_lead;
 
   if (!signe(y)) pari_err_INV("RgXQX_pseudodivrem",y);
@@ -1852,7 +1898,7 @@ RgXQX_pseudodivrem(GEN x, GEN y, GEN T, GEN *ptr)
     GEN c = gmul(gel(ypow,i-1), y_lead);
     gel(ypow,i) = rem(c,T);
   }
-  av2 = avma; lim = stack_lim(av2,1);
+  av2 = avma;
   for (iz=2;;)
   {
     p--;
@@ -1871,7 +1917,7 @@ RgXQX_pseudodivrem(GEN x, GEN y, GEN T, GEN *ptr)
     x++; dx--;
     while (dx >= dy && gequal0(gel(x,0))) { x++; dx--; iz++; }
     if (dx < dy) break;
-    if (low_stack(lim,stack_lim(av2,1)))
+    if (gc_needed(av2,1))
     {
       GEN X = x-2;
       if(DEBUGMEM>1) pari_warn(warnmem,"RgX_pseudodivrem dx=%ld >= %ld",dx,dy);
@@ -1930,6 +1976,12 @@ RgXQX_RgXQ_mul(GEN x, GEN y, GEN T)
   return RgXQX_red(RgX_Rg_mul(x,y), T);
 }
 GEN
+RgXQV_RgXQ_mul(GEN v, GEN x, GEN T)
+{
+  return RgXQV_red(RgV_Rg_mul(v,x), T);
+}
+
+GEN
 RgXQX_sqr(GEN x, GEN T)
 {
   return RgXQX_red(RgX_sqr(x), T);
@@ -1973,12 +2025,12 @@ struct modXn {
 static GEN
 _sqrXn(void *data, GEN x) {
   struct modXn *S = (struct modXn*)data;
-  return RgX_sqrlow(x, S->n);
+  return RgXn_sqr(x, S->n);
 }
 static GEN
 _mulXn(void *data, GEN x, GEN y) {
   struct modXn *S = (struct modXn*)data;
-  return RgX_mullow(x,y, S->n);
+  return RgXn_mul(x,y, S->n);
 }
 static GEN
 _oneXn(void *data) {
@@ -1990,11 +2042,38 @@ _zeroXn(void *data) {
   struct modXn *S = (struct modXn*)data;
   return pol_0(S->v);
 }
-static struct bb_algebra RgX_modXn_algebra = { _red,_add, _mulXn,_sqrXn, _oneXn,_zeroXn };
+static struct bb_algebra RgXn_algebra = { _red,_add, _mulXn,_sqrXn, _oneXn,_zeroXn };
+
+GEN
+RgXn_powers(GEN x, long m, long n)
+{
+  long d = degpol(x);
+  int use_sqr = (d<<1) >= n;
+  struct modXn S;
+  S.v = varn(x); S.n = n;
+  return gen_powers(x,m,use_sqr,(void*)&S,_sqrXn,_mulXn,_oneXn);
+}
+
+GEN
+RgX_RgXnV_eval(GEN Q, GEN x, long n)
+{
+  struct modXn S;
+  S.v = varn(gel(x,2)); S.n = n;
+  return gen_bkeval_powers(Q,degpol(Q),x,(void*)&S,&RgXn_algebra,_cmul);
+}
+
+GEN
+RgX_RgXn_eval(GEN Q, GEN x, long n)
+{
+  int use_sqr = (degpol(x)<<1) >= n;
+  struct modXn S;
+  S.v = varn(x); S.n = n;
+  return gen_bkeval(Q,degpol(Q),x,use_sqr,(void*)&S,&RgXn_algebra,_cmul);
+}
 
 /* Q(x) mod t^n, x in R[t], n >= 1 */
 GEN
-RgX_modXn_eval(GEN Q, GEN x, long n)
+RgXn_eval(GEN Q, GEN x, long n)
 {
   long d = degpol(x);
   int use_sqr;
@@ -2007,7 +2086,111 @@ RgX_modXn_eval(GEN Q, GEN x, long n)
   S.v = varn(x);
   S.n = n;
   use_sqr = (d<<1) >= n;
-  return gen_bkeval(Q,degpol(Q),x,use_sqr,(void*)&S,&RgX_modXn_algebra,_cmul);
+  return gen_bkeval(Q,degpol(Q),x,use_sqr,(void*)&S,&RgXn_algebra,_cmul);
+}
+
+GEN
+RgXn_inv(GEN f, long e)
+{
+  pari_sp av = avma, av2;
+  ulong mask;
+  GEN W;
+  long v = varn(f), n=1;
+  if (signe(f)==0)
+    pari_err_INV("RgXn_inv",f);
+  W = scalarpol(ginv(gel(f,2)),v);
+  mask = quadratic_prec_mask(e);
+  av2 = avma;
+  for (;mask>1;)
+  {
+    GEN u, fr;
+    long n2 = n;
+    n<<=1; if (mask & 1) n--;
+    mask >>= 1;
+    fr = RgXn_red_shallow(f, n);
+    u = RgX_shift_shallow(RgXn_mul(W, fr, n), -n2);
+    W = RgX_sub(W, RgX_shift_shallow(RgXn_mul(u, W, n-n2), n2));
+    if (gc_needed(av2,2))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"RgXn_inv, e = %ld", n);
+      W = gerepileupto(av2, W);
+    }
+  }
+  return gerepileupto(av, W);
+}
+
+GEN
+RgXn_exp(GEN h, long e)
+{
+  pari_sp av = avma, av2;
+  long v = varn(h), n=1;
+  GEN f = pol_1(v), g = pol_1(v);
+  ulong mask = quadratic_prec_mask(e);
+  av2 = avma;
+  if (signe(h)==0 || degpol(h)<1 || !gequal0(gel(h,2)))
+    pari_err_DOMAIN("RgXn_exp","valuation", "<", gen_1, h);
+  for (;mask>1;)
+  {
+    GEN q, w;
+    long n2 = n;
+    n<<=1; if (mask & 1) n--;
+    mask >>= 1;
+    g = RgX_sub(RgX_muls(g,2),RgXn_mul(f,RgXn_sqr(g,n2),n2));
+    q = RgX_deriv(RgXn_red_shallow(h,n2));
+    w = RgX_add(q, RgXn_mul(g, RgX_sub(RgX_deriv(f), RgXn_mul(f,q,n-1)),n-1));
+    f = RgX_add(f, RgXn_mul(f, RgX_sub(RgXn_red_shallow(h, n), RgX_integ(w)), n));
+    if (gc_needed(av2,2))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"RgXn_exp, e = %ld", n);
+      gerepileall(av2, 2, &f, &g);
+    }
+  }
+  return gerepileupto(av, f);
+}
+
+GEN
+RgXn_reverse(GEN f, long e)
+{
+  pari_sp av = avma, av2;
+  ulong mask;
+  GEN fi, a, df, W, an;
+  long v = varn(f), n=1;
+  if (degpol(f)<1 || !gequal0(gel(f,2)))
+    pari_err_INV("serreverse",f);
+  fi = ginv(gel(f,3));
+  a = deg1pol_shallow(fi,gen_0,v);
+  if (e <= 2) return gerepilecopy(av, a);
+  W = scalarpol(fi,v);
+  df = RgX_deriv(f);
+  mask = quadratic_prec_mask(e);
+  av2 = avma;
+  for (;mask>1;)
+  {
+    GEN u, fa, fr;
+    long n2 = n, rt;
+    n<<=1; if (mask & 1) n--;
+    mask >>= 1;
+    fr = RgXn_red_shallow(f, n);
+    rt = brent_kung_optpow(degpol(fr), 4, 3);
+    an = RgXn_powers(a, rt, n);
+    if (n>1)
+    {
+      long n4 = (n2+1)>>1;
+      GEN dfr = RgXn_red_shallow(df, n2);
+      dfr = RgX_RgXnV_eval(dfr, RgXnV_red_shallow(an, n2), n2);
+      u = RgX_shift(RgX_Rg_sub(RgXn_mul(W, dfr, n2), gen_1), -n4);
+      W = RgX_sub(W, RgX_shift(RgXn_mul(u, W, n2-n4), n4));
+    }
+    fa = RgX_sub(RgX_RgXnV_eval(fr, an, n), pol_x(v));
+    fa = RgX_shift(fa, -n2);
+    a = RgX_sub(a, RgX_shift(RgXn_mul(W, fa, n-n2), n2));
+    if (gc_needed(av2,2))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"RgXn_reverse, e = %ld", n);
+      gerepileall(av2, 2, &a, &W);
+    }
+  }
+  return gerepileupto(av, a);
 }
 
 /* x,T in Rg[X], n in N, compute lift(x^n mod T)) */
diff --git a/src/basemath/ZG.c b/src/basemath/ZG.c
new file mode 100644
index 0000000..22635ea
--- /dev/null
+++ b/src/basemath/ZG.c
@@ -0,0 +1,146 @@
+/* $Id$
+
+Copyright (C) 2011  The PARI group.
+
+This file is part of the PARI/GP package.
+
+PARI/GP 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. It is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY WHATSOEVER.
+
+Check the License for details. You should have received a copy of it, along
+with the package; see the file 'COPYING'. If not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "pari.h"
+#include "paripriv.h"
+
+static int
+cmp_G(void *E, GEN x, GEN y) { (void)E; return cmp_universal(x,y); }
+
+/* a ZG is either a t_INT or a t_VEC of pairs [g,e] representing
+ * \sum e_i [g_i], e_i in Z, g_i in G. */
+GEN
+ZG_normalize(GEN x)
+{
+  if (typ(x) == t_INT) return x;
+  return sort_factor(x, NULL, &cmp_G);
+}
+GEN
+ZG_add(GEN x, GEN y)
+{
+  if (typ(x) == t_INT)
+  {
+    if (!signe(x)) return y;
+    if (typ(y) == t_INT)
+    {
+      if (!signe(y)) return x;
+      return addii(x,y);
+    }
+    x = to_famat_shallow(gen_1,x);
+  }
+  else if (typ(y) == t_INT)
+  {
+    if (!signe(y)) return x;
+    y = to_famat_shallow(gen_1,y);
+  }
+  x = merge_factor(x, y, NULL, &cmp_G);
+  if (lg(gel(x,1)) == 1) return gen_0;
+  return x;
+}
+GEN
+ZG_neg(GEN x)
+{
+  if (typ(x) == t_INT) return negi(x);
+  return mkmat2(gel(x,1),ZC_neg(gel(x,2)));
+}
+GEN
+ZG_sub(GEN x, GEN y) { return ZG_add(x, ZG_neg(y)); }
+
+/* x * c.[1], x in Z[G] */
+GEN
+ZG_Z_mul(GEN x, GEN c)
+{
+  if (is_pm1(c)) return signe(c) > 0? x: ZG_neg(x);
+  if (typ(x) == t_INT) return mulii(x,c);
+  return mkmat2(gel(x,1), ZC_Z_mul(gel(x,2), c));
+}
+
+GEN
+ZG_mul(GEN x, GEN y)
+{
+  GEN z, XG, XE;
+  long i, l;
+  if (typ(x) == t_INT) return ZG_Z_mul(y, x);
+  if (typ(y) == t_INT) return ZG_Z_mul(x, y);
+  XG = gel(x,1); XE = gel(x,2); l = lg(XG);
+  z = ZG_Z_mul(G_ZG_mul(gel(XG,1), y), gel(XE,1));
+  for (i = 2; i < l; i++)
+    z = ZG_add(z, ZG_Z_mul(G_ZG_mul(gel(XG,i), y), gel(XE,i)));
+  return z;
+}
+#if 0
+static GEN
+ZGV_add(GEN x, GEN y)
+{
+  long i, l;
+  GEN v = cgetg_copy(x, &l);
+  for (i = 1; i < l; i++) gel(v,i) = ZG_add(gel(x,i), gel(y,i));
+  return v;
+}
+static GEN
+ZGV_sub(GEN x, GEN y)
+{
+  long i, l;
+  GEN v = cgetg_copy(x, &l);
+  for (i = 1; i < l; i++) gel(v,i) = ZG_sub(gel(x,i), gel(y,i));
+  return v;
+}
+#endif
+GEN
+ZG_G_mul(GEN x, GEN y)
+{
+  long i, l;
+  GEN z, X;
+  if (typ(x) == t_INT) return to_famat_shallow(y, x);
+  X = gel(x,1);
+  z = cgetg_copy(X, &l);
+  for (i = 1; i < l; i++) gel(z,i) = gmul(gel(X,i), y);
+  return ZG_normalize( mkmat2(z, gel(x,2)) );
+}
+GEN
+G_ZG_mul(GEN x, GEN y)
+{
+  long i, l;
+  GEN z, Y;
+  if (typ(y) == t_INT) return to_famat_shallow(x, y);
+  Y = gel(y,1);
+  z = cgetg_copy(Y, &l);
+  for (i = 1; i < l; i++) gel(z,i) = gmul(x, gel(Y,i));
+  return ZG_normalize( mkmat2(z, gel(y,2)) );
+}
+GEN
+ZGC_G_mul(GEN v, GEN x)
+{
+  long i, l;
+  GEN w = cgetg_copy(v, &l);
+  for (i = 1; i < l; i++) gel(w,i) = ZG_G_mul(gel(v,i), x);
+  return w;
+}
+GEN
+G_ZGC_mul(GEN x, GEN v)
+{
+  long i, l;
+  GEN w = cgetg_copy(v, &l);
+  for (i = 1; i < l; i++) gel(w,i) = G_ZG_mul(gel(v,i), x);
+  return w;
+}
+GEN
+ZGC_Z_mul(GEN v, GEN x)
+{
+  long i, l;
+  GEN w = cgetg_copy(v, &l);
+  for (i = 1; i < l; i++) gel(w,i) = ZG_Z_mul(gel(v,i), x);
+  return w;
+}
diff --git a/src/basemath/ZV.c b/src/basemath/ZV.c
index 06a18cb..222c559 100644
--- a/src/basemath/ZV.c
+++ b/src/basemath/ZV.c
@@ -104,6 +104,19 @@ ZM_nc_mul_i(GEN x, GEN y, long c, long l)
   }
   return z;
 }
+
+/* x ZV, y a compatible zc. */
+GEN
+ZV_zc_mul(GEN x, GEN y)
+{
+  long j, l = lg(x);
+  pari_sp av = avma;
+  GEN s = mulis(gel(x,1),y[1]);
+  for (j=2; j<l; j++)
+    if (y[j]) s = addii(s, mulis(gel(x,j),y[j]));
+  return gerepileuptoint(av,s);
+}
+
 /* x non-empty ZM, y a compatible zc (dimension > 0). */
 static GEN
 ZM_zc_mul_i(GEN x, GEN y, long c, long l)
@@ -246,6 +259,35 @@ ZM_transmultosym(GEN x, GEN y)
   }
   return M;
 }
+/* x~ * y */
+GEN
+ZM_transmul(GEN x, GEN y)
+{
+  long i, j, l, lx, ly = lg(y);
+  GEN M;
+  if (ly == 1) return cgetg(1,t_MAT);
+  lx = lg(x);
+  l = lgcols(y);
+  if (lgcols(x) != l) pari_err_OP("operation 'ZM_transmul'", x,y);
+  M = cgetg(ly, t_MAT);
+  for (i=1; i<ly; i++)
+  {
+    GEN yi = gel(y,i), c = cgetg(lx,t_COL);
+    gel(M,i) = c;
+    for (j=1; j<lx; j++) gel(c,j) = ZV_dotproduct_i(yi,gel(x,j),l);
+  }
+  return M;
+}
+GEN
+ZM_sqr(GEN x)
+{
+  long j, l, lx=lg(x);
+  GEN z;
+  if (lx==1) return cgetg(1,t_MAT);
+  l = lgcols(x); z = cgetg(lx,t_MAT);
+  for (j=1; j<lx; j++) gel(z,j) = ZM_ZC_mul_i(x, gel(x,j), lx, l);
+  return z;
+}
 GEN
 ZM_ZC_mul(GEN x, GEN y)
 {
@@ -253,6 +295,22 @@ ZM_ZC_mul(GEN x, GEN y)
   return lx==1? cgetg(1,t_COL): ZM_ZC_mul_i(x, y, lx, lgcols(x));
 }
 
+GEN
+ZM_Z_div(GEN X, GEN c)
+{
+  long i, j, h, l = lg(X);
+  GEN A = cgetg(l, t_MAT);
+  if (l == 1) return A;
+  h = lgcols(X);
+  for (j=1; j<l; j++)
+  {
+    GEN a = cgetg(h, t_COL), x = gel(X, j);
+    for (i = 1; i < h; i++) gel(a,i) = gred_frac2(gel(x,i), c);
+    gel(A,j) = a;
+  }
+  return A;
+}
+
 long
 zv_dotproduct(GEN x, GEN y)
 {
@@ -616,7 +674,7 @@ zv_to_Flv(GEN z, ulong p)
 {
   long i, l = lg(z);
   GEN x = cgetg(l,t_VECSMALL);
-  for (i=1; i<l; i++) x[i] = smodss(z[i],p);
+  for (i=1; i<l; i++) x[i] = umodsu(z[i], p);
   return x;
 }
 
@@ -872,6 +930,21 @@ ZM_isidentity(GEN x)
   return 1;
 }
 
+long
+ZC_is_ei(GEN x)
+{
+  long i, j = 0, l = lg(x);
+  for (i = 1; i < l; i++)
+  {
+    GEN c = gel(x,i);
+    long s = signe(c);
+    if (!s) continue;
+    if (s < 0 || !is_pm1(c) || j) return 0;
+    j = i;
+  }
+  return j;
+}
+
 /********************************************************************/
 /**                                                                **/
 /**                       MISCELLANEOUS                            **/
@@ -899,7 +972,9 @@ ZV_abscmp(GEN x, GEN y)
 long
 zv_content(GEN x)
 {
-  long i, l = lg(x), s = labs(x[1]);
+  long i, s, l = lg(x);
+  if (l == 1) return 0;
+  s = labs(x[1]);
   for (i=2; i<l && s!=1; i++) s = cgcd(x[i],s);
   return s;
 }
@@ -909,7 +984,7 @@ ZV_content(GEN x)
   long i, l = lg(x);
   pari_sp av = avma;
   GEN c;
-  if (l == 1) return gen_1;
+  if (l == 1) return gen_0;
   if (l == 2) return absi(gel(x,1));
   c = gel(x,1);
   for (i = 2; i < l; i++)
diff --git a/src/basemath/ZX.c b/src/basemath/ZX.c
index ea274f7..a6a7096 100644
--- a/src/basemath/ZX.c
+++ b/src/basemath/ZX.c
@@ -300,6 +300,38 @@ ZX_valrem(GEN x, GEN *Z)
   return vx;
 }
 
+GEN
+ZX_div_by_X_1(GEN a, GEN *r)
+{
+  long l = lg(a), i;
+  GEN a0, z0, z = cgetg(l-1, t_POL);
+  z[1] = a[1];
+  a0 = a + l-1;
+  z0 = z + l-2; *z0 = *a0--;
+  for (i=l-3; i>1; i--) /* z[i] = a[i+1] + z[i+1] */
+  {
+    GEN t = addii(gel(a0--,0), gel(z0--,0));
+    gel(z0,0) = t;
+  }
+  if (r) *r = addii(gel(a0,0), gel(z0,0));
+  return z;
+}
+
+/* Return 2^(n degpol(P))  P(x >> n), not memory clean if P is a ZX */
+GEN
+ZX_rescale2n(GEN P, long n)
+{
+  long i, l = lg(P), ni = n;
+  GEN Q = cgetg(l,t_POL);
+  Q[l-1] = P[l-1];
+  for (i=l-2; i>=2; i--)
+  {
+    gel(Q,i) = shifti(gel(P,i), ni);
+    ni += n;
+  }
+  Q[1] = P[1]; return Q;
+}
+
 /* Return h^deg(P) P(x / h), not memory clean. h integer, P ZX */
 GEN
 ZX_rescale(GEN P, GEN h)
@@ -721,6 +753,33 @@ ZXX_max_lg(GEN x)
 }
 
 GEN
+ZXX_Z_mul(GEN y, GEN x)
+{
+  long i, l = lg(y);
+  GEN z = cgetg(l,t_POL); z[1] = y[1];
+  for(i=2; i<l; i++)
+    if(typ(gel(y,i))==t_INT)
+      gel(z,i) = mulii(gel(y,i),x);
+    else
+      gel(z,i) = ZX_Z_mul(gel(y,i),x);
+  return z;
+}
+
+GEN
+ZXX_Z_add_shallow(GEN x, GEN y)
+{
+  long i, l = lg(x);
+  GEN z, a;
+  if (signe(x)==0) return scalarpol(y,varn(x));
+  z = cgetg(l,t_POL); z[1] = x[1];
+  a = gel(x,2);
+  gel(z, 2) = typ(a)==t_INT? addii(a,y): ZX_Z_add(a,y);
+  for(i=3; i<l; i++)
+    gel(z,i) = gel(x,i);
+  return z;
+}
+
+GEN
 ZXX_Z_divexact(GEN y, GEN x)
 {
   long i, l = lg(y);
diff --git a/src/basemath/alglin1.c b/src/basemath/alglin1.c
index d3868dc..646a8e9 100644
--- a/src/basemath/alglin1.c
+++ b/src/basemath/alglin1.c
@@ -29,7 +29,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 static void
 gerepile_mat(pari_sp av, pari_sp tetpil, GEN x, long k, long m, long n, long t)
 {
-  pari_sp A;
+  pari_sp A, bot = pari_mainstack->bot;
   long u, i;
   size_t dec;
 
@@ -77,13 +77,13 @@ _copy(void *E, GEN x)
 static void
 gerepile_gauss_ker(GEN x, long k, long t, pari_sp av)
 {
-  return gen_gerepile_gauss_ker(x, k, t, av, NULL, &_copy);
+  gen_gerepile_gauss_ker(x, k, t, av, NULL, &_copy);
 }
 
 static void
 gerepile_gauss(GEN x,long k,long t,pari_sp av, long j, GEN c)
 {
-  pari_sp tetpil = avma, A;
+  pari_sp tetpil = avma, A, bot;
   long u,i, n = lg(x)-1, m = n? nbrows(x): 0;
   size_t dec;
 
@@ -95,6 +95,7 @@ gerepile_gauss(GEN x,long k,long t,pari_sp av, long j, GEN c)
       for (i=k+1; i<=n; i++) COPY(gcoeff(x,u,i));
 
   (void)gerepile(av,tetpil,NULL); dec = av-tetpil;
+  bot = pari_mainstack->bot;
   for (u=t+1; u<=m; u++)
     if (u==j || !c[u])
     {
@@ -118,7 +119,7 @@ gerepile_gauss(GEN x,long k,long t,pari_sp av, long j, GEN c)
 GEN
 gen_ker(GEN x, long deplin, void *E, const struct bb_field *ff)
 {
-  pari_sp av0 = avma, av, lim, tetpil;
+  pari_sp av0 = avma, av, tetpil;
   GEN y, c, d;
   long i, j, k, r, t, n, m;
 
@@ -127,7 +128,7 @@ gen_ker(GEN x, long deplin, void *E, const struct bb_field *ff)
   x = RgM_shallowcopy(x);
   c = zero_zv(m);
   d=new_chunk(n+1);
-  av=avma; lim=stack_lim(av,1);
+  av=avma;
   for (k=1; k<=n; k++)
   {
     for (j=1; j<=m; j++)
@@ -165,7 +166,7 @@ gen_ker(GEN x, long deplin, void *E, const struct bb_field *ff)
         gcoeff(x,t,k) = ff->s(E,0);
         for (i=k+1; i<=n; i++)
            gcoeff(x,t,i) = ff->add(E, gcoeff(x,t,i), ff->mul(E,piv,gcoeff(x,j,i)));
-        if (low_stack(lim, stack_lim(av,1)))
+        if (gc_needed(av,1))
           gen_gerepile_gauss_ker(x,k,t,av,E,ff->red);
       }
     }
@@ -194,7 +195,7 @@ gen_ker(GEN x, long deplin, void *E, const struct bb_field *ff)
 GEN
 gen_Gauss_pivot(GEN x, long *rr, void *E, const struct bb_field *ff)
 {
-  pari_sp av, lim;
+  pari_sp av;
   GEN c, d;
   long i, j, k, r, t, m, n = lg(x)-1;
 
@@ -204,7 +205,7 @@ gen_Gauss_pivot(GEN x, long *rr, void *E, const struct bb_field *ff)
   d = cgetg(n+1, t_VECSMALL);
   x = RgM_shallowcopy(x);
   c = zero_zv(m);
-  av=avma; lim=stack_lim(av,1);
+  av=avma;
   for (k=1; k<=n; k++)
   {
     for (j=1; j<=m; j++)
@@ -229,7 +230,7 @@ gen_Gauss_pivot(GEN x, long *rr, void *E, const struct bb_field *ff)
         gcoeff(x,t,k) = g0;
         for (i=k+1; i<=n; i++)
           gcoeff(x,t,i) = ff->add(E,gcoeff(x,t,i), ff->mul(E,piv,gcoeff(x,j,i)));
-        if (low_stack(lim, stack_lim(av,1)))
+        if (gc_needed(av,1))
           gerepile_gauss(x,k,t,av,j,c);
       }
       for (i=k; i<=n; i++) gcoeff(x,j,i) = g0; /* dummy */
@@ -241,7 +242,7 @@ gen_Gauss_pivot(GEN x, long *rr, void *E, const struct bb_field *ff)
 GEN
 gen_det(GEN a, void *E, const struct bb_field *ff)
 {
-  pari_sp av = avma, lim = stack_lim(av,1);
+  pari_sp av = avma;
   long i,j,k, s = 1, nbco = lg(a)-1;
   GEN q, x = ff->s(E,1);
   a = RgM_shallowcopy(a);
@@ -271,7 +272,7 @@ gen_det(GEN a, void *E, const struct bb_field *ff)
       for (j=i+1; j<=nbco; j++)
       {
         gcoeff(a,j,k) = ff->add(E, gcoeff(a,j,k), ff->mul(E,m,gcoeff(a,j,i)));
-        if (low_stack(lim, stack_lim(av,1)))
+        if (gc_needed(av,1))
         {
           if(DEBUGMEM>1) pari_warn(warnmem,"det. col = %ld",i);
           gerepileall(av,4, &a,&x,&q,&m);
@@ -314,7 +315,7 @@ gen_Gauss(GEN a, GEN b, void *E, const struct bb_field *ff)
 {
   long i, j, k, li, bco, aco;
   GEN u, g0 = ff->s(E,0);
-  pari_sp av = avma, lim = stack_lim(av,1);
+  pari_sp av = avma;
   a = RgM_shallowcopy(a);
   b = RgM_shallowcopy(b);
   aco = lg(a)-1; bco = lg(b)-1; li = nbrows(a);
@@ -346,7 +347,7 @@ gen_Gauss(GEN a, GEN b, void *E, const struct bb_field *ff)
       for (j=i+1; j<=aco; j++) _gen_addmul(gel(a,j),k,i,m,E,ff);
       for (j=1  ; j<=bco; j++) _gen_addmul(gel(b,j),k,i,m,E,ff);
     }
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"gen_Gauss. i=%ld",i);
       gerepileall(av,2, &a,&b);
@@ -381,7 +382,7 @@ GEN
 gen_matcolmul(GEN A, GEN B, void *E, const struct bb_field *ff)
 {
   ulong lgA = lg(A);
-  if (lgA != lg(B))
+  if (lgA != (ulong)lg(B))
     pari_err_OP("operation 'gen_matcolmul'", A, B);
   if (lgA == 1)
     return cgetg(1, t_COL);
@@ -502,35 +503,35 @@ F2m_ker_sp(GEN x, long deplin)
 static void /* assume m < p */
 _Fl_submul(GEN b, long k, long i, ulong m, ulong p)
 {
-  b[k] = Fl_sub(b[k], Fl_mul(m, b[i], p), p);
+  uel(b,k) = Fl_sub(uel(b,k), Fl_mul(m, uel(b,i), p), p);
 }
 static void /* same m = 1 */
 _Fl_sub(GEN b, long k, long i, ulong p)
 {
-  b[k] = Fl_sub(b[k], b[i], p);
+  uel(b,k) = Fl_sub(uel(b,k), uel(b,i), p);
 }
 static void /* assume m < p && SMALL_ULONG(p) && (! (b[i] & b[k] & HIGHMASK)) */
 _Fl_addmul_OK(GEN b, long k, long i, ulong m, ulong p)
 {
   uel(b,k) += m * uel(b,i);
-  if (b[k] & HIGHMASK) uel(b,k) %= p;
+  if (uel(b,k) & HIGHMASK) uel(b,k) %= p;
 }
 static void /* assume SMALL_ULONG(p) && (! (b[i] & b[k] & HIGHMASK)) */
 _Fl_add_OK(GEN b, long k, long i, ulong p)
 {
   uel(b,k) += uel(b,i);
-  if (b[k] & HIGHMASK) uel(b,k) %= p;
+  if (uel(b,k) & HIGHMASK) uel(b,k) %= p;
 }
 static void /* assume m < p */
 _Fl_addmul(GEN b, long k, long i, ulong m, ulong p)
 {
   uel(b,i) %= p;
-  b[k] = Fl_add(b[k], Fl_mul(m, b[i], p), p);
+  uel(b,k) = Fl_add(uel(b,k), Fl_mul(m, uel(b,i), p), p);
 }
 static void /* same m = 1 */
 _Fl_add(GEN b, long k, long i, ulong p)
 {
-  b[k] = Fl_add(b[k], b[i], p);
+  uel(b,k) = Fl_add(uel(b,k), uel(b,i), p);
 }
 
 /* in place, destroy x */
@@ -608,10 +609,10 @@ Flm_ker_sp(GEN x, ulong p, long deplin)
     gel(y,j) = C; while (d[k]) k++;
     for (i=1; i<k; i++)
       if (d[i])
-        C[i] = ucoeff(x,d[i],k) % p;
+        uel(C,i) = ucoeff(x,d[i],k) % p;
       else
-        C[i] = 0;
-    C[k] = 1; for (i=k+1; i<=n; i++) C[i] = 0;
+        uel(C,i) = 0UL;
+    uel(C,k) = 1UL; for (i=k+1; i<=n; i++) uel(C,i) = 0UL;
   }
   return y;
 }
@@ -625,7 +626,7 @@ FpM_intersect(GEN x, GEN y, GEN p)
 
   if (lx==1 || lg(y)==1) return cgetg(1,t_MAT);
   z = FpM_ker(shallowconcat(x,y), p);
-  for (j=lg(z)-1; j; j--) setlg(z[j],lx);
+  for (j=lg(z)-1; j; j--) setlg(gel(z,j),lx);
   return gerepileupto(av, FpM_mul(x,z,p));
 }
 
@@ -747,7 +748,7 @@ FpM_init(GEN a, GEN p, ulong *pp)
 {
   if (lgefint(p) == 3)
   {
-    *pp = (ulong)p[2];
+    *pp = uel(p,2);
     return (*pp==2)? ZM_to_F2m(a): ZM_to_Flm(a, *pp);
   }
   *pp = 0; return a;
@@ -757,7 +758,7 @@ RgM_Fp_init(GEN a, GEN p, ulong *pp)
 {
   if (lgefint(p) == 3)
   {
-    *pp = (ulong)p[2];
+    *pp = uel(p,2);
     return (*pp==2)? RgM_to_F2m(a): RgM_to_Flm(a, *pp);
   }
   *pp = 0; return RgM_to_FpM(a,p);
@@ -975,7 +976,17 @@ FlxqM_FlxqC_mul(GEN A, GEN B, GEN T, unsigned long p) {
 GEN
 FlxqM_mul(GEN A, GEN B, GEN T, unsigned long p) {
   void *E;
-  const struct bb_field *ff = get_Flxq_field(&E, T, p);
+  const struct bb_field *ff;
+  long n = lg(A) - 1;
+
+  if (n == 0)
+    return cgetg(1, t_MAT);
+  if (n > 1) {
+    GEN C = FlxqM_mul_Kronecker(A, B, T, p);
+    if (C != NULL)
+      return C;
+  }
+  ff = get_Flxq_field(&E, T, p);
   return gen_matmul(A, B, E, ff);
 }
 
@@ -998,10 +1009,9 @@ GEN
 F2xqM_inv(GEN a, GEN T)
 {
   pari_sp av = avma;
-  long n = lg(a)-1;
   GEN u;
-  if (!n) { avma = av; return cgetg(1, t_MAT); }
-  u = F2xqM_gauss_gen(a, matid_F2xqM(n,T), T);
+  if (lg(a) == 1) { avma = av; return cgetg(1, t_MAT); }
+  u = F2xqM_gauss_gen(a, matid_F2xqM(nbrows(a),T), T);
   if (!u) { avma = av; return NULL; }
   return gerepilecopy(av, u);
 }
@@ -1035,7 +1045,7 @@ FqM_gauss_pivot(GEN x, GEN T, GEN p, long *rr)
   if (lgefint(p) == 3)
   {
     pari_sp av = avma;
-    ulong pp = (ulong)p[2];
+    ulong pp = uel(p,2);
     GEN Tp = ZXT_to_FlxT(T, pp);
     GEN d = FlxqM_gauss_pivot(FqM_to_FlxM(x, T, p), Tp, pp, rr);
     return d ? gerepileuptoleaf(av, d): d;
@@ -1376,7 +1386,7 @@ Fl_get_col_OK(GEN a, GEN b, long li, ulong p)
     }
     m %= p;
     if (m) m = ((p-m) * ucoeff(a,i,i)) % p;
-    u[i] = m;
+    uel(u,i) = m;
   }
   return u;
 }
@@ -1384,17 +1394,17 @@ static GEN
 Fl_get_col(GEN a, GEN b, long li, ulong p)
 {
   GEN u = cgetg(li+1,t_VECSMALL);
-  ulong m = b[li] % p;
+  ulong m = uel(b,li) % p;
   long i,j;
 
-  u[li] = Fl_mul(m, ucoeff(a,li,li), p);
+  uel(u,li) = Fl_mul(m, ucoeff(a,li,li), p);
   for (i=li-1; i>0; i--)
   {
     m = b[i]%p;
     for (j = i+1; j <= li; j++)
-      m = Fl_sub(m, Fl_mul(ucoeff(a,i,j), u[j], p), p);
+      m = Fl_sub(m, Fl_mul(ucoeff(a,i,j), uel(u,j), p), p);
     if (m) m = Fl_mul(m, ucoeff(a,i,i), p);
-    u[i] = m;
+    uel(u,i) = m;
   }
   return u;
 }
@@ -1526,13 +1536,14 @@ is_modular_solve(GEN a, GEN b, GEN *u)
 GEN
 RgM_solve(GEN a, GEN b)
 {
-  pari_sp av = avma, lim = stack_lim(av,1);
+  pari_sp av = avma;
   long i, j, k, li, bco, aco;
   int iscol;
   pivot_fun pivot;
-  GEN p, u, data;
+  GEN p, u, data, ff = NULL;
 
   if (is_modular_solve(a,b,&u)) return gerepileupto(av, u);
+  if (!b && RgM_is_FFM(a, &ff)) return FFM_inv(a, ff);
   avma = av;
 
   if (lg(a)-1 == 2 && nbrows(a) == 2) {
@@ -1581,7 +1592,7 @@ RgM_solve(GEN a, GEN b)
         for (j=1;   j<=bco; j++) _submul(gel(b,j),k,i,m);
       }
     }
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"gauss. i=%ld",i);
       gerepileall(av,2, &a,&b);
@@ -1756,6 +1767,23 @@ gauss(GEN a, GEN b)
   return z;
 }
 
+static GEN
+F2_get_col(GEN b, GEN d, long li, long aco)
+{
+  long i, l = nbits2lg(aco);
+  GEN u = cgetg(l, t_VECSMALL);
+  u[1] = aco;
+  for (i = 1; i <= li; i++)
+    if (d[i]) /* d[i] can still be 0 if li > aco */
+    {
+      if (F2v_coeff(b, i))
+        F2v_set(u, d[i]);
+      else
+        F2v_clear(u, d[i]);
+    }
+  return u;
+}
+
 /* destroy a, b */
 static GEN
 F2m_gauss_sp(GEN a, GEN b)
@@ -1764,7 +1792,7 @@ F2m_gauss_sp(GEN a, GEN b)
   GEN u, d;
 
   if (!aco) return cgetg(1,t_MAT);
-  li = coeff(a,1,1);
+  li = gel(a,1)[1];
   d = zero_Flv(li);
   bco = lg(b)-1;
   for (i=1; i<=aco; i++)
@@ -1778,37 +1806,25 @@ F2m_gauss_sp(GEN a, GEN b)
     if (k > li) return NULL;
     d[k] = i;
 
-    /* Clear k-th row but column-wise */
+    /* Clear k-th row but column-wise instead of line-wise */
+    /*  a_ij -= a_i1*a1j/a_11
+       line-wise grouping:  L_j -= a_1j/a_11*L_1
+       column-wise:         C_i -= a_i1/a_11*C_1
+    */
     F2v_clear(ai,k);
     for (l=1; l<=aco; l++)
     {
       GEN al = gel(a,l);
-      if (!F2v_coeff(al,k)) continue;
-
-      F2v_add_inplace(al,ai);
+      if (F2v_coeff(al,k)) F2v_add_inplace(al,ai);
     }
     for (l=1; l<=bco; l++)
     {
-      GEN al = gel(b,l);
-      if (!F2v_coeff(al,k)) continue;
-
-      F2v_add_inplace(al,ai);
+      GEN bl = gel(b,l);
+      if (F2v_coeff(bl,k)) F2v_add_inplace(bl,ai);
     }
   }
-  u = gcopy(b);
-  for (j = 1; j <= bco; j++)
-  {
-    GEN bj = gel(b, j), uj = gel(u, j);
-
-    for (i = 1; i <= li; i++)
-      if (d[i] && d[i] != i) /* can d[i] still be 0 ? */
-      {
-        if (F2v_coeff(bj, i))
-          F2v_set(uj, d[i]);
-        else
-          F2v_clear(uj, d[i]);
-      }
-  }
+  u = cgetg(bco+1,t_MAT);
+  for (j = 1; j <= bco; j++) gel(u,j) = F2_get_col(gel(b,j), d, li, aco);
   return u;
 }
 
@@ -1833,7 +1849,7 @@ F2m_inv(GEN a)
 {
   pari_sp av = avma;
   if (lg(a) == 1) return cgetg(1,t_MAT);
-  return gerepileupto(av, F2m_gauss_sp(F2m_copy(a), matid_F2m(lg(a)-1)));
+  return gerepileupto(av, F2m_gauss_sp(F2m_copy(a), matid_F2m(gel(a,1)[1])));
 }
 
 /* destroy a, b */
@@ -1941,7 +1957,8 @@ Flm_gauss(GEN a, GEN b, ulong p) {
 }
 static GEN
 Flm_inv_sp(GEN a, ulong *detp, ulong p) {
-  return Flm_gauss_sp(a, matid_Flm(lg(a)-1), detp, p);
+  if (lg(a) == 1) return cgetg(1,t_MAT);
+  return Flm_gauss_sp(a, matid_Flm(nbrows(a)), detp, p);
 }
 GEN
 Flm_inv(GEN a, ulong p) {
@@ -1962,11 +1979,11 @@ FpM_gauss_gen(GEN a, GEN b, GEN p)
   const struct bb_field *S = get_Fp_field(&E,p);
   return gen_Gauss(a,b, E, S);
 }
-/* a an FpM; b an FpM or NULL (replace by identity) */
+/* a an FpM, lg(a)>1; b an FpM or NULL (replace by identity) */
 static GEN
 FpM_gauss_i(GEN a, GEN b, GEN p, ulong *pp)
 {
-  long n = lg(a)-1;
+  long n = nbrows(a);
   a = FpM_init(a,p,pp);
   switch(*pp)
   {
@@ -2056,10 +2073,9 @@ GEN
 FlxqM_inv(GEN a, GEN T, ulong p)
 {
   pari_sp av = avma;
-  long n = lg(a)-1;
   GEN u;
-  if (!n) { avma = av; return cgetg(1, t_MAT); }
-  u = FlxqM_gauss_gen(a, matid_FlxqM(n,T,p), T,p);
+  if (lg(a) == 1) { avma = av; return cgetg(1, t_MAT); }
+  u = FlxqM_gauss_gen(a, matid_FlxqM(nbrows(a),T,p), T,p);
   if (!u) { avma = av; return NULL; }
   return gerepilecopy(av, u);
 }
@@ -2098,10 +2114,9 @@ FqM_inv(GEN a, GEN T, GEN p)
 {
   pari_sp av = avma;
   GEN u;
-  long n;
   if (!T) return FpM_inv(a,p);
-  n = lg(a)-1; if (!n) return cgetg(1, t_MAT);
-  u = FqM_gauss_gen(a,matid(n),T,p);
+  if (lg(a) == 1) return cgetg(1, t_MAT);
+  u = FqM_gauss_gen(a,matid(nbrows(a)),T,p);
   if (!u) { avma = av; return NULL; }
   return gerepilecopy(av, u);
 }
@@ -2183,7 +2198,7 @@ ZM_gauss(GEN a, GEN b0)
 GEN
 ZM_inv(GEN M, GEN dM)
 {
-  pari_sp av2, av = avma, lim = stack_lim(av,1);
+  pari_sp av2, av = avma;
   GEN Hp,q,H;
   ulong p;
   long lM = lg(M), stable = 0;
@@ -2238,7 +2253,7 @@ ZM_inv(GEN M, GEN dM)
       { if (ZM_isidentity(ZM_mul(M, H))) break; }
     }
 
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"ZM_inv");
       gerepileall(av2, 2, &H, &q);
@@ -2274,7 +2289,7 @@ detint(GEN A)
 GEN
 ZM_detmult(GEN A)
 {
-  pari_sp av1, av = avma, lim = stack_lim(av,1);
+  pari_sp av1, av = avma;
   GEN B, c, v, piv;
   long rg, i, j, k, m, n = lg(A) - 1;
 
@@ -2313,11 +2328,11 @@ ZM_detmult(GEN A)
       {
         /* improve further; at this point c[i] is set for all i != t */
         gcoeff(B,t,t) = piv; v = centermod(gel(B,t), det);
-        av1 = avma; lim = stack_lim(av1,1);
+        av1 = avma;
         for ( ; k<=n; k++)
         {
           det = gcdii(det, ZV_dotproduct(v, gel(A,k)));
-          if (low_stack(lim, stack_lim(av1,1)))
+          if (gc_needed(av1,1))
           {
             if(DEBUGMEM>1) pari_warn(warnmem,"detint end. k=%ld",k);
             det = gerepileuptoint(av1, det);
@@ -2344,7 +2359,7 @@ ZM_detmult(GEN A)
         }
     }
     c[t] = k;
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"detint. k=%ld",k);
       gerepileall(av1, 2, &piv,&B); v = zerovec(m);
@@ -2380,7 +2395,7 @@ reducemodlll(GEN x,GEN y)
 GEN
 keri(GEN x)
 {
-  pari_sp av, av0, lim;
+  pari_sp av, av0;
   GEN c, l, y, p, pp;
   long i, j, k, r, t, n, m;
 
@@ -2390,7 +2405,7 @@ keri(GEN x)
   x = RgM_shallowcopy(x);
   c = zero_zv(m);
   l = cgetg(n+1, t_VECSMALL);
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
   for (r=0, p=gen_1, k=1; k<=n; k++)
   {
     j = 1;
@@ -2416,7 +2431,7 @@ keri(GEN x)
             GEN p1 = subii(mulii(p,gcoeff(x,t,i)), mulii(q,gcoeff(x,j,i)));
             gcoeff(x,t,i) = gerepileuptoint(av1, diviiexact(p1,p0));
           }
-          if (low_stack(lim, stack_lim(av,1)))
+          if (gc_needed(av,1))
           {
             GEN _p0 = gclone(p0);
             GEN _p  = gclone(p);
@@ -2565,7 +2580,7 @@ static GEN
 gauss_pivot_ker(GEN x, GEN x0, GEN *dd, long *rr)
 {
   GEN c, d, p, data;
-  pari_sp av, lim;
+  pari_sp av;
   long i, j, k, r, t, n, m;
   pivot_fun pivot;
 
@@ -2575,7 +2590,7 @@ gauss_pivot_ker(GEN x, GEN x0, GEN *dd, long *rr)
   x = RgM_shallowcopy(x);
   c = zero_zv(m);
   d = cgetg(n+1,t_VECSMALL);
-  av=avma; lim=stack_lim(av,1);
+  av=avma;
   for (k=1; k<=n; k++)
   {
     j = pivot(x, data, k, c);
@@ -2597,7 +2612,7 @@ gauss_pivot_ker(GEN x, GEN x0, GEN *dd, long *rr)
           p = gcoeff(x,t,k); gcoeff(x,t,k) = gen_0;
           for (i=k+1; i<=n; i++)
             gcoeff(x,t,i) = gadd(gcoeff(x,t,i),gmul(p,gcoeff(x,j,i)));
-          if (low_stack(lim, stack_lim(av,1))) gerepile_gauss_ker(x,k,t,av);
+          if (gc_needed(av,1)) gerepile_gauss_ker(x,k,t,av);
         }
     }
   }
@@ -2618,7 +2633,7 @@ RgM_pivots(GEN x0, GEN data, long *rr, pivot_fun pivot)
 {
   GEN x, c, d, p;
   long i, j, k, r, t, m, n = lg(x0)-1;
-  pari_sp av, lim;
+  pari_sp av;
 
   if (RgM_is_ZM(x0)) return ZM_pivots(x0, rr);
   if (!n) { *rr = 0; return NULL; }
@@ -2627,7 +2642,7 @@ RgM_pivots(GEN x0, GEN data, long *rr, pivot_fun pivot)
   x = RgM_shallowcopy(x0);
   m = nbrows(x); r = 0;
   c = zero_zv(m);
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
   for (k=1; k<=n; k++)
   {
     j = pivot(x, data, k, c);
@@ -2643,7 +2658,7 @@ RgM_pivots(GEN x0, GEN data, long *rr, pivot_fun pivot)
           p = gcoeff(x,t,k); gcoeff(x,t,k) = gen_0;
           for (i=k+1; i<=n; i++)
             gcoeff(x,t,i) = gadd(gcoeff(x,t,i), gmul(p, gcoeff(x,j,i)));
-          if (low_stack(lim, stack_lim(av,1))) gerepile_gauss(x,k,t,av,j,c);
+          if (gc_needed(av,1)) gerepile_gauss(x,k,t,av,j,c);
         }
       for (i=k; i<=n; i++) gcoeff(x,j,i) = gen_0; /* dummy */
     }
@@ -2661,7 +2676,7 @@ ZM_count_0_cols(GEN M)
 }
 
 static void indexrank_all(long m, long n, long r, GEN d, GEN *prow, GEN *pcol);
-/* As above, integer entries */
+/* As RgM_pivots, integer entries */
 GEN
 ZM_pivots(GEN M0, long *rr)
 {
@@ -2677,7 +2692,7 @@ ZM_pivots(GEN M0, long *rr)
   if (n == zc) { *rr = zc; return zero_zv(n); }
 
   m = nbrows(M0);
-  rmin = (m < n-zc) ? n-m : zc;
+  rmin = maxss(zc, n-m);
   init_modular(&S);
   imax = (n < (1<<4))? 1: (n>>3); /* heuristic */
 
@@ -3439,6 +3454,15 @@ ZM_rank(GEN x) {
   (void)ZM_pivots(x,&r);
   avma = av; return lg(x)-1-r;
 }
+GEN
+ZM_indexrank(GEN x) {
+  pari_sp av = avma;
+  long r;
+  GEN d;
+  init_indexrank(x);
+  d = ZM_pivots(x,&r);
+  avma = av; return indexrank0(lg(x)-1, r, d);
+}
 
 /*******************************************************************/
 /*                                                                 */
@@ -3688,33 +3712,24 @@ ZM_det3(GEN M)
   GEN a = gcoeff(M,1,1), b = gcoeff(M,1,2), c = gcoeff(M,1,3);
   GEN d = gcoeff(M,2,1), e = gcoeff(M,2,2), f = gcoeff(M,2,3);
   GEN g = gcoeff(M,3,1), h = gcoeff(M,3,2), i = gcoeff(M,3,3);
-  GEN p1,p2,p3,p4,p5,p6, D;
-  if (!signe(i)) p1 = p5 = gen_0;
-  else
+  GEN t, D = signe(i)? mulii(subii(mulii(a,e), mulii(b,d)), i): gen_0;
+  if (signe(g))
   {
-    p1 = mulii(mulii(a,e), i);
-    p5 = mulii(mulii(b,d), i);
+    t = mulii(subii(mulii(b,f), mulii(c,e)), g);
+    D = addii(D, t);
   }
-  if (!signe(g)) p2 = p6 = gen_0;
-  else
-  {
-    p2 = mulii(mulii(b,f), g);
-    p6 = mulii(mulii(c,e), g);
-  }
-  if (!signe(h)) p3 = p4 = gen_0;
-  else
+  if (signe(h))
   {
-    p3 = mulii(mulii(c,d), h);
-    p4 = mulii(mulii(a,f), h);
+    t = mulii(subii(mulii(c,d), mulii(a,f)), h);
+    D = addii(D, t);
   }
-  D = subii(addii(p1,addii(p2,p3)), addii(p4,addii(p5,p6)));
   return gerepileuptoint(av, D);
 }
 
 static GEN
 det_simple_gauss(GEN a, GEN data, pivot_fun pivot)
 {
-  pari_sp av = avma, lim = stack_lim(av,3);
+  pari_sp av = avma;
   long i,j,k, s = 1, nbco = lg(a)-1;
   GEN p, x = gen_1;
 
@@ -3740,7 +3755,7 @@ det_simple_gauss(GEN a, GEN data, pivot_fun pivot)
       for (j=i+1; j<=nbco; j++)
       {
         gcoeff(a,j,k) = gsub(gcoeff(a,j,k), gmul(m,gcoeff(a,j,i)));
-        if (low_stack(lim, stack_lim(av,3)))
+        if (gc_needed(av,3))
         {
           if(DEBUGMEM>1) pari_warn(warnmem,"det. col = %ld",i);
           gerepileall(av,2, &a,&x);
@@ -3782,7 +3797,7 @@ mydiv(GEN x, GEN y)
 static GEN
 det_bareiss(GEN a)
 {
-  pari_sp av = avma, lim = stack_lim(av,2);
+  pari_sp av = avma;
   long nbco = lg(a)-1,i,j,k,s = 1;
   GEN p, pprec;
 
@@ -3827,7 +3842,7 @@ det_bareiss(GEN a)
           GEN p1 = gsub(gmul(p,gel(ck,j)), gmul(m,gel(ci,j)));
           if (diveuc) p1 = mydiv(p1,pprec);
           gel(ck,j) = gerepileupto(av2, p1);
-          if (low_stack(lim,stack_lim(av,2)))
+          if (gc_needed(av,2))
           {
             if(DEBUGMEM>1) pari_warn(warnmem,"det. col = %ld",i);
             gerepileall(av,2, &a,&pprec);
diff --git a/src/basemath/alglin2.c b/src/basemath/alglin2.c
index 35a41aa..a4b98f6 100644
--- a/src/basemath/alglin2.c
+++ b/src/basemath/alglin2.c
@@ -25,6 +25,73 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 /*                                                                 */
 /*******************************************************************/
 
+static GEN
+Flm_charpoly_i(GEN x, ulong p)
+{
+  long lx = lg(x), r, i;
+  GEN H, y = cgetg(lx+1, t_VEC);
+  gel(y,1) = pol1_Flx(0); H = Flm_hess(x, p);
+  for (r = 1; r < lx; r++)
+  {
+    pari_sp av2 = avma;
+    ulong a = 1;
+    GEN z, b = zero_Flx(0);
+    for (i = r-1; i; i--)
+    {
+      a = Fl_mul(a, ucoeff(H,i+1,i), p);
+      if (!a) break;
+      b = Flx_add(b, Flx_Fl_mul(gel(y,i), Fl_mul(a,ucoeff(H,i,r),p), p), p);
+    }
+    z = Flx_sub(Flx_shift(gel(y,r), 1),
+                Flx_Fl_mul(gel(y,r), ucoeff(H,r,r), p), p);
+    /* (X - H[r,r])y[r] - b */
+    gel(y,r+1) = gerepileuptoleaf(av2, Flx_sub(z, b, p));
+  }
+  return gel(y,lx);
+}
+
+GEN
+Flm_charpoly(GEN x, ulong p)
+{
+  pari_sp av = avma;
+  return gerepileuptoleaf(av, Flm_charpoly_i(x,p));
+}
+
+GEN
+FpM_charpoly(GEN x, GEN p)
+{
+  pari_sp av = avma;
+  long lx, r, i;
+  GEN y, H;
+
+  if (lgefint(p) == 3)
+  {
+    ulong pp = p[2];
+    y = Flx_to_ZX(Flm_charpoly_i(ZM_to_Flm(x,pp), pp));
+    return gerepileupto(av, y);
+  }
+  lx = lg(x); y = cgetg(lx+1, t_VEC);
+  gel(y,1) = pol_1(0); H = FpM_hess(x, p);
+  for (r = 1; r < lx; r++)
+  {
+    pari_sp av2 = avma;
+    GEN z, a = gen_1, b = pol_0(0);
+    for (i = r-1; i; i--)
+    {
+      a = Fp_mul(a, gcoeff(H,i+1,i), p);
+      if (!signe(a)) break;
+      b = ZX_add(b, ZX_Z_mul(gel(y,i), Fp_mul(a,gcoeff(H,i,r),p)));
+    }
+    b = FpX_red(b, p);
+    z = FpX_sub(RgX_shift_shallow(gel(y,r), 1),
+                FpX_Fp_mul(gel(y,r), gcoeff(H,r,r), p), p);
+    z = FpX_sub(z,b,p);
+    if (r+1 == lx) { gel(y,lx) = z; break; }
+    gel(y,r+1) = gerepileupto(av2, z); /* (X - H[r,r])y[r] - b */
+  }
+  return gerepileupto(av, gel(y,lx));
+}
+
 GEN
 charpoly0(GEN x, long v, long flag)
 {
@@ -95,7 +162,7 @@ RgM_Fp_charpoly(GEN x, GEN p, long v)
   if (lgefint(p) == 3)
   {
     ulong pp = itou(p);
-    T = Flm_charpoly(RgM_to_Flm(x, pp), pp);
+    T = Flm_charpoly_i(RgM_to_Flm(x, pp), pp);
     T = Flx_to_ZX(T);
   }
   else
@@ -278,19 +345,21 @@ GEN
 adj(GEN x)
 {
   GEN y;
-  (void)caradj(x, MAXVARN, &y); return y;
+  (void)caradj(x, fetch_var(), &y);
+  (void)delete_var(); return y;
 }
 
 GEN
 adjsafe(GEN x)
 {
-  const long v = MAXVARN;
+  const long v = fetch_var();
   pari_sp av = avma;
-  GEN C;
+  GEN C, A;
   if (typ(x) != t_MAT) pari_err_TYPE("matadjoint",x);
   if (lg(x) < 3) return gcopy(x);
   C = charpoly(x,v);
-  return gerepileupto(av, RgM_adj_from_char(x, v, C));
+  A = RgM_adj_from_char(x, v, C);
+  (void)delete_var(); return gerepileupto(av, A);
 }
 
 GEN
@@ -306,6 +375,301 @@ matadjoint0(GEN x, long flag)
 
 /*******************************************************************/
 /*                                                                 */
+/*                       Frobenius form                            */
+/*                                                                 */
+/*******************************************************************/
+
+/* The following section implement a mix of Ozello and Storjohann algorithms
+
+P. Ozello, doctoral thesis (in French):
+Calcul exact des formes de Jordan et de Frobenius d'une matrice
+Chapitre 2
+http://tel.archives-ouvertes.fr/tel-00323705
+
+A. Storjohann,  Diss. ETH No. 13922
+Algorithms for Matrix Canonical Forms
+Chapter 9
+https://cs.uwaterloo.ca/~astorjoh/diss2up.pdf
+
+We use Storjohann Lemma 9.14 (step1, step2, step3) Ozello theorem 4,
+and Storjohann Lemma 9.18
+*/
+
+/* Elementary transforms */
+
+static void
+transL(GEN M, GEN P, GEN k, long i, long j)
+{
+  long l, n = lg(M)-1;
+  for(l=1; l<=n; l++)
+    gcoeff(M,l,j) = gsub(gcoeff(M,l,j), gmul(gcoeff(M,l,i), k));
+  for(l=1; l<=n; l++)
+    gcoeff(M,i,l) = gadd(gcoeff(M,i,l), gmul(gcoeff(M,j,l), k));
+  if (P)
+    for(l=1; l<=n; l++)
+      gcoeff(P,i,l) = gadd(gcoeff(P,i,l), gmul(gcoeff(P,j,l), k));
+}
+
+static void
+transD(GEN M, GEN P, GEN k, long j)
+{
+  long l, n = lg(M)-1;
+  GEN ki = ginv(k);
+  for(l=1; l<=n; l++)
+    if (l!=j)
+    {
+      gcoeff(M,l,j) = gmul(gcoeff(M,l,j), k);
+      gcoeff(M,j,l) = gmul(gcoeff(M,j,l), ki);
+    }
+  if (P)
+    for(l=1; l<=n; l++)
+      gcoeff(P,j,l) = gmul(gcoeff(P,j,l), ki);
+}
+
+static void
+transS(GEN M, GEN P, long i, long j)
+{
+  long l, n = lg(M)-1;
+  swap(gel(M,i), gel(M,j));
+  for (l=1; l<=n; l++)
+    swap(gcoeff(M,i,l), gcoeff(M,j,l));
+  if (P)
+    for (l=1; l<=n; l++)
+      swap(gcoeff(P,i,l), gcoeff(P,j,l));
+}
+
+/* Convert companion matrix to polynomial*/
+static GEN
+minpoly_polslice(GEN M, long i, long j, long v)
+{
+  long k, d = j+1-i;
+  GEN P = cgetg(d+3,t_POL);
+  P[1] = evalsigne(1)|evalvarn(v);
+  for (k=0; k<d; k++)
+    gel(P,k+2) = gneg(gcoeff(M,i+k, j));
+  gel(P,d+2) = gen_1;
+  return P;
+}
+
+static GEN
+minpoly_listpolslice(GEN M, GEN V, long v)
+{
+  long i, n = lg(M)-1, nb = lg(V)-1;
+  GEN W = cgetg(nb+1, t_VEC);
+  for (i=1; i<=nb; i++)
+    gel(W,i) = minpoly_polslice(M, V[i], i < nb? V[i+1]-1: n, v);
+  return W;
+}
+
+static int
+minpoly_dvdslice(GEN M, long i, long j, long k)
+{
+  pari_sp av = avma;
+  long r = signe(RgX_rem(minpoly_polslice(M, i, j-1, 0),
+                        minpoly_polslice(M, j, k, 0)));
+  avma = av; return r==0;
+}
+
+static void
+RgM_replace(GEN M, GEN M2)
+{
+  long n = lg(M)-1, m = nbrows(M), i, j;
+  for(i=1; i<=n; i++)
+    for(j=1; j<=m; j++)
+      gcoeff(M, i, j) = gcoeff(M2, i, j);
+}
+
+static void
+gerepilemat2_inplace(pari_sp av, GEN M, GEN P)
+{
+  GEN M2 = M, P2 = P;
+  gerepileall(av, P ? 2: 1, &M2, &P2);
+  RgM_replace(M, M2);
+  if (P) RgM_replace(P, P2);
+}
+
+/* Lemma 9.14 */
+
+static long
+weakfrobenius_step1(GEN M, GEN P, long j0)
+{
+  pari_sp av = avma;
+  long n = lg(M)-1, k, j;
+  for (j = j0; j < n; ++j)
+  {
+    if (gequal0(gcoeff(M, j + 1, j)))
+    {
+      for (k = j+2; k <= n; ++k)
+        if (!gequal0(gcoeff(M, k, j)))
+          break;
+      if (k > n)
+        return j;
+      transS(M, P, k, j + 1);
+    }
+    if (!gequal1(gcoeff(M, j + 1, j)))
+      transD(M, P, gcoeff(M, j + 1, j), j + 1);
+    for (k = 1; k <= n; ++k)
+      if (k != j + 1 && !gequal0(gcoeff(M, k, j)))
+        transL(M, P, gneg(gcoeff(M, k, j)), k, j + 1);
+    if (gc_needed(av,1))
+    {
+      if (DEBUGMEM > 1)
+        pari_warn(warnmem,"RgM_minpoly stage 1: j0=%ld, j=%ld", j0, j);
+      gerepilemat2_inplace(av, M, P);
+    }
+  }
+  return n;
+}
+
+static void
+weakfrobenius_step2(GEN M, GEN P, long j)
+{
+  pari_sp av = avma;
+  long i, k, n = lg(M)-1;
+  for(i=j; i>=2; i--)
+  {
+    for(k=j+1; k<=n; k++)
+      if (!gequal0(gcoeff(M,i,k)))
+        transL(M, P, gcoeff(M,i,k), i-1, k);
+    if (gc_needed(av,1))
+    {
+      if (DEBUGMEM > 1)
+        pari_warn(warnmem,"RgM_minpoly stage 2: j=%ld, i=%ld", j, i);
+      gerepilemat2_inplace(av, M, P);
+    }
+  }
+}
+
+static long
+weakfrobenius_step3(GEN M, GEN P, long j0, long j)
+{
+  long i, k, n = lg(M)-1;
+  if (j == n) return 0;
+  if (gequal0(gcoeff(M, j0, j+1)))
+  {
+    for (k=j+2; k<=n; k++)
+      if (!gequal0(gcoeff(M, j0, k)))
+        break;
+    if (k > n) return 0;
+    transS(M, P, k, j+1);
+  }
+  if (!gequal1(gcoeff(M, j0, j + 1)))
+    transD(M, P, gcoeff(M, j0, j + 1), j + 1);
+  for (i=j+2; i<=n; i++)
+      if (!gequal0(gcoeff(M, j0, i)))
+        transL(M, P, gcoeff(M, j0, i),j + 1, i);
+  return 1;
+}
+
+/* flag: 0 -> full Frobenius from , 1 -> weak Frobenius form */
+static GEN
+RgM_Frobenius(GEN M, long flag, GEN *pt_P, GEN *pt_v)
+{
+  pari_sp av = avma, av2, ltop;
+  long n = lg(M)-1, eps, j0 = 1, nb = 0;
+  GEN v, P;
+  v = cgetg(n+1, t_VECSMALL);
+  ltop = avma;
+  P = pt_P ? matid(n): NULL;
+  M = RgM_shallowcopy(M);
+  av2 = avma;
+  while (j0 <= n)
+  {
+    long j = weakfrobenius_step1(M, P, j0);
+    weakfrobenius_step2(M, P, j);
+    eps = weakfrobenius_step3(M, P, j0, j);
+    if (eps == 0)
+    {
+      v[++nb] = j0;
+      if (flag == 0 && nb > 1 && !minpoly_dvdslice(M, v[nb-1], j0, j))
+      {
+        j = j0; j0 = v[nb-1]; nb -= 2;
+        transL(M, P, gen_1, j, j0); /*lemma 9.18*/
+      } else
+        j0 = j+1;
+    }
+    else
+      transS(M, P, j0, j+1); /*theorem 4*/
+    if (gc_needed(av,1))
+    {
+      if (DEBUGMEM > 1)
+        pari_warn(warnmem,"weakfrobenius j0=%ld",j0);
+      gerepilemat2_inplace(av2, M, P);
+    }
+  }
+  fixlg(v, nb+1);
+  if (pt_v) *pt_v = v;
+  gerepileall(pt_v ? ltop: av, P? 2: 1, &M, &P);
+  if (pt_P) *pt_P = P;
+  return M;
+}
+
+static GEN
+RgM_minpoly(GEN M, long v)
+{
+  pari_sp av = avma;
+  GEN V, W;
+  M = RgM_Frobenius(M, 1, NULL, &V);
+  W = minpoly_listpolslice(M, V, v);
+  if (varncmp(v,gvar2(W)) >= 0)
+    pari_err_PRIORITY("matfrobenius", M, "<=", v);
+  return gerepileupto(av, RgX_normalize(glcm0(W, NULL)));
+}
+
+GEN
+Frobeniusform(GEN V, long n)
+{
+  long i, j, k;
+  GEN M = zeromatcopy(n,n);
+  for (k=1,i=1;i<lg(V);i++,k++)
+  {
+    GEN  P = gel(V,i);
+    long d = degpol(P);
+    if (k+d-1 > n) pari_err_PREC("matfrobenius");
+    for (j=0; j<d-1; j++, k++) gcoeff(M,k+1,k) = gen_1;
+    for (j=0; j<d; j++) gcoeff(M,k-j,k) = gneg(gel(P, 1+d-j));
+  }
+  return M;
+}
+
+GEN
+matfrobenius(GEN M, long flag, long v)
+{
+  long n;
+  if (typ(M)!=t_MAT) pari_err_TYPE("matfrobenius",M);
+  if (v < 0) v = 0;
+  n = lg(M)-1;
+  if (n && lgcols(M)!=n+1) pari_err_DIM("matfrobenius");
+  if (flag > 2) pari_err_FLAG("matfrobenius");
+  switch (flag)
+  {
+  case 0:
+    return RgM_Frobenius(M, 0, NULL, NULL);
+  case 1:
+    {
+      pari_sp av = avma;
+      GEN V, W, F;
+      F = RgM_Frobenius(M, 0, NULL, &V);
+      W = minpoly_listpolslice(F, V, v);
+      if (varncmp(v, gvar2(W)) >= 0)
+        pari_err_PRIORITY("matfrobenius", M, "<=", v);
+      return gerepileupto(av, W);
+    }
+  case 2:
+    {
+      GEN P, F, R = cgetg(3, t_VEC);
+      F = RgM_Frobenius(M, 0, &P, NULL);
+      gel(R,1) = F; gel(R,2) = P;
+      return R;
+    }
+  default:
+    pari_err_FLAG("matfrobenius");
+  }
+  return NULL; /*NOT REACHED*/
+}
+
+/*******************************************************************/
+/*                                                                 */
 /*                       MINIMAL POLYNOMIAL                        */
 /*                                                                 */
 /*******************************************************************/
@@ -338,7 +702,7 @@ minpoly(GEN x, long v)
       setvarn(p1,v); return gerepileupto(ltop,p1);
   }
 
-  P=easymin(x,v);
+  P = easymin(x,v);
   if (P) return P;
   if (typ(x)==t_POLMOD)
   {
@@ -348,7 +712,7 @@ minpoly(GEN x, long v)
   }
   if (typ(x)!=t_MAT) pari_err_TYPE("minpoly",x);
   if (lg(x) == 1) return pol_1(v);
-  return gerepilecopy(ltop,gel(matfrobenius(x,1,v),1));
+  return RgM_minpoly(x,v);
 }
 
 /*******************************************************************/
@@ -359,14 +723,14 @@ minpoly(GEN x, long v)
 GEN
 hess(GEN x)
 {
-  pari_sp av = avma, lim;
+  pari_sp av = avma;
   long lx = lg(x), m, i, j;
 
   if (typ(x) != t_MAT) pari_err_TYPE("hess",x);
   if (lx == 1) return cgetg(1,t_MAT);
   if (lgcols(x) != lx) pari_err_DIM("hess");
 
-  x = RgM_shallowcopy(x); lim = stack_lim(av,2);
+  x = RgM_shallowcopy(x);
   for (m=2; m<lx-1; m++)
   {
     GEN t = NULL;
@@ -385,7 +749,7 @@ hess(GEN x)
         gcoeff(x,i,j) = gsub(gcoeff(x,i,j), gmul(c,gcoeff(x,m,j)));
       for (j=1; j<lx; j++)
         gcoeff(x,j,m) = gadd(gcoeff(x,j,m), gmul(c,gcoeff(x,j,i)));
-      if (low_stack(lim, stack_lim(av,2)))
+      if (gc_needed(av,2))
       {
         if (DEBUGMEM>1) pari_warn(warnmem,"hess, m = %ld", m);
         gerepileall(av,2, &x, &t);
@@ -428,7 +792,7 @@ Flm_hess(GEN x, ulong p)
 GEN
 FpM_hess(GEN x, GEN p)
 {
-  pari_sp av = avma, lim;
+  pari_sp av = avma;
   long lx = lg(x), m, i, j;
   if (lx == 1) return cgetg(1,t_MAT);
   if (lgcols(x) != lx) pari_err_DIM("hess");
@@ -438,7 +802,7 @@ FpM_hess(GEN x, GEN p)
     x = Flm_hess(ZM_to_Flm(x, pp), pp);
     return gerepileupto(av, Flm_to_ZM(x));
   }
-  x = RgM_shallowcopy(x); lim = stack_lim(av,2);
+  x = RgM_shallowcopy(x);
   for (m=2; m<lx-1; m++)
   {
     GEN t = NULL;
@@ -457,7 +821,7 @@ FpM_hess(GEN x, GEN p)
         gcoeff(x,i,j) = Fp_sub(gcoeff(x,i,j), Fp_mul(c,gcoeff(x,m,j),p), p);
       for (j=1; j<lx; j++)
         gcoeff(x,j,m) = Fp_add(gcoeff(x,j,m), Fp_mul(c,gcoeff(x,j,i),p), p);
-      if (low_stack(lim, stack_lim(av,2)))
+      if (gc_needed(av,2))
       {
         if (DEBUGMEM>1) pari_warn(warnmem,"hess, m = %ld", m);
         gerepileall(av,2, &x, &t);
@@ -494,77 +858,20 @@ carhess(GEN x, long v)
   return fix_pol(av, gel(y,lx));
 }
 
-GEN
-FpM_charpoly(GEN x, GEN p)
-{
-  pari_sp av = avma;
-  long lx, r, i;
-  GEN y, H;
-
-  if (lgefint(p) == 3)
-  {
-    ulong pp = p[2];
-    y = Flx_to_ZX(Flm_charpoly(ZM_to_Flm(x,pp), pp));
-    return gerepileupto(av, y);
-  }
-  lx = lg(x); y = cgetg(lx+1, t_VEC);
-  gel(y,1) = pol_1(0); H = FpM_hess(x, p);
-  for (r = 1; r < lx; r++)
-  {
-    pari_sp av2 = avma;
-    GEN z, a = gen_1, b = pol_0(0);
-    for (i = r-1; i; i--)
-    {
-      a = Fp_mul(a, gcoeff(H,i+1,i), p);
-      if (!signe(a)) break;
-      b = ZX_add(b, ZX_Z_mul(gel(y,i), Fp_mul(a,gcoeff(H,i,r),p)));
-    }
-    b = FpX_red(b, p);
-    z = FpX_sub(RgX_shift_shallow(gel(y,r), 1),
-                FpX_Fp_mul(gel(y,r), gcoeff(H,r,r), p), p);
-    z = FpX_sub(z,b,p);
-    if (r+1 == lx) { gel(y,lx) = z; break; }
-    gel(y,r+1) = gerepileupto(av2, z); /* (X - H[r,r])y[r] - b */
-  }
-  return gerepileupto(av, gel(y,lx));
-}
-GEN
-Flm_charpoly(GEN x, long p)
-{
-  pari_sp av;
-  long lx, r, i;
-  GEN y, H;
-
-  lx = lg(x); av = avma; y = cgetg(lx+1, t_VEC);
-  gel(y,1) = pol1_Flx(0); H = Flm_hess(x, p);
-  for (r = 1; r < lx; r++)
-  {
-    pari_sp av2 = avma;
-    ulong a = 1;
-    GEN z, b = zero_Flx(0);
-    for (i = r-1; i; i--)
-    {
-      a = Fl_mul(a, ucoeff(H,i+1,i), p);
-      if (!a) break;
-      b = Flx_add(b, Flx_Fl_mul(gel(y,i), Fl_mul(a,ucoeff(H,i,r),p), p), p);
-    }
-    z = Flx_sub(Flx_shift(gel(y,r), 1),
-                Flx_Fl_mul(gel(y,r), ucoeff(H,r,r), p), p);
-    /* (X - H[r,r])y[r] - b */
-    gel(y,r+1) = gerepileuptoleaf(av2, Flx_sub(z, b, p));
-  }
-  return gerepileuptoleaf(av, gel(y,lx));
-}
-
-/* s = max_k binomial(n,k) (kB^2)^(k/2),  B = |M|oo. Return ceil(log2(s)) */
+/* Bound for sup norm of charpoly(M/dM), M integral: let B = |M|oo / |dM|,
+ *   s = max_k binomial(n,k) (kB^2)^(k/2),
+ * return ceil(log2(s)) */
 static double
-charpoly_bound(GEN M)
+charpoly_bound(GEN M, GEN dM)
 {
   pari_sp av = avma;
-  GEN s = real_0(LOWDEFAULTPREC), bin, B2 = itor(sqri(ZM_supnorm(M)), LOWDEFAULTPREC);
+  GEN B = itor(ZM_supnorm(M), LOWDEFAULTPREC);
+  GEN s = real_0(LOWDEFAULTPREC), bin, B2;
   long n = lg(M)-1, k;
   double d;
   bin = gen_1;
+  if (dM) B = divri(B, dM);
+  B2 = sqrr(B);
   for (k = n; k >= (n+1)>>1; k--)
   {
     GEN t = mulri(powruhalf(mulur(k, B2), k), bin);
@@ -574,45 +881,113 @@ charpoly_bound(GEN M)
   d = dbllog2(s); avma = av; return ceil(d);
 }
 
-GEN
-ZM_charpoly(GEN M)
+/* Return char_{M/d}(X) = d^(-n) char_M(dX) modulo p. Assume dp = d mod p. */
+static GEN
+QM_charpoly_Flx(GEN M, ulong dp, ulong p)
 {
-  pari_timer T;
   pari_sp av = avma;
-  long l = lg(M), n = l-1, bit;
-  GEN q = NULL, H = NULL, Hp;
+  GEN H = Flm_charpoly_i(ZM_to_Flm(M,p), p);
+  if (dp) H = Flx_rescale(H, Fl_inv(dp,p), p);
+  return gerepileuptoleaf(av, H);
+}
+
+static int
+ZX_CRT(GEN *H, GEN Hp, GEN *q, ulong p, long bit)
+{
+  if (!*H)
+  {
+    *H = ZX_init_CRT(Hp, p, 0);
+    if (DEBUGLEVEL>5)
+      err_printf("charpoly mod %lu, bound = 2^%ld", p, expu(p));
+    if (expu(p) > bit) return 1;
+    *q = utoipos(p);
+  }
+  else
+  {
+    int stable = ZX_incremental_CRT(H, Hp, q,p);
+    if (DEBUGLEVEL>5)
+      err_printf("charpoly mod %lu (stable=%ld), bound = 2^%ld",
+                 p, stable, expi(*q));
+    if (stable && expi(*q) > bit) return 1;
+  }
+  return 0;
+}
+/* Let V = V1 \oplus V2 Q-vector spaces and f in End(V) stabilizing the Vi
+ * Let M, M2 be square QM representing f, f|V2.
+ * Return H := char(f|V1) = char(f) / char(f|V2) assuming H is in Z[X]
+ * and log 2 |H|oo <= bit */
+GEN
+QM_charpoly_ZX2_bound(GEN M, GEN M2, long bit)
+{
+  long n = lg(M)-1, n2 = lg(M2)-1;
+  GEN q = NULL, H1 = NULL, dM, dM2;
   forprime_t S;
   ulong p;
-  if (!n) return pol_1(0);
+  if (n == n2) return pol_1(0);
+  if (!n2) return QM_charpoly_ZX_bound(M, bit);
+  M = Q_remove_denom(M,&dM);
+  M2= Q_remove_denom(M2,&dM2);
 
-  bit = (long)charpoly_bound(M) + 1;
-  if (DEBUGLEVEL>5) {
-    err_printf("ZM_charpoly: bit-bound 2^%ld\n", bit);
-    timer_start(&T);
+  if (DEBUGLEVEL>5) err_printf("QM_charpoly_ZX2_bound: bit-bound 2^%ld\n", bit);
+  init_modular(&S);
+  while ((p = u_forprime_next(&S)))
+  {
+    ulong dMp = 0, dM2p = 0;
+    GEN Hp, H1p, H2p;
+    if (dM && !(dMp = umodiu(dM, p))) continue;
+    if (dM2 && !(dM2p = umodiu(dM2, p))) continue;
+    Hp  = QM_charpoly_Flx(M,  dMp,  p);
+    H2p = QM_charpoly_Flx(M2, dM2p, p);
+    H1p = Flx_div(Hp, H2p, p);
+    if (ZX_CRT(&H1, H1p, &q,p, bit)) break;
   }
+  if (!p) pari_err_OVERFLOW("charpoly [ran out of primes]");
+  return H1;
+}
+
+/* Assume M a square ZM, dM integer. Return charpoly(M / dM) in Z[X] */
+static GEN
+QM_charpoly_ZX_i(GEN M, GEN dM, long bit)
+{
+  long n = lg(M)-1;
+  GEN q = NULL, H = NULL;
+  forprime_t S;
+  ulong p;
+  if (!n) return pol_1(0);
+
+  if (bit < 0) bit = (long)charpoly_bound(M, dM) + 1;
+  if (DEBUGLEVEL>5) err_printf("ZM_charpoly: bit-bound 2^%ld\n", bit);
   init_modular(&S);
   while ((p = u_forprime_next(&S)))
   {
-    Hp = Flm_charpoly(ZM_to_Flm(M, p), p);
-    if (!H)
-    {
-      H = ZX_init_CRT(Hp, p, 0);
-      if (DEBUGLEVEL>5)
-        timer_printf(&T, "charpoly mod %lu, bound = 2^%ld", p, expu(p));
-      if (expu(p) > bit) break;
-      q = utoipos(p);
-    }
-    else
-    {
-      int stable = ZX_incremental_CRT(&H, Hp, &q,p);
-      if (DEBUGLEVEL>5)
-        timer_printf(&T, "charpoly mod %lu (stable=%ld), bound = 2^%ld",
-                     p, stable, expi(q));
-      if (stable && expi(q) > bit) break;
-    }
+    ulong dMp = 0;
+    GEN Hp;
+    if (dM && !(dMp = umodiu(dM, p))) continue;
+    Hp = QM_charpoly_Flx(M, dMp, p);
+    if (ZX_CRT(&H, Hp, &q,p, bit)) break;
   }
-  if (!p) pari_err_OVERFLOW("ZM_charpoly [ran out of primes]");
-  return gerepilecopy(av, H);
+  if (!p) pari_err_OVERFLOW("charpoly [ran out of primes]");
+  return H;
+}
+GEN
+QM_charpoly_ZX_bound(GEN M, long bit)
+{
+  pari_sp av = avma;
+  GEN dM; M = Q_remove_denom(M, &dM);
+  return gerepilecopy(av, QM_charpoly_ZX_i(M, dM, bit));
+}
+GEN
+QM_charpoly_ZX(GEN M)
+{
+  pari_sp av = avma;
+  GEN dM; M = Q_remove_denom(M, &dM);
+  return gerepilecopy(av, QM_charpoly_ZX_i(M, dM, -1));
+}
+GEN
+ZM_charpoly(GEN M)
+{
+  pari_sp av = avma;
+  return gerepilecopy(av, QM_charpoly_ZX_i(M, NULL, -1));
 }
 
 /*******************************************************************/
@@ -625,9 +1000,9 @@ carberkowitz(GEN x, long v)
 {
   long lx, i, j, k, r;
   GEN V, S, C, Q;
-  pari_sp av0, av, lim;
+  pari_sp av0, av;
   if ((V = easychar(x,v))) return V;
-  lx = lg(x); av0 = avma; lim = stack_lim(av0,1);
+  lx = lg(x); av0 = avma;
   V = cgetg(lx+1, t_VEC);
   S = cgetg(lx+1, t_VEC);
   C = cgetg(lx+1, t_VEC);
@@ -660,7 +1035,7 @@ carberkowitz(GEN x, long v)
     av2 = avma; t = gmul(gcoeff(x,r,1), gel(S,1));
     for (j = 2; j < r; j++) t = gadd(t, gmul(gcoeff(x,r,j), gel(S,j)));
     gel(C,r+1) = gerepileupto(av2, t);
-    if (low_stack(lim, stack_lim(av0,1)))
+    if (gc_needed(av0,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"carberkowitz");
       gerepileall(av, 2, &C, &V);
@@ -735,7 +1110,7 @@ cxquadnorm(GEN q, long prec)
 static GEN
 gnorml2_i(GEN x, long prec)
 {
-  pari_sp av, lim;
+  pari_sp av;
   long i, lx;
   GEN s;
 
@@ -757,12 +1132,12 @@ gnorml2_i(GEN x, long prec)
       return NULL; /* not reached */
   }
   if (lx == 1) return gen_0;
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
   s = gnorml2(gel(x,1));
   for (i=2; i<lx; i++)
   {
     s = gadd(s, gnorml2(gel(x,i)));
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"gnorml2");
       s = gerepileupto(av, s);
@@ -777,13 +1152,13 @@ static GEN pnormlp(GEN,GEN,long);
 static GEN
 pnormlpvec(long i0, GEN x, GEN p, long prec)
 {
-  pari_sp av = avma, lim = stack_lim(av,1);
+  pari_sp av = avma;
   long i, lx = lg(x);
   GEN s = gen_0;
   for (i=i0; i<lx; i++)
   {
     s = gadd(s, pnormlp(gel(x,i),p,prec));
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"gnormlp, i = %ld", i);
       s = gerepileupto(av, s);
@@ -1001,6 +1376,7 @@ gtrace(GEN x)
       return normalizepol_lg(y, lx);
 
     case t_SER:
+      if (ser_isexactzero(x)) return gcopy(x);
       y = cgetg_copy(x, &lx); y[1] = x[1];
       for (i=2; i<lx; i++) gel(y,i) = gtrace(gel(x,i));
       return normalize(y);
@@ -1042,7 +1418,7 @@ gtrace(GEN x)
 GEN
 qfgaussred_positive(GEN a)
 {
-  pari_sp av = avma, lim=stack_lim(av,1);
+  pari_sp av = avma;
   GEN b;
   long i,j,k, n = lg(a);
 
@@ -1071,7 +1447,7 @@ qfgaussred_positive(GEN a)
       for (j=i; j<n; j++)
         gcoeff(b,i,j) = gsub(gcoeff(b,i,j), gmul(c,gcoeff(b,k,j)));
     }
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"qfgaussred_positive");
       b=gerepilecopy(av,b);
@@ -1107,7 +1483,7 @@ static GEN
 gaussred(GEN a, long signature)
 {
   GEN r, ak, al;
-  pari_sp av, av1, lim;
+  pari_sp av, av1;
   long n = lg(a), i, j, k, l, sp, sn, t;
 
   if (typ(a) != t_MAT) pari_err_TYPE("gaussred",a);
@@ -1117,7 +1493,7 @@ gaussred(GEN a, long signature)
 
   av = avma;
   r = const_vecsmall(n, 1);
-  av1= avma; lim = stack_lim(av1,1);
+  av1= avma;
   a = RgM_shallowcopy(a);
   t = n; sp = sn = 0;
   while (t)
@@ -1186,7 +1562,7 @@ gaussred(GEN a, long signature)
         gcoeff(a,l,k) = gen_m1;
         gcoeff(a,k,k) = gmul2n(p,-1);
         gcoeff(a,l,l) = gneg(gcoeff(a,k,k));
-        if (low_stack(lim, stack_lim(av1,1)))
+        if (gc_needed(av1,1))
         {
           if(DEBUGMEM>1) pari_warn(warnmem,"gaussred");
           a = gerepilecopy(av1, a);
@@ -1341,7 +1717,7 @@ matrixqz0(GEN x,GEN p)
 GEN
 QM_minors_coprime(GEN x, GEN D)
 {
-  pari_sp av = avma, av1, lim;
+  pari_sp av = avma, av1;
   long i, j, m, n, lP;
   GEN P, y;
 
@@ -1369,7 +1745,7 @@ QM_minors_coprime(GEN x, GEN D)
     if (is_pm1(D)) { avma = av2; return ZM_copy(x); }
   }
   P = gel(Z_factor(D), 1); lP = lg(P);
-  av1 = avma; lim = stack_lim(av1,1);
+  av1 = avma;
   for (i=1; i < lP; i++)
   {
     GEN p = gel(P,i), pov2 = shifti(p, -1);
@@ -1379,14 +1755,14 @@ QM_minors_coprime(GEN x, GEN D)
       long lM = lg(M);
       if (lM==1) break;
 
-      M = FpM_center(M, p, pov2);
+      FpM_center_inplace(M, p, pov2);
       N = ZM_Z_divexact(ZM_mul(x,M), p);
       for (j=1; j<lM; j++)
       {
         long k = n; while (!signe(gcoeff(M,k,j))) k--;
         gel(x,k) = gel(N,j);
       }
-      if (low_stack(lim, stack_lim(av1,1)))
+      if (gc_needed(av1,1))
       {
         if (DEBUGMEM>1) pari_warn(warnmem,"QM_minors_coprime, p = %Ps", p);
         x = gerepilecopy(av1, x); pov2 = shifti(p, -1);
@@ -1461,9 +1837,8 @@ QC_elem(GEN aj, GEN ak, GEN A, long j, long k)
 static GEN
 QM_imZ_hnf_aux(GEN A)
 {
-  pari_sp av = avma, lim = stack_lim(av,1);
+  pari_sp av = avma;
   long i,j,k,n,m;
-  GEN a;
 
   n = lg(A);
   if (n == 1) return cgetg(1,t_MAT);
@@ -1476,6 +1851,7 @@ QM_imZ_hnf_aux(GEN A)
   m = lgcols(A);
   for (i=1; i<m; i++)
   {
+    GEN b;
     for (j = k = 1; j<n; j++)
     {
       GEN a = gcoeff(A,i,j);
@@ -1485,13 +1861,13 @@ QM_imZ_hnf_aux(GEN A)
       /* zero a = Aij  using  b = Aik */
       QC_elem(a, gcoeff(A,i,k), A, j,k);
     }
-    a = gcoeff(A,i,k);
-    if (!gequal0(a))
+    b = gcoeff(A,i,k);
+    if (!gequal0(b))
     {
-      a = Q_denom(a);
-      if (!is_pm1(a)) gel(A,k) = RgC_Rg_mul(gel(A,k), a);
+      b = Q_denom(b);
+      if (!is_pm1(b)) gel(A,k) = RgC_Rg_mul(gel(A,k), b);
     }
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"QM_imZ_hnf_aux");
       A = gerepilecopy(av,A);
@@ -1510,14 +1886,14 @@ QM_ImZ_hnf(GEN x)
 GEN
 QM_ImQ_hnf(GEN x)
 {
-  pari_sp av = avma, av1, lim;
+  pari_sp av = avma, av1;
   long j,j1,k,m,n;
   GEN c;
 
   n = lg(x); if (n==1) return gcopy(x);
   m = lgcols(x); x = RgM_shallowcopy(x);
   c = zero_zv(n-1);
-  av1 = avma; lim = stack_lim(av1,1);
+  av1 = avma;
   for (k=1; k<m; k++)
   {
     j=1; while (j<n && (c[j] || gequal0(gcoeff(x,k,j)))) j++;
@@ -1530,7 +1906,7 @@ QM_ImQ_hnf(GEN x)
         GEN t = gcoeff(x,k,j1);
         if (!gequal0(t)) gel(x,j1) = RgC_sub(gel(x,j1), RgC_Rg_mul(gel(x,j),t));
       }
-    if (low_stack(lim, stack_lim(av1,1)))
+    if (gc_needed(av1,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"QM_ImQ_hnf");
       x = gerepilecopy(av1,x);
diff --git a/src/basemath/alglin3.c b/src/basemath/alglin3.c
index 8551c71..91c1fc6 100644
--- a/src/basemath/alglin3.c
+++ b/src/basemath/alglin3.c
@@ -29,7 +29,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 GEN
 vecsum(GEN v)
 {
-  pari_sp av = avma, lim;
+  pari_sp av = avma;
   long i, l;
   GEN p;
   if (!is_vec_t(typ(v)))
@@ -38,11 +38,10 @@ vecsum(GEN v)
   if (l == 1) return gen_0;
   p = gel(v,1);
   if (l == 2) return gcopy(p);
-  lim = stack_lim(av, 2);
   for (i=2; i<l; i++)
   {
     p = gadd(p, gel(v,i));
-    if (low_stack(lim, stack_lim(av, 2)))
+    if (gc_needed(av, 2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"sum");
       p = gerepileupto(av, p);
@@ -567,10 +566,17 @@ genselect(void *E, long (*f)(void* E, GEN x), GEN A)
   clone_unlock(A); return y;
 }
 
+static void
+check_callgen1(GEN f, const char *s)
+{
+  if (typ(f) != t_CLOSURE || closure_is_variadic(f)  || closure_arity(f) < 1)
+    pari_err_TYPE(s, f);
+}
+
 GEN
 select0(GEN f, GEN x, long flag)
 {
-  if (typ(f) != t_CLOSURE || closure_arity(f) < 1) pari_err_TYPE("select", f);
+  check_callgen1(f, "select");
   switch(flag)
   {
     case 0: return genselect((void *) f, gp_callbool, x);
@@ -587,7 +593,7 @@ parselect(GEN C, GEN D, long flag)
   long lv, l = lg(D), i, pending = 0, workid;
   GEN V, worker, done;
   struct pari_mt pt;
-  if (typ(C) != t_CLOSURE || closure_arity(C) < 1) pari_err_TYPE("parapply",C);
+  check_callgen1(C, "parselect");
   if (!is_vec_t(typ(D))) pari_err_TYPE("parapply",D);
   V = cgetg(l, t_VECSMALL); av = avma;
   worker = strtoclosure("_parapply_worker", 1, C);
@@ -649,7 +655,9 @@ genapply(void *E, GEN (*f)(void* E, GEN x), GEN x)
   clone_lock(x);
   switch(tx) {
     case t_POL: y = normalizepol(vecapply2(E,f,x)); break;
-    case t_SER: y = normalize(vecapply2(E,f,x)); break;
+    case t_SER:
+      y = ser_isexactzero(x)? gcopy(x): normalize(vecapply2(E,f,x));
+      break;
     case t_LIST:
       z = list_data(x);
       if (!z)
@@ -676,7 +684,7 @@ genapply(void *E, GEN (*f)(void* E, GEN x), GEN x)
 GEN
 apply0(GEN f, GEN x)
 {
-  if (typ(f) != t_CLOSURE || closure_arity(f) < 1) pari_err_TYPE("apply",f);
+  check_callgen1(f, "apply");
   return genapply((void *) f, gp_call, x);
 }
 
@@ -714,7 +722,7 @@ parapply(GEN C, GEN D)
   long l = lg(D), i, pending = 0, workid;
   GEN V, worker, done;
   struct pari_mt pt;
-  if (typ(C) != t_CLOSURE || closure_arity(C) < 1) pari_err_TYPE("parapply",C);
+  check_callgen1(C, "parapply");
   if (!is_vec_t(typ(D))) pari_err_TYPE("parapply",D);
   worker = strtoclosure("_parapply_worker", 1, C);
   V = cgetg(l, typ(D));
@@ -729,6 +737,27 @@ parapply(GEN C, GEN D)
   return gerepilecopy(av, V);
 }
 
+GEN
+genfold(void *E, GEN (*f)(void* E, GEN x, GEN y), GEN x)
+{
+  pari_sp av = avma;
+  GEN z;
+  long i, l = lg(x);
+  if (!is_vec_t(typ(x))|| l==1  ) pari_err_TYPE("fold",x);
+  clone_lock(x);
+  z = gel(x,1);
+  for (i=2; i<l; i++)
+    z = f(E,z,gel(x,i));
+  clone_unlock(x);
+  return gerepilecopy(av, z);
+}
+
+GEN
+fold0(GEN f, GEN x)
+{
+  if (typ(f) != t_CLOSURE || closure_arity(f) < 2) pari_err_TYPE("apply",f);
+  return genfold((void *) f, gp_call2, x);
+}
 /*******************************************************************/
 /*                                                                 */
 /*                     SCALAR-MATRIX OPERATIONS                    */
@@ -768,7 +797,7 @@ gtomat(GEN x)
       lx = lg(x);
       if (lx == 1) return cgetg(1, t_MAT);
       if (typ(gel(x,1)) == t_VEC) {
-        long j, h = lgcols(x);
+        long j, h = lg(gel(x,1));
         for (i=2; i<lx; i++) {
           if (typ(gel(x,i)) != t_VEC || lg(gel(x,i)) != h) break;
         }
diff --git a/src/basemath/arith1.c b/src/basemath/arith1.c
index 2f278ca..fcf34a2 100644
--- a/src/basemath/arith1.c
+++ b/src/basemath/arith1.c
@@ -63,7 +63,7 @@ u_is_gener_expo(ulong p, GEN L0)
     L0 = L = u_odd_prime_divisors(q);
     l = lg(L);
   }
-  for (i=1; i<l; i++) L[i] = q / (ulong)L0[i];
+  for (i=1; i<l; i++) L[i] = q / uel(L0,i);
   return L;
 }
 
@@ -74,7 +74,7 @@ is_gener_Fl(ulong x, ulong p, ulong p_1, GEN L)
   if (krouu(x, p) >= 0) return 0;
   for (i=lg(L)-1; i; i--)
   {
-    ulong t = Fl_powu(x, (ulong)L[i], p);
+    ulong t = Fl_powu(x, uel(L,i), p);
     if (t == p_1 || t == 1) return 0;
   }
   return 1;
@@ -106,7 +106,7 @@ pgener_Fl(ulong p) { return pgener_Fl_local(p, NULL); }
 int
 is_gener_Fp(GEN x, GEN p, GEN p_1, GEN L)
 {
-  long i, t = lgefint(x)==3 && x[2]>0? krosi(x[2], p): kronecker(x, p);
+  long i, t = lgefint(x)==3? kroui(x[2], p): kronecker(x, p);
   if (t >= 0) return 0;
   for (i = lg(L)-1; i; i--)
   {
@@ -127,13 +127,13 @@ pgener_Fp_local(GEN p, GEN L0)
     ulong z;
     if (p[2] == 2) return gen_1;
     if (L0) L0 = ZV_to_nv(L0);
-    z = pgener_Fl_local((ulong)p[2], L0);
+    z = pgener_Fl_local(uel(p,2), L0);
     avma = av0; return utoipos(z);
   }
   p_1 = subis(p,1); L = is_gener_expo(p, L0);
   x = utoipos(2);
   for (;; x[2]++) { if (is_gener_Fp(x, p, p_1, L)) break; }
-  avma = av0; return utoipos((ulong)x[2]);
+  avma = av0; return utoipos(uel(x,2));
 }
 
 GEN
@@ -174,7 +174,7 @@ pgener_Zp(GEN p)
     GEN x = utoipos(2);
     for (;; x[2]++)
       if (is_gener_Fp(x,p,p_1,L) && !equali1(Fp_pow(x,p_1,p2))) break;
-    avma = av; return utoipos((ulong)x[2]);
+    avma = av; return utoipos(uel(x,2));
   }
 }
 
@@ -319,6 +319,7 @@ znstar(GEN N)
     gel(gen,i) = e > 1? pgener_Zp(p): pgener_Fp(p);
     gel(mod,i) = Q;
   }
+  /* gen[i] has order cyc[i] and generates (Z/mod[i]Z)^* */
   setlg(gen, sizeh+1);
   setlg(cyc, sizeh+1);
   if (nbp > 1)
@@ -329,7 +330,7 @@ znstar(GEN N)
       gel(gen,i) = modii(g, N);
     }
 
-  /*The cyc[i] are > 1. They remain so in the loop*/
+  /*The cyc[i] are > 1 and remain so in the loop, gen[i] = 1 mod (N/mod[i]) */
   for (i=sizeh; i>=2; i--)
   {
     GEN ci = gel(cyc,i), gi = gel(gen,i);
@@ -628,7 +629,7 @@ Z_issquareall(GEN x, GEN *pt)
   }
   if (lgefint(x) == 3)
   {
-    ulong u = (ulong)x[2], a;
+    ulong u = uel(x,2), a;
     if (!pt) return uissquare(u);
     if (!uissquareall(u, &a)) return 0;
     *pt = utoipos(a); return 1;
@@ -654,76 +655,36 @@ Zp_issquare(GEN a, GEN p)
                       : kronecker(ap,p) == 1;
 }
 
-static int
-is_char_2(GEN a)
-{
-  long j;
-  GEN b;
-  switch(typ(a))
-  {
-  case t_INTMOD:
-    b = gel(a,1);
-    if (!mod2(b))
-    {
-      if (!equaliu(b, 2)) pari_err_IMPL( "issquare for this input");
-      return 1;
-    }
-    return 0;
-  case t_FFELT:
-    if (equaliu(FF_p_i(a), 2)) return 1;
-    return 0;
-  case t_POLMOD:
-    if (is_char_2(gel(a,1)) || is_char_2(gel(a,2))) return 1;
-    return 0;
-  case t_POL:
-    for (j = 2; j < lg(a); j++)
-      if (is_char_2(gel(a,j))) return 1;
-    return 0;
-  }
-  return 0;
-}
-
 static long
 polissquareall(GEN x, GEN *pt)
 {
   pari_sp av;
-  long v, l = degpol(x);
-  GEN y, a, b;
+  long v;
+  GEN y, a, b, p;
 
   if (!signe(x))
   {
     if (pt) *pt = gcopy(x);
     return 1;
   }
-  if (pt) *pt = gen_0;
-  if (l&1) return 0; /* odd degree */
+  if (odd(degpol(x))) return 0; /* odd degree */
   av = avma;
   v = RgX_valrem(x, &x);
-  if (v) {
-    l = degpol(x);
-    if (l&1) return 0;
-  }
-  a = gel(x,2);
-  switch (typ(a))
-  {
-    case t_INT:
-      if (!Z_issquareall(a,&b)) { avma = av; return 0; }
-      break;
-    case t_POL:
-      if (!polissquareall(a,&b)) { avma = av; return 0; }
-      break;
-    default:
-      if (!issquare(a)) { avma = av; return 0; }
-      b = NULL; break;
-  }
-  if (!l) {
+  if (v & 1) { avma = av; return 0; }
+  a = gel(x,2); /* test constant coeff */
+  if (!pt)
+  { if (!issquare(a)) { avma = av; return 0; } }
+  else
+  { if (!issquareall(a,&b)) { avma = av; return 0; } }
+  if (!degpol(x)) { /* constant polynomial */
     if (!pt) { avma = av; return 1; }
-    if (!b) b = gsqrt(a,DEFAULTPREC);
     y = scalarpol(b, varn(x)); goto END;
   }
-  if (is_char_2(x))
+  p = characteristic(x);
+  if (signe(p) && !mod2(p))
   {
     long i, lx;
+    if (!equaliu(p,2)) pari_err_IMPL("issquare for even characteristic != 2");
     x = gmul(x, mkintmod(gen_1, gen_2));
     lx = lg(x);
     if ((lx-3) & 1) { avma = av; return 0; }
@@ -743,19 +704,19 @@ polissquareall(GEN x, GEN *pt)
   }
   else
   {
+    long m = 1;
     x = RgX_Rg_div(x,a);
-    y = gtrunc(gsqrt(RgX_to_ser(x,2+l),0));
-    if (!RgX_equal(gsqr(y), x)) { avma = av; return 0; }
+    /* a(x^m) = B^2 => B = b(x^m) provided a(0) != 0 */
+    if (!signe(p)) x = RgX_deflate_max(x,&m);
+    y = ser2rfrac_i(gsqrt(RgX_to_ser(x,lg(x)-1),0));
+    if (!RgX_equal(RgX_sqr(y), x)) { avma = av; return 0; }
     if (!pt) { avma = av; return 1; }
-    if (!gequal1(a))
-    {
-      if (!b) b = gsqrt(a,DEFAULTPREC);
-      y = gmul(b, y);
-    }
+    if (!gequal1(a)) y = gmul(b, y);
+    if (m != 1) y = RgX_inflate(y,m);
   }
 END:
-  *pt = v? gerepilecopy(av, RgX_shift_shallow(y, v >> 1)): gerepileupto(av, y);
-  return 1;
+  if (v) y = RgX_shift_shallow(y, v>>1);
+  *pt = gerepilecopy(av, y); return 1;
 }
 
 /* b unit mod p */
@@ -1039,23 +1000,28 @@ static long
 polispower(GEN x, GEN K, GEN *pt)
 {
   pari_sp av;
-  long v, l = degpol(x), k = itos(K);
+  long v, k = itos(K);
   GEN y, a, b;
 
-  if (!signe(x)) return 1;
-  if (l % k) return 0; /* degree not multiple of k */
+  if (!signe(x))
+  {
+    if (pt) *pt = gcopy(x);
+    return 1;
+  }
+  if (degpol(x) % k) return 0; /* degree not multiple of k */
+  av = avma;
   v = RgX_valrem(x, &x);
   if (v % k) return 0;
-  av = avma; a = gel(x,2); b = NULL;
+  a = gel(x,2); b = NULL;
   if (!ispower(a, K, &b)) { avma = av; return 0; }
-  av = avma;
   if (degpol(x))
   {
     x = RgX_Rg_div(x,a);
     y = gtrunc(gsqrtn(RgX_to_ser(x,lg(x)), K, NULL, 0));
     if (!RgX_equal(powgi(y, K), x)) { avma = av; return 0; }
   }
-  else y = pol_1(varn(x));
+  else
+    y = pol_1(varn(x));
   if (pt)
   {
     if (!gequal1(a))
@@ -1471,8 +1437,8 @@ Z_ispow2(GEN n)
   return !(u & (u-1)); /* faster than hamming_word(u) == 1 */
 }
 
-long
-isprimepower(GEN n, GEN *pt)
+static long
+isprimepower_i(GEN n, GEN *pt, long flag)
 {
   pari_sp av = avma;
   long i, v;
@@ -1505,10 +1471,14 @@ isprimepower(GEN n, GEN *pt)
   }
   /* p | n => p >= 103 */
   v = Z_isanypower_nosmalldiv(&n); /* expensive */
-  if (!isprime(n)) { avma = av; return 0; }
+  if (!(flag? isprime(n): BPSW_psp(n))) { avma = av; return 0; }
   if (pt) *pt = gerepilecopy(av, n); else avma = av;
   return v;
 }
+long
+isprimepower(GEN n, GEN *pt) { return isprimepower_i(n,pt,1); }
+long
+ispseudoprimepower(GEN n, GEN *pt) { return isprimepower_i(n,pt,0); }
 
 long
 uisprimepower(ulong n, ulong *pp)
@@ -1643,7 +1613,7 @@ krouu_s(ulong x, ulong y, long s)
 long
 kronecker(GEN x, GEN y)
 {
-  pari_sp av = avma, lim;
+  pari_sp av = avma;
   long s = 1, r;
   ulong xu, yu;
 
@@ -1661,7 +1631,6 @@ kronecker(GEN x, GEN y)
     if (odd(r) && gome(x)) s = -s;
     y = shifti(y,-r);
   }
-  lim = stack_lim(av,2);
   x = modii(x,y);
   while (lgefint(x) > 3) /* x < y */
   {
@@ -1675,7 +1644,7 @@ kronecker(GEN x, GEN y)
     /* x=3 mod 4 && y=3 mod 4 ? (both are odd here) */
     if (mod2BIL(x) & mod2BIL(y) & 2) s = -s;
     z = remii(y,x); y = x; x = z;
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"kronecker");
       gerepileall(av, 2, &x, &y);
@@ -1699,7 +1668,7 @@ long
 krois(GEN x, long y)
 {
   ulong yu;
-  long s = 1, r;
+  long s = 1;
 
   if (y <= 0)
   {
@@ -1708,12 +1677,12 @@ krois(GEN x, long y)
   }
   else
     yu = (ulong)y;
-  r = vals(yu);
-  if (r)
+  if (!odd(yu))
   {
+    long r;
     if (!mpodd(x)) return 0;
+    r = vals(yu); yu >>= r;
     if (odd(r) && gome(x)) s = -s;
-    yu >>= r;
   }
   return krouu_s(umodiu(x, yu), yu, s);
 }
@@ -1721,14 +1690,29 @@ krois(GEN x, long y)
 long
 kroiu(GEN x, ulong y)
 {
-  long s = 1, r = vals(y);
+  long r;
+  if (odd(y)) return krouu_s(umodiu(x,y), y, 1);
+  if (!mpodd(x)) return 0;
+  r = vals(y); y >>= r;
+  return krouu_s(umodiu(x,y), y, (odd(r) && gome(x))? -1: 1);
+}
+
+/* assume y > 0, odd, return s * kronecker(x,y) */
+static long
+krouodd(ulong x, GEN y, long s)
+{
+  long r;
+  if (lgefint(y) == 3) return krouu_s(x, y[2], s);
+  if (!x) return 0; /* y != 1 */
+  r = vals(x);
   if (r)
   {
-    if (!mpodd(x)) return 0;
-    if (odd(r) && gome(x)) s = -s;
-    y >>= r;
+    if (odd(r) && gome(y)) s = -s;
+    x >>= r;
   }
-  return krouu_s(umodiu(x, y), y, s);
+  /* x=3 mod 4 && y=3 mod 4 ? (both are odd here) */
+  if (x & mod2BIL(y) & 2) s = -s;
+  return krouu_s(umodiu(y,x), x, s);
 }
 
 long
@@ -1736,8 +1720,6 @@ krosi(long x, GEN y)
 {
   const pari_sp av = avma;
   long s = 1, r;
-  ulong u, xu;
-
   switch (signe(y))
   {
     case -1: y = negi(y); if (x < 0) s = -1; break;
@@ -1751,27 +1733,36 @@ krosi(long x, GEN y)
     y = shifti(y,-r);
   }
   if (x < 0) { x = -x; if (mod4(y) == 3) s = -s; }
-  xu = (ulong)x;
-  if (lgefint(y) == 3)
-    return krouu_s(xu, itou(y), s);
-  if (!xu) return 0; /* y != 1 */
-  r = vals(xu);
+  s = krouodd((ulong)x, y, s);
+  avma = av; return s;
+}
+
+long
+kroui(ulong x, GEN y)
+{
+  const pari_sp av = avma;
+  long s = 1, r;
+  switch (signe(y))
+  {
+    case -1: y = negi(y); break;
+    case 0: return x==1UL;
+  }
+  r = vali(y);
   if (r)
   {
-    if (odd(r) && gome(y)) s = -s;
-    xu >>= r;
+    if (!odd(x)) { avma = av; return 0; }
+    if (odd(r) && ome(x)) s = -s;
+    y = shifti(y,-r);
   }
-  /* xu=3 mod 4 && y=3 mod 4 ? (both are odd here) */
-  if (xu & mod2BIL(y) & 2) s = -s;
-  u = umodiu(y, xu);
-  avma = av; return krouu_s(u, xu, s);
+  s = krouodd(x, y, s);
+  avma = av; return s;
 }
 
 long
 kross(long x, long y)
 {
   ulong yu;
-  long s = 1, r;
+  long s = 1;
 
   if (y <= 0)
   {
@@ -1780,12 +1771,12 @@ kross(long x, long y)
   }
   else
     yu = (ulong)y;
-  r = vals(yu);
-  if (r)
+  if (!odd(yu))
   {
+    long r;
     if (!odd(x)) return 0;
+    r = vals(yu); yu >>= r;
     if (odd(r) && ome(x)) s = -s;
-    yu >>= r;
   }
   x %= (long)yu; if (x < 0) x += yu;
   return krouu_s((ulong)x, yu, s);
@@ -1795,10 +1786,10 @@ long
 krouu(ulong x, ulong y)
 {
   long r;
-  if (y & 1) return krouu_s(x, y, 1);
+  if (odd(y)) return krouu_s(x, y, 1);
   if (!odd(x)) return 0;
-  r = vals(y);
-  return krouu_s(x, y >> r, (odd(r) && ome(x))? -1: 1);
+  r = vals(y); y >>= r;
+  return krouu_s(x, y, (odd(r) && ome(x))? -1: 1);
 }
 
 /*********************************************************************/
@@ -1939,12 +1930,35 @@ hilbert(GEN x, GEN y, GEN p)
 /*                                                                 */
 /*******************************************************************/
 
+static ulong
+Fl_2gener_pre_all(long e, ulong p, ulong pi, ulong *pt_m)
+{
+  ulong y, m;
+  long k, i;
+  ulong q = (p-1) >> e; /* q = (p-1)/2^oo is odd */
+  for (k=2; ; k++)
+  { /* loop terminates for k < p (even if p composite) */
+    i = krouu(k, p);
+    if (i >= 0)
+    {
+      if (i) continue;
+      pari_err_PRIME("Fl_sqrt [modulus]",utoi(p));
+    }
+    y = m = Fl_powu_pre(k, q, p, pi);
+    for (i=1; i<e; i++)
+      if ((m = Fl_sqr_pre(m, p, pi)) == 1) break;
+    if (i == e) break; /* success */
+  }
+  *pt_m = m;
+  return y;
+}
+
 /* Tonelli-Shanks. Assume p is prime and (a,p) != -1. */
-ulong
-Fl_sqrt(ulong a, ulong p)
+static ulong
+Fl_sqrt_i(ulong a, ulong p, ulong pi, ulong y, ulong m)
 {
   long i, e, k;
-  ulong p1, q, v, y, w, m;
+  ulong p1, q, v, w;
 
   if (!a) return 0;
   p1 = p - 1; e = vals(p1);
@@ -1954,43 +1968,115 @@ Fl_sqrt(ulong a, ulong p)
     return ((a & 1) == 0)? 0: 1;
   }
   q = p1 >> e; /* q = (p-1)/2^oo is odd */
-  if (e == 1) y = p1;
-  else /* look for an odd power of a primitive root */
-    for (k=2; ; k++)
-    { /* loop terminates for k < p (even if p composite) */
-      i = krouu(k, p);
-      if (i >= 0)
-      {
-        if (i) continue;
-        pari_err_PRIME("Fl_sqrt [modulus]",utoi(p));
-      }
-      y = m = Fl_powu(k, q, p);
-      for (i=1; i<e; i++)
-        if ((m = Fl_sqr(m,p)) == 1) break;
-      if (i == e) break; /* success */
-    }
-
-  p1 = Fl_powu(a, q >> 1, p); /* a ^ [(q-1)/2] */
+  if (e == 1)    y = p1;
+  else if (y==0) y = Fl_2gener_pre_all(e, p, pi, &m);
+  p1 = Fl_powu_pre(a, q >> 1, p, pi); /* a ^ [(q-1)/2] */
   if (!p1) return 0;
-  v = Fl_mul(a, p1, p);
-  w = Fl_mul(v, p1, p);
+  v = Fl_mul_pre(a, p1, p, pi);
+  w = Fl_mul_pre(v, p1, p, pi);
   while (w != 1)
   { /* a*w = v^2, y primitive 2^e-th root of 1
        a square --> w even power of y, hence w^(2^(e-1)) = 1 */
-    p1 = Fl_sqr(w,p);
-    for (k=1; p1 != 1 && k < e; k++) p1 = Fl_sqr(p1,p);
+    p1 = Fl_sqr_pre(w,p,pi);
+    for (k=1; p1 != 1 && k < e; k++) p1 = Fl_sqr_pre(p1,p,pi);
     if (k == e) return ~0UL;
     /* w ^ (2^k) = 1 --> w = y ^ (u * 2^(e-k)), u odd */
     p1 = y;
-    for (i=1; i < e-k; i++) p1 = Fl_sqr(p1,p);
-    y = Fl_sqr(p1, p); e = k;
-    w = Fl_mul(y, w, p);
-    v = Fl_mul(v, p1, p);
+    for (i=1; i < e-k; i++) p1 = Fl_sqr_pre(p1, p, pi);
+    y = Fl_sqr_pre(p1, p, pi); e = k;
+    w = Fl_mul_pre(y, w, p, pi);
+    v = Fl_mul_pre(v, p1, p, pi);
   }
   p1 = p - v; if (v > p1) v = p1;
   return v;
 }
 
+ulong
+Fl_sqrt(ulong a, ulong p)
+{
+  ulong pi = get_Fl_red(p);
+  return Fl_sqrt_i(a, p, pi, 0, 0);
+}
+
+ulong
+Fl_sqrt_pre(ulong a, ulong p, ulong pi)
+{
+  return Fl_sqrt_i(a, p, pi, 0, 0);
+}
+
+static ulong
+Fl_lgener_pre_all(ulong l, long e, ulong r, ulong p, ulong pi, ulong *pt_m)
+{
+  ulong x, y, m;
+  ulong le1 = upowuu(l, e-1);
+  for (x = 2; ; x++)
+  {
+    y = Fl_powu_pre(x, r, p, pi);
+    if (y==1) continue;
+    m = Fl_powu_pre(y, le1, p, pi);
+    if (m != 1) break;
+  }
+  *pt_m = m;
+  return y;
+}
+
+/* solve x^l = a , l prime in G of order q.
+ *
+ * q =  (l^e)*r, e >= 1, (r,l) = 1
+ * y generates the l-Sylow of G
+ * m = y^(l^(e-1)) != 1 */
+static ulong
+Fl_sqrtl_i(ulong a, ulong l, ulong p, ulong pi, ulong y, ulong m)
+{
+  ulong p1, v, w, z, dl, zm;
+  ulong r, e, u2;
+  if (a==0) return a;
+  e = u_lvalrem(p-1, l, &r);
+  u2 = Fl_inv(l%r, r);
+  v = Fl_powu_pre(a, u2, p,pi);
+  w = Fl_powu_pre(v, l, p,pi);
+  w = Fl_mul_pre(w, Fl_inv(a, p),p,pi);
+  if (w==1) return v;
+  if (y==0) y = Fl_lgener_pre_all(l, e, r, p, pi, &m);
+  while (w!=1)
+  {
+    ulong k = 0;
+    p1 = w;
+    do
+    {
+      z = p1; p1 = Fl_powu_pre(p1, l, p, pi);
+      k++;
+    } while (p1!=1);
+    if (k==e) return ~0UL;
+    dl = 0; zm = 1;
+    while (z!=zm)
+    {
+      zm = Fl_mul_pre(zm, m, p, pi); dl++;
+    }
+    dl = Fl_neg(dl, l);
+    p1 = Fl_powu_pre(y,dl*upowuu(l,e-k-1),p,pi);
+    m = Fl_powu_pre(m, dl, p, pi);
+    e = k;
+    v = Fl_mul_pre(p1,v,p,pi);
+    y = Fl_powu_pre(p1,l,p,pi);
+    w = Fl_mul_pre(y,w,p,pi);
+  }
+  return v;
+}
+
+ulong
+Fl_sqrtl_pre(ulong a, ulong l, ulong p, ulong pi)
+{
+  return Fl_sqrtl_i(a, l, p, pi, 0, 0);
+}
+
+ulong
+Fl_sqrtl(ulong a, ulong l, ulong p)
+{
+  ulong pi = get_Fl_red(p);
+  return Fl_sqrtl_i(a, l, p, pi, 0, 0);
+}
+
 /* Cipolla is better than Tonelli-Shanks when e = v_2(p-1) is "too big".
  * Otherwise, is a constant times worse; for p = 3 (mod 4), is about 3 times worse,
  * and in average is about 2 or 2.5 times worse. But try both algorithms for
@@ -2067,7 +2153,7 @@ sqrt_Cipolla(GEN a, GEN p)
 GEN
 Fp_sqrt(GEN a, GEN p)
 {
-  pari_sp av = avma, av1,lim;
+  pari_sp av = avma, av1;
   long i, k, e;
   GEN p1, q, v, y, w, m;
 
@@ -2076,7 +2162,7 @@ Fp_sqrt(GEN a, GEN p)
   if (signe(p) <= 0 || equali1(p)) pari_err_PRIME("Fp_sqrt",p);
   if (lgefint(p) == 3)
   {
-    ulong u = (ulong)p[2]; u = Fl_sqrt(umodiu(a, u), u);
+    ulong pp = uel(p,2), u = Fl_sqrt(umodiu(a, pp), pp);
     if (u == ~0UL) return NULL;
     return utoi(u);
   }
@@ -2125,7 +2211,6 @@ Fp_sqrt(GEN a, GEN p)
   if (!signe(p1)) { avma=av; return gen_0; }
   v = Fp_mul(a, p1, p);
   w = Fp_mul(v, p1, p);
-  lim = stack_lim(av,1);
   while (!equali1(w))
   { /* a*w = v^2, y primitive 2^e-th root of 1
        a square --> w even power of y, hence w^(2^(e-1)) = 1 */
@@ -2138,7 +2223,7 @@ Fp_sqrt(GEN a, GEN p)
     y = sqrmod(p1, p); e = k;
     w = Fp_mul(y, w, p);
     v = Fp_mul(v, p1, p);
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"Fp_sqrt");
       gerepileall(av,3, &y,&w,&v);
@@ -2337,6 +2422,386 @@ chinese1_coprime_Z(GEN x) {return gassoc_proto(chinese1_coprime_Z_aux,x,NULL);}
 /**                                                                 **/
 /*********************************************************************/
 
+/* xa, ya = t_VECSMALL */
+GEN
+ZV_producttree(GEN xa)
+{
+  long n = lg(xa)-1;
+  long m = n==1 ? 1: expu(n-1)+1;
+  GEN T = cgetg(m+1, t_VEC), t;
+  long i, j, k;
+  t = cgetg(((n+1)>>1)+1, t_VEC);
+  if (typ(xa)==t_VECSMALL)
+  {
+    for (j=1, k=1; k<n; j++, k+=2)
+      gel(t, j) = muluu(xa[k], xa[k+1]);
+    if (k==n) gel(t, j) = utoi(xa[k]);
+  } else {
+    for (j=1, k=1; k<n; j++, k+=2)
+      gel(t, j) = mulii(gel(xa,k), gel(xa,k+1));
+    if (k==n) gel(t, j) = icopy(gel(xa,k));
+  }
+  gel(T,1) = t;
+  for (i=2; i<=m; i++)
+  {
+    GEN u = gel(T, i-1);
+    long n = lg(u)-1;
+    t = cgetg(((n+1)>>1)+1, t_VEC);
+    for (j=1, k=1; k<n; j++, k+=2)
+      gel(t, j) = mulii(gel(u, k), gel(u, k+1));
+    if (k==n) gel(t, j) = gel(u, k);
+    gel(T, i) = t;
+  }
+  return T;
+}
+
+static GEN
+Z_ZV_mod_tree(GEN P, GEN xa, GEN T)
+{
+  long i,j,k;
+  long m = lg(T)-1, n = lg(xa)-1;
+  GEN t;
+  GEN Tp = cgetg(m+1, t_VEC);
+  gel(Tp, m) = mkvec(P);
+  for (i=m-1; i>=1; i--)
+  {
+    GEN u = gel(T, i);
+    GEN v = gel(Tp, i+1);
+    long n = lg(u)-1;
+    t = cgetg(n+1, t_VEC);
+    for (j=1, k=1; k<n; j++, k+=2)
+    {
+      gel(t, k)   = modii(gel(v, j), gel(u, k));
+      gel(t, k+1) = modii(gel(v, j), gel(u, k+1));
+    }
+    if (k==n) gel(t, k) = gel(v, j);
+    gel(Tp, i) = t;
+  }
+  {
+    GEN u = gel(T, i+1);
+    GEN v = gel(Tp, i+1);
+    long l = lg(u)-1;
+    if (typ(xa)==t_VECSMALL)
+    {
+      GEN R = cgetg(n+1, t_VECSMALL);
+      for (j=1, k=1; j<=l; j++, k+=2)
+      {
+        uel(R,k) = umodiu(gel(v, j), xa[k]);
+        if (k < n)
+          uel(R,k+1) = umodiu(gel(v, j), xa[k+1]);
+      }
+      return R;
+    }
+    else
+    {
+      GEN R = cgetg(n+1, t_VEC);
+      for (j=1, k=1; j<=l; j++, k+=2)
+      {
+        gel(R,k) = modii(gel(v, j), gel(xa,k));
+        if (k < n)
+          gel(R,k+1) = modii(gel(v, j), gel(xa,k+1));
+      }
+      return R;
+    }
+  }
+}
+
+static GEN
+ZV_polint_tree(GEN T, GEN R, GEN xa, GEN ya)
+{
+  long m = lg(T)-1, n = lg(ya)-1;
+  long i,j,k;
+  GEN Tp = cgetg(m+1, t_VEC);
+  GEN M = gel(T, 1);
+  GEN t = cgetg(lg(M), t_VEC);
+  if (typ(xa)==t_VECSMALL)
+  {
+    for (j=1, k=1; k<n; j++, k+=2)
+    {
+      pari_sp av = avma;
+      GEN a = mului(ya[k], gel(R,k)), b = mului(ya[k+1], gel(R,k+1));
+      GEN tj = modii(addii(mului(xa[k],b), mului(xa[k+1],a)), gel(M,j));
+      gel(t, j) = gerepileuptoint(av, tj);
+    }
+    if (k==n) gel(t, j) = modii(mului(ya[k], gel(R,k)), gel(M, j));
+  } else
+  {
+    for (j=1, k=1; k<n; j++, k+=2)
+    {
+      pari_sp av = avma;
+      GEN a = mulii(gel(ya,k), gel(R,k)), b = mulii(gel(ya,k+1), gel(R,k+1));
+      GEN tj = modii(addii(mulii(gel(xa,k),b), mulii(gel(xa,k+1),a)), gel(M,j));
+      gel(t, j) = gerepileuptoint(av, tj);
+    }
+    if (k==n) gel(t, j) = modii(mulii(gel(ya,k), gel(R,k)), gel(M, j));
+  }
+  gel(Tp, 1) = t;
+  for (i=2; i<=m; i++)
+  {
+    GEN u = gel(T, i-1), M = gel(T, i);
+    GEN t = cgetg(lg(M), t_VEC);
+    GEN v = gel(Tp, i-1);
+    long n = lg(v)-1;
+    for (j=1, k=1; k<n; j++, k+=2)
+    {
+      pari_sp av = avma;
+      gel(t, j) = gerepileuptoint(av, modii(addii(mulii(gel(u, k), gel(v, k+1)),
+            mulii(gel(u, k+1), gel(v, k))), gel(M, j)));
+    }
+    if (k==n) gel(t, j) = gel(v, k);
+    gel(Tp, i) = t;
+  }
+  return gmael(Tp,m,1);
+}
+
+static GEN
+ncV_polint_tree(GEN T, GEN R, GEN xa, GEN Va)
+{
+  long i, j, l = lg(gel(Va,1)), n = lg(xa);
+  GEN V = cgetg(l, t_COL);
+  for(i=1; i < l; i++)
+  {
+    pari_sp av = avma;
+    GEN ya = cgetg(n, t_VECSMALL);
+    for(j=1; j < n; j++)
+      ya[j] = mael(Va,j,i);
+    gel(V,i) = gerepilecopy(av, ZV_polint_tree(T, R, xa, ya));
+  }
+  return V;
+}
+
+static GEN
+nmV_polint_tree(GEN T, GEN R, GEN xa, GEN Ma)
+{
+  long i, j, l = lg(gel(Ma,1)), n = lg(xa);
+  GEN ya = cgetg(n, t_VEC);
+  GEN M = cgetg(l, t_MAT);
+  for(i=1; i < l; i++)
+  {
+    for(j=1; j < n; j++)
+      gel(ya,j) = gmael(Ma,j,i);
+    gel(M,i) = ncV_polint_tree(T, R, xa, ya);
+  }
+  return M;
+}
+GEN
+Z_ZV_mod(GEN P, GEN xa)
+{
+  pari_sp av = avma;
+  GEN T = ZV_producttree(xa);
+  return gerepileuptoleaf(av, Z_ZV_mod_tree(P, xa, T));
+}
+
+GEN
+Z_nv_mod(GEN P, GEN xa)
+{
+  return Z_ZV_mod(P, xa);
+}
+
+GEN
+ZX_nv_mod_tree(GEN P, GEN xa, GEN T)
+{
+  long i, j, l = lg(P), n = lg(xa)-1;
+  GEN V = cgetg(n+1, t_VEC);
+  for (j=1; j <= n; j++)
+  {
+    gel(V, j) = cgetg(l, t_VECSMALL);
+    mael(V, j, 1) = P[1]&VARNBITS;
+  }
+  for (i=2; i < l; i++)
+  {
+    GEN v = Z_ZV_mod_tree(gel(P, i), xa, T);
+    for (j=1; j <= n; j++)
+      mael(V, j, i) = v[j];
+  }
+  for (j=1; j <= n; j++)
+    (void) Flx_renormalize(gel(V, j), l);
+  return V;
+}
+
+static GEN
+ZV_sqr(GEN z)
+{
+  long i,l = lg(z);
+  GEN x = cgetg(l, t_VEC);
+  if (typ(z)==t_VECSMALL)
+    for (i=1; i<l; i++) gel(x,i) = sqru(z[i]);
+  else
+    for (i=1; i<l; i++) gel(x,i) = sqri(gel(z,i));
+  return x;
+}
+
+static GEN
+ZT_sqr(GEN z)
+{
+  if (typ(z) == t_INT)
+    return sqri(z);
+  else
+  {
+    long i,l = lg(z);
+    GEN x = cgetg(l, t_VEC);
+    for (i=1; i<l; i++) gel(x,i) = ZT_sqr(gel(z,i));
+    return x;
+  }
+}
+
+static GEN
+ZV_invdivexact(GEN y, GEN x)
+{
+  long i, l = lg(y);
+  GEN z = cgetg(l,t_VEC);
+  if (typ(x)==t_VECSMALL)
+    for (i=1; i<l; i++)
+    {
+      pari_sp av = avma;
+      ulong a = Fl_inv(umodiu(diviuexact(gel(y,i),x[i]), x[i]), x[i]);
+      avma = av;
+      gel(z,i) = utoi(a);
+    }
+  else
+    for (i=1; i<l; i++)
+      gel(z,i) = Fp_inv(diviiexact(gel(y,i), gel(x,i)), gel(x,i));
+  return z;
+}
+
+static GEN
+ZV_chinesetree(GEN T, GEN xa)
+{
+  GEN T2 = ZT_sqr(T), xa2 = ZV_sqr(xa);
+  GEN mod = gmael(T,lg(T)-1,1);
+  return ZV_invdivexact(Z_ZV_mod_tree(mod, xa2, T2), xa);
+}
+
+GEN
+ZV_chinese_tree(GEN A, GEN P, GEN T, GEN *pt_mod)
+{
+  pari_sp av = avma;
+  GEN R = ZV_chinesetree(T, P);
+  GEN a = ZV_polint_tree(T, R, P, A);
+  if (!pt_mod)
+    return gerepileuptoleaf(av, a);
+  else
+  {
+    GEN mod = gmael(T, lg(T)-1, 1);
+    gerepileall(av, 2, &a, &mod);
+    *pt_mod = mod;
+    return a;
+  }
+}
+
+GEN
+ZV_chinese(GEN A, GEN P, GEN *pt_mod)
+{
+  pari_sp av = avma;
+  GEN T = ZV_producttree(P);
+  GEN R = ZV_chinesetree(T, P);
+  GEN a = ZV_polint_tree(T, R, P, A);
+  if (!pt_mod)
+    return gerepileuptoint(av, a);
+  else
+  {
+    GEN mod = gmael(T, lg(T)-1, 1);
+    gerepileall(av, 2, &a, &mod);
+    *pt_mod = mod;
+    return a;
+  }
+}
+
+GEN
+nmV_chinese(GEN A, GEN P, GEN *pt_mod)
+{
+  pari_sp av = avma;
+  GEN T = ZV_producttree(P);
+  GEN R = ZV_chinesetree(T, P);
+  GEN a = nmV_polint_tree(T, R, P, A);
+  if (!pt_mod)
+    return gerepileupto(av, a);
+  else
+  {
+    GEN mod = gmael(T, lg(T)-1, 1);
+    gerepileall(av, 2, &a, &mod);
+    *pt_mod = mod;
+    return a;
+  }
+}
+
+/**********************************************************************
+ **                                                                  **
+ **                    Powering  over (Z/NZ)^*, small N              **
+ **                                                                  **
+ **********************************************************************/
+
+ulong
+Fl_powu_pre(ulong x, ulong n0, ulong p, ulong pi)
+{
+  ulong y, z, n;
+  if (n0 <= 1)
+  { /* frequent special cases */
+    if (n0 == 1) return x;
+    if (n0 == 0) return 1;
+  }
+  if (x <= 1) return x; /* 0 or 1 */
+  y = 1; z = x; n = n0;
+  for(;;)
+  {
+    if (n&1) y = Fl_mul_pre(y,z,p,pi);
+    n>>=1; if (!n) return y;
+    z = Fl_sqr_pre(z,p,pi);
+  }
+}
+
+ulong
+Fl_powu(ulong x, ulong n0, ulong p)
+{
+  ulong y, z, n;
+  if (n0 <= 2)
+  { /* frequent special cases */
+    if (n0 == 2) return Fl_sqr(x,p);
+    if (n0 == 1) return x;
+    if (n0 == 0) return 1;
+  }
+  if (x <= 1) return x; /* 0 or 1 */
+  if (!SMALL_ULONG(p))
+    return Fl_powu_pre(x, n0, p, get_Fl_red(p));
+  y = 1; z = x; n = n0;
+  for(;;)
+  {
+    if (n&1) y = Fl_mul(y,z,p);
+    n>>=1; if (!n) return y;
+    z = Fl_sqr(z,p);
+  }
+}
+
+/* Reduce data dependency to maximize internal parallelism */
+GEN
+Fl_powers_pre(ulong x, long n, ulong p, ulong pi)
+{
+  long i, k;
+  GEN powers = cgetg(n + 2, t_VECSMALL);
+  powers[1] = 1; if (n == 0) return powers;
+  powers[2] = x;
+  for (i = 3, k=2; i <= n; i+=2, k++)
+  {
+    powers[i] = Fl_mul_pre(powers[k], powers[k], p, pi);
+    powers[i+1] = Fl_mul_pre(powers[k], powers[k+1], p, pi);
+  }
+  if (i==n+1)
+    powers[i] = Fl_mul_pre(powers[k], powers[k], p, pi);
+  return powers;
+}
+
+GEN
+Fl_powers(ulong x, long n, ulong p)
+{
+  return Fl_powers_pre(x, n, p, get_Fl_red(p));
+}
+
+/**********************************************************************
+ **                                                                  **
+ **                    Powering  over (Z/NZ)^*, large N              **
+ **                                                                  **
+ **********************************************************************/
+
 /* modified Barrett reduction with one fold */
 /* See Fast Modular Reduction, W. Hasenplaugh, G. Gaubatz, V. Gopal, ARITH 18 */
 
@@ -2347,20 +2812,23 @@ Fp_invmBarrett(GEN p, long s)
   return mkvec2(Q,R);
 }
 
+/* a <= (N-1)^2, 2^(2s-2) <= N < 2^(2s). Return 0 <= r < N such that
+ * a = r (mod N) */
 static GEN
-Fp_rem_mBarrett(GEN a, GEN B, long s, GEN p)
+Fp_rem_mBarrett(GEN a, GEN B, long s, GEN N)
 {
   pari_sp av = avma;
-  GEN Q = gel(B, 1), R = gel(B, 2);
-  long sQ = expi(Q);
-  GEN A = addii(remi2n(a, 3*s), mulii(R,shifti(a, -3*s)));
-  GEN q = shifti(mulii(shifti(A, sQ-3*s), Q), -sQ);
-  GEN r = subii(A, mulii(q, p));
-  GEN sr= subii(r,p);     /* Now 0 <= r < 4*p */
+  GEN P = gel(B, 1), Q = gel(B, 2); /* 2^(3s) = P N + Q, 0 <= Q < N */
+  long t = expi(P)+1; /* 2^(t-1) <= P < 2^t */
+  GEN u = shifti(a, -3*s), v = remi2n(a, 3*s); /* a = 2^(3s)u + v */
+  GEN A = addii(v, mulii(Q,u)); /* 0 <= A < 2^(3s+1) */
+  GEN q = shifti(mulii(shifti(A, t-3*s), P), -t); /* A/N - 4 < q <= A/N */
+  GEN r = subii(A, mulii(q, N));
+  GEN sr= subii(r,N);     /* 0 <= r < 4*N */
   if (signe(sr)<0) return gerepileuptoint(av, r);
-  r=sr; sr = subii(r,p);  /* Now 0 <= r < 3*p */
+  r=sr; sr = subii(r,N);  /* 0 <= r < 3*N */
   if (signe(sr)<0) return gerepileuptoint(av, r);
-  r=sr; sr = subii(r,p);  /* Now 0 <= r < 2*p */
+  r=sr; sr = subii(r,N);  /* 0 <= r < 2*N */
   return gerepileuptoint(av, signe(sr)>=0 ? sr:r);
 }
 
@@ -2388,7 +2856,15 @@ static GEN
 _remii(muldata *D, GEN x) { return remii(x, D->N); }
 
 static GEN
-_remiibar(muldata *D, GEN x) { return Fp_rem_mBarrett(x, D->iM, D->s, D->N); }
+_remiibar(muldata *D, GEN x) {
+#if DEBUG
+  GEN r = Fp_rem_mBarrett(x, D->iM, D->s, D->N);
+  if (cmpii(r, D->N) >= 0) pari_err_BUG("Rp_rem_mBarrett");
+  return r;
+#else
+  return Fp_rem_mBarrett(x, D->iM, D->s, D->N);
+#endif
+}
 
 /* 2x mod N */
 static GEN
@@ -2423,25 +2899,6 @@ _m2sqr(void *data, GEN x)
   muldata *D = (muldata *)data;
   return D->mul2(D, D->res(D, sqri(x)));
 }
-ulong
-Fl_powu(ulong x, ulong n0, ulong p)
-{
-  ulong y, z, n;
-  if (n0 <= 2)
-  { /* frequent special cases */
-    if (n0 == 2) return Fl_sqr(x,p);
-    if (n0 == 1) return x;
-    if (n0 == 0) return 1;
-  }
-  if (x <= 1) return x; /* 0 or 1 */
-  y = 1; z = x; n = n0;
-  for(;;)
-  {
-    if (n&1) y = Fl_mul(y,z,p);
-    n>>=1; if (!n) return y;
-    z = Fl_sqr(z,p);
-  }
-}
 
 static long
 Fp_select_red(GEN *y, ulong k, GEN N, long lN, muldata *D)
@@ -2480,7 +2937,7 @@ Fp_powu(GEN A, ulong k, GEN N)
   pari_sp av;
 
   if (lN == 3) {
-    ulong n = (ulong)N[2];
+    ulong n = uel(N,2);
     return utoi( Fl_powu(umodiu(A, n), k, n) );
   }
   if (k <= 2)
@@ -2571,7 +3028,7 @@ Fp_pow(GEN A, GEN K, GEN N)
         k = umodiu(negi(K), eulerphiu(n));
     }
     else
-      k = (ulong)K[2];
+      k = uel(K,2);
     return utoi(Fl_powu(a, k, n));
   }
 
@@ -2610,6 +3067,20 @@ static GEN
 _Fp_mul(void *E, GEN x, GEN y) { return Fp_mul(x,y,(GEN)E); }
 
 static GEN
+_Fp_sqr(void *E, GEN x) { return Fp_sqr(x,(GEN)E); }
+
+static GEN
+_Fp_one(void *E) { (void) E; return gen_1; }
+
+GEN
+Fp_powers(GEN x, long n, GEN p)
+{
+  if (lgefint(p) == 3)
+    return Flv_to_ZV(Fl_powers(umodiu(x, uel(p, 2)), n, uel(p, 2)));
+  return gen_powers(x, n, 1, (void*)p, _Fp_sqr, _Fp_mul, _Fp_one);
+}
+
+static GEN
 _Fp_pow(void *E, GEN x, GEN n) { return Fp_pow(x,n,(GEN)E); }
 
 static GEN
@@ -2997,6 +3468,12 @@ Fp_log_index(GEN a, GEN b, GEN m, GEN p)
   return gerepileuptoint(av, l);
 }
 
+static int
+Fp_log_use_index(long e, long p)
+{
+  return (e >= 27 && 20*(p+6)<=e*e);
+}
+
 /* Trivial cases a = 1, -1. Return x s.t. g^x = a or [] if no such x exist */
 static GEN
 Fp_easylog(void *E, GEN a, GEN g, GEN ord)
@@ -3017,7 +3494,7 @@ Fp_easylog(void *E, GEN a, GEN g, GEN ord)
     if (!equalii(Fp_pow(g, t, p), a)) { avma = av; return cgetg(1, t_VEC); }
     avma = av2; return gerepileuptoint(av, t);
   }
-  if (typ(ord)==t_INT && expi(ord)>=27 && BPSW_psp(p))
+  if (typ(ord)==t_INT && BPSW_psp(p) && Fp_log_use_index(expi(ord),expi(p)))
     return Fp_log_index(a, g, ord, p);
   avma = av; return NULL; /* not easy */
 }
@@ -3026,8 +3503,13 @@ GEN
 Fp_log(GEN a, GEN g, GEN ord, GEN p)
 {
   GEN v = dlog_get_ordfa(ord);
-  ord = mkvec2(gel(v,1),ZM_famat_limit(gel(v,2),int2n(27)));
-  return gen_PH_log(a,g,ord,(void*)p,&Fp_star);
+  GEN F = gmael(v,2,1);
+  long lF = lg(F)-1, lmax;
+  if (lF == 0) return equali1(a)? gen_0: cgetg(1, t_VEC);
+  lmax = expi(gel(F,lF));
+  if (BPSW_psp(p) && Fp_log_use_index(lmax,expi(p)))
+    v = mkvec2(gel(v,1),ZM_famat_limit(gel(v,2),int2n(27)));
+  return gen_PH_log(a,g,v,(void*)p,&Fp_star);
 }
 
 /* find x such that h = g^x mod N > 1, N = prod_{i <= l} P[i]^E[i], P[i] prime.
@@ -3056,9 +3538,9 @@ znlog_rec(GEN h, GEN g, GEN N, GEN P, GEN E, GEN PHI)
   if (hp == gen_0 || gp == gen_0) return NULL;
   if (equaliu(p, 2))
   {
-    GEN N = int2n(e);
-    ogpe = Zp_order(gpe, gen_2, e, N);
-    a = Fp_log(hpe, gpe, ogpe, N);
+    GEN n = int2n(e);
+    ogpe = Zp_order(gpe, gen_2, e, n);
+    a = Fp_log(hpe, gpe, ogpe, n);
     if (typ(a) != t_INT) return NULL;
   }
   else
@@ -3360,7 +3842,7 @@ Qsfcont(GEN a, GEN b, GEN y, ulong k)
   GEN  z, c;
   ulong i, l, ly = lgefint(b);
 
-  /* times log(2) / log2( (1+sqrt(5)) / 2 )  */
+  /* times 1 / log2( (1+sqrt(5)) / 2 )  */
   l = (ulong)(3 + bit_accuracy_mul(ly, 1.44042009041256));
   if (k > 0 && k+1 > 0 && l > k+1) l = k+1; /* beware overflow */
   if (l > LGBITS) l = LGBITS;
@@ -3573,7 +4055,7 @@ contfracpnqn(GEN x, long n)
     if (lx == 2) return gerepilecopy(av, mkmat(mkcol2(p1,q1)));
   }
   else if (lx == 2)
-    return gerepilecopy(av, mkmat2(mkcol2(gen_1,gen_0), mkcol2(p1,q1)));
+    return gerepilecopy(av, mkmat2(mkcol2(p1,q1), mkcol2(gen_1,gen_0)));
   /* lx >= 3 */
   p0 = gen_1;
   q0 = gen_0; /* p[-1], q[-1] */
@@ -3596,6 +4078,26 @@ contfracpnqn(GEN x, long n)
 }
 GEN
 pnqn(GEN x) { return contfracpnqn(x,-1); }
+/* x = [a0, ..., an] from gboundcf, n >= 0;
+ * return [[p0, ..., pn], [q0,...,qn]] */
+GEN
+ZV_allpnqn(GEN x)
+{
+  long i, lx = lg(x);
+  GEN p0, p1, q0, q1, p2, q2, P,Q, v = cgetg(3,t_VEC);
+
+  gel(v,1) = P = cgetg(lx, t_VEC);
+  gel(v,2) = Q = cgetg(lx, t_VEC);
+  p0 = gen_1; q0 = gen_0;
+  gel(P, 1) = p1 = gel(x,1); gel(Q, 1) = q1 = gen_1;
+  for (i=2; i<lx; i++)
+  {
+    GEN a = gel(x,i);
+    gel(P, i) = p2 = addmulii(p0, a, p1); p0 = p1; p1 = p2;
+    gel(Q, i) = q2 = addmulii(q0, a, q1); q0 = q1; q1 = q2;
+  }
+  return v;
+}
 
 /* write Mod(x,N) as a/b, gcd(a,b) = 1, b <= B (no condition if B = NULL) */
 static GEN
@@ -3776,7 +4278,10 @@ bestappr_Q(GEN x, GEN k)
       return gerepilecopy(av, a);
     }
 
-    case t_COMPLEX: case t_POLMOD: case t_POL: case t_SER: case t_RFRAC:
+    case t_SER:
+      if (ser_isexactzero(x)) return gcopy(x);
+      /* fall through */
+    case t_COMPLEX: case t_POLMOD: case t_POL: case t_RFRAC:
     case t_VEC: case t_COL: case t_MAT:
       y = cgetg_copy(x, &lx);
       if (lontyp[tx] == 1) i = 1; else { y[1] = x[1]; i = 2; }
@@ -3929,13 +4434,13 @@ update_f(GEN f, GEN a)
 GEN
 quadunit(GEN x)
 {
-  pari_sp av = avma, av2, lim;
+  pari_sp av = avma, av2;
   GEN pol, y, a, u, v, sqd, f;
   long r;
 
   check_quaddisc_real(x, &r, "quadunit");
   pol = quadpoly(x);
-  sqd = sqrti(x); av2 = avma; lim = stack_lim(av2,2);
+  sqd = sqrti(x); av2 = avma;
   a = shifti(addsi(r,sqd),-1);
   f = mkmat2(mkcol2(a, gen_1), mkcol2(gen_1, gen_0)); /* [a,0; 1,0] */
   u = stoi(r); v = gen_2;
@@ -3958,7 +4463,7 @@ quadunit(GEN x)
     }
     update_f(f,a);
     u = u1; v = v1;
-    if (low_stack(lim, stack_lim(av2,2)))
+    if (gc_needed(av2,2))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"quadunit");
       gerepileall(av2,4, &a,&f,&u,&v);
@@ -3971,7 +4476,7 @@ quadunit(GEN x)
 GEN
 quadregulator(GEN x, long prec)
 {
-  pari_sp av = avma, av2, lim;
+  pari_sp av = avma, av2;
   GEN R, rsqd, u, v, sqd;
   long r, Rexpo;
 
@@ -3979,7 +4484,7 @@ quadregulator(GEN x, long prec)
   sqd = sqrti(x);
   rsqd = gsqrt(x,prec);
   Rexpo = 0; R = real2n(1, prec); /* = 2 */
-  av2 = avma; lim = stack_lim(av2,2);
+  av2 = avma;
   u = stoi(r); v = gen_2;
   for(;;)
   {
@@ -4000,7 +4505,7 @@ quadregulator(GEN x, long prec)
     Rexpo += expo(R); setexpo(R,0);
     u = u1; v = v1;
     if (Rexpo & ~EXPOBITS) pari_err_OVERFLOW("quadregulator [exponent]");
-    if (low_stack(lim, stack_lim(av2,2)))
+    if (gc_needed(av2,2))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"quadregulator");
       gerepileall(av2,3, &R,&u,&v);
@@ -4023,8 +4528,17 @@ quadregulator(GEN x, long prec)
 /*************************************************************************/
 static int qfb_is_1(GEN f) { return equali1(gel(f,1)); }
 static GEN qfb_pow(void *E, GEN f, GEN n) { (void)E; return powgi(f,n); }
-static const struct bb_group qfb_group={ NULL,qfb_pow,NULL,NULL,
-                                         NULL,qfb_is_1,NULL};
+static GEN qfi_comp(void *E, GEN f, GEN g) { (void)E; return qficomp(f,g); }
+static ulong qfb_hash(GEN x)
+{
+  GEN a = gel(x,1);
+  GEN b = gel(x,2);
+  ulong A = mod2BIL(a);
+  ulong B = signe(b)? mod2BIL(b): 0;
+  return (A  << BITS_IN_HALFULONG) | B;
+}
+static const struct bb_group qfi_group={ qfi_comp,qfb_pow,NULL,qfb_hash,
+                                         gidentical,qfb_is_1,NULL};
 
 GEN
 qfbclassno0(GEN x,long flag)
@@ -4038,43 +4552,66 @@ qfbclassno0(GEN x,long flag)
   return NULL; /* not reached */
 }
 
-/* f^h = 1, return order(f) */
+/* f^h = 1, return order(f). Set *pfao to its factorization */
 static GEN
-find_order(GEN f, GEN h) { return gen_order(f, h, NULL, &qfb_group); }
+find_order(GEN f, GEN h, GEN *pfao)
+{
+  GEN v = gen_factored_order(f, h, NULL, &qfi_group);
+  *pfao = gel(v,2); return gel(v,1);
+}
 
-static GEN
-end_classno(GEN h, GEN hin, GEN forms)
+static int
+ok_q(GEN q, GEN h, GEN d2, long r2)
 {
-  GEN a, b, p1, q, fh, fg, f = gel(forms,1);
-  long i, com, l = lg(forms);
+  if (d2)
+  {
+    if (r2 <= 2 && !mpodd(q)) return 0;
+    return is_pm1(coprime_part(q,d2));
+  }
+  else
+  {
+    if (r2 <= 1 && !mpodd(q)) return 0;
+    return is_pm1(coprime_part(q,h));
+  }
+}
 
-  h = find_order(f,h); /* H = <f> */
-  q = diviiround(hin, h); /* approximate order of G/H */
-  for (i=2; i < l; i++)
+/* a,b given by their factorizations. Return factorization of lcm(a,b).
+ * Set A,B such that A*B = lcm(a, b), (A,B)=1, A|a, B|b */
+static GEN
+split_lcm(GEN a, GEN Fa, GEN b, GEN Fb, GEN *pA, GEN *pB)
+{
+  GEN P = ZV_union_shallow(gel(Fa,1), gel(Fb,1));
+  GEN A = gen_1, B = gen_1;
+  long i, l = lg(P);
+  GEN E = cgetg(l, t_COL);
+  for (i=1; i<l; i++)
   {
-    pari_sp av = avma;
-    fg = powgi(gel(forms,i), h);
-    fh = powgi(fg, q);
-    a = gel(fh,1);
-    if (equali1(a)) continue;
-    b = gel(fh,2); p1 = fg;
-    for (com=1; ; com++, p1 = gmul(p1,fg))
-      if (equalii(gel(p1,1), a) && absi_equal(gel(p1,2), b)) break;
-    if (signe(gel(p1,2)) == signe(b)) com = -com;
-    /* f_i ^ h(q+com) = 1 */
-    q = addsi(com,q);
-    if (gequal0(q))
-    { /* f^(ih) != 1 for all 0 < i <= oldq. Happen if the original upper bound
-         for h was wrong */
-      ulong c;
-      p1 = fh;
-      for (c=1; ; c++, p1 = gmul(p1,fh))
-        if (qfb_is_1(p1)) break;
-      q = mulsi(-com, find_order(fh, utoipos(c)));
+    GEN p = gel(P,i);
+    long va = Z_pval(a,p);
+    long vb = Z_pval(b,p);
+    if (va < vb)
+    {
+      B = mulii(B,powiu(p,vb));
+      gel(E,i) = utoi(vb);
+    }
+    else
+    {
+      A = mulii(A,powiu(p,va));
+      gel(E,i) = utoi(va);
     }
-    q = gerepileuptoint(av, q);
   }
-  return mulii(q,h);
+  *pA = A;
+  *pB = B; return mkmat2(P,E);
+}
+
+/* g1 has order d1, f has order o, replace g1 by an element of order lcm(d1,o)*/
+static void
+update_g1(GEN *pg1, GEN *pd1, GEN *pfad1, GEN f, GEN o, GEN fao)
+{
+  GEN A,B, g1 = *pg1, d1 = *pd1;
+  *pfad1 = split_lcm(d1,*pfad1, o,fao, &A,&B);
+  *pg1 = gmul(powgi(g1, diviiexact(d1,A)),  powgi(f, diviiexact(o,B)));
+  *pd1 = mulii(A,B); /* g1 has order d1 <- lcm(d1,o) */
 }
 
 /* Write x = Df^2, where D = fundamental discriminant,
@@ -4154,9 +4691,93 @@ two_rank(GEN x)
 
 static GEN
 sqr_primeform(GEN x, ulong p) { return redimag(qfisqr(primeform_u(x, p))); }
+/* return a set of forms hopefully generating Cl(K)^2; set L ~ L(chi_D,1) */
+static GEN
+get_forms(GEN D, GEN *pL)
+{
+  const long MAXFORM = 20;
+  GEN L, sqrtD = gsqrt(absi(D),DEFAULTPREC), forms = vectrunc_init(MAXFORM+1);
+  long s, nforms = 0;
+  ulong p;
+  forprime_t S;
+  L = mulrr(divrr(sqrtD,mppi(DEFAULTPREC)), dbltor(1.005));/*overshoot by 0.5%*/
+  s = itos_or_0( truncr(shiftr(sqrtr(sqrtD), 1)) );
+  if (!s) pari_err_OVERFLOW("classno [discriminant too large]");
+  if      (s < 10)   s = 200;
+  else if (s < 20)   s = 1000;
+  else if (s < 5000) s = 5000;
+  u_forprime_init(&S, 2, s);
+  while ( (p = u_forprime_next(&S)) )
+  {
+    long d, k = kroiu(D,p);
+    pari_sp av2;
+    if (!k) continue;
+    if (k > 0)
+    {
+      if (++nforms < MAXFORM) vectrunc_append(forms, sqr_primeform(D,p));
+      d = p-1;
+    }
+    else
+      d = p+1;
+    av2 = avma; affrr(divru(mulur(p,L),d), L); avma = av2;
+  }
+  *pL = L; return forms;
+}
 
-static ulong
-_low(GEN x) { return signe(x)? mod2BIL(x): 0; }
+/* h ~ #G, return o = order of f, set fao = its factorization */
+static  GEN
+Shanks_order(GEN f, GEN h, GEN *pfao)
+{
+  long s = minss(itos(sqrti(h)), 10000);
+  GEN T = gen_Shanks_init(f, s, NULL, &qfi_group);
+  GEN v = gen_Shanks(T, ginv(f), ULONG_MAX, NULL, &qfi_group);
+  return find_order(f, addiu(v,1), pfao);
+}
+
+/* if g = 1 in  G/<f> ? */
+static int
+equal1(GEN T, ulong N, GEN g)
+{ return !!gen_Shanks(T, g, N, NULL, &qfi_group); }
+
+/* Order of 'a' in G/<f>, T = gen_Shanks_init(f,n), order(f) < n*N
+ * FIXME: should be gen_order, but equal1 has the wrong prototype */
+static GEN
+relative_order(GEN a, GEN o, ulong N,  GEN T)
+{
+  pari_sp av = avma;
+  long i, l;
+  GEN m;
+
+  m = dlog_get_ordfa(o);
+  if (!m) pari_err_TYPE("gen_order [missing order]",a);
+  o = gel(m,1);
+  m = gel(m,2); l = lgcols(m);
+  for (i = l-1; i; i--)
+  {
+    GEN t, y, p = gcoeff(m,i,1);
+    long j, e = itos(gcoeff(m,i,2));
+    if (l == 2) {
+      t = gen_1;
+      y = a;
+    } else {
+      t = diviiexact(o, powiu(p,e));
+      y = powgi(a, t);
+    }
+    if (equal1(T,N,y)) o = t;
+    else {
+      for (j = 1; j < e; j++)
+      {
+        y = powgi(y, p);
+        if (equal1(T,N,y)) break;
+      }
+      if (j < e) {
+        if (j > 1) p = powiu(p, j);
+        o = mulii(t, p);
+      }
+    }
+  }
+  return gerepilecopy(av, o);
+}
 
 /* h(x) for x<0 using Baby Step/Giant Step.
  * Assumes G is not too far from being cyclic.
@@ -4165,12 +4786,9 @@ _low(GEN x) { return signe(x)? mod2BIL(x): 0; }
 GEN
 classno(GEN x)
 {
-  const long MAXFORM = 12;
-  pari_sp av = avma, av2, lim;
-  long r2, p, nforms, k, i, j, com, s;
-  GEN forms, count, index, tabla, tablb, hash, p1, p2;
-  GEN hin, h, f, fh, fg, ftest, Hf, D;
-  forprime_t S;
+  pari_sp av = avma;
+  long r2, k, s, i, l;
+  GEN forms, hin, Hf, D, g1, d1, d2, q, L, fad1, order_bound;
 
   if (signe(x) >= 0) return classno2(x);
 
@@ -4179,85 +4797,78 @@ classno(GEN x)
 
   Hf = conductor_part(x, k, &D, NULL);
   if (cmpiu(D,12) <= 0) return gerepilecopy(av, Hf);
-
-  p2 = gsqrt(absi(D),DEFAULTPREC);
-  p1 = mulrr(divrr(p2,mppi(DEFAULTPREC)), dbltor(1.005)); /*overshoot by 0.5%*/
-  s = itos_or_0( truncr(shiftr(sqrtr(p2), 1)) );
-  if (!s) pari_err_OVERFLOW("classno [discriminant too large]");
-  if      (s < 10)   s = 200;
-  else if (s < 20)   s = 1000;
-  else if (s < 5000) s = 5000;
-  forms = vectrunc_init(MAXFORM+1);
-
-  u_forprime_init(&S, 2, s);
-  nforms = 0;
-  while ( (p = u_forprime_next(&S)) )
+  forms =  get_forms(D, &L);
+  r2 = two_rank(D);
+  hin = roundr(shiftr(L, -r2)); /* rough approximation for #G, G = Cl(K)^2 */
+
+  l = lg(forms);
+  order_bound = const_vec(l-1, NULL);
+  g1 = gel(forms,1);
+  gel(order_bound,1) = d1 = Shanks_order(g1, hin, &fad1);
+  q = diviiround(hin, d1); /* approximate order of G/<g1> */
+  d2 = NULL; /* not computed yet */
+  if (is_pm1(q)) goto END;
+  for (i=2; i < l; i++)
   {
-    long d, k = kroiu(D,p);
-    pari_sp av3;
-    if (!k) continue;
-    if (k > 0)
+    GEN o, fao, a, F, fd, f = gel(forms,i);
+    fd = powgi(f, d1); if (is_pm1(gel(fd,1))) continue;
+    F = powgi(fd, q);
+    a = gel(F,1);
+    o = is_pm1(a)? find_order(fd, q, &fao): Shanks_order(fd, q, &fao);
+    /* f^(d1 q) = 1 */
+    fao = merge_factor(fad1,fao, (void*)&cmpii, &cmp_nodata);
+    o = find_order(f, fao, &fao);
+    gel(order_bound,i) = o;
+    /* o = order of f, fao = factor(o) */
+    update_g1(&g1,&d1,&fad1, f,o,fao);
+    q = diviiround(hin, d1);
+    if (is_pm1(q)) goto END;
+  }
+  /* very probably d1 = expo(Cl^2(K)), q ~ #Cl^2(K) / d1 */
+  if (expi(q) > 3)
+  { /* q large: compute d2, 2nd elt divisor */
+    ulong N, n = 2*itou(sqrti(d1));
+    GEN D = d1, T = gen_Shanks_init(g1, n, NULL, &qfi_group);
+    d2 = gen_1;
+    N = itou( gceil(gdivgs(d1,n)) ); /* order(g1) <= n*N */
+    for (i = 1; i < l; i++)
     {
-      if (++nforms < MAXFORM) vectrunc_append(forms, sqr_primeform(D,p));
-      d = p - 1;
+      GEN d, f = gel(forms,i), B = gel(order_bound,i);
+      if (!B) B = find_order(f, fad1, /*junk*/&d);
+      f = powgi(f,d2);
+      if (equal1(T,N,f)) continue;
+      B = gdiv(B,d2); if (typ(B) == t_FRAC) B = gel(B,1);
+      /* f^B = 1 */
+      d = relative_order(f, B, N,T);
+      d2= mulii(d,d2);
+      D = mulii(d1,d2);
+      q = diviiround(hin,D);
+      if (is_pm1(q)) { d1 = D; goto END; }
     }
-    else
-      d = p + 1;
-    av3 = avma; affrr(divru(mulur(p,p1),d), p1);
-    avma = av3;
+    /* very probably, d2 is the 2nd elementary divisor */
+    d1 = D; /* product of first two elt divisors */
   }
-  r2 = two_rank(D);
-  h = hin = roundr(shiftr(p1, -r2));
-  s = 2*itos(gceil(sqrtnr(p1, 4)));
-  if (s > 10000) s = 10000;
-
-  count = new_chunk(256); for (i=0; i<=255; i++) count[i]=0;
-  index = new_chunk(257);
-  tabla = new_chunk(10000);
-  tablb = new_chunk(10000);
-  hash  = new_chunk(10000);
-  f = gel(forms,1);
-  p1 = fh = powgi(f, h);
-  for (i=0; i<s; i++, p1 = qficomp(p1,f))
-  {
-    tabla[i] = _low(gel(p1,1));
-    tablb[i] = _low(gel(p1,2)); count[tabla[i]&255]++;
-  }
-  /* follow the idea of counting sort to avoid maintaining linked lists in
-   * hashtable */
-  index[0]=0; for (i=0; i< 255; i++) index[i+1] = index[i]+count[i];
-  /* index[i] = # of forms hashing to <= i */
-  for (i=0; i<s; i++) hash[ index[tabla[i]&255]++ ] = i;
-  index[0]=0; for (i=0; i<=255; i++) index[i+1] = index[i]+count[i];
-  /* hash[index[i-1]..index[i]-1] = forms hashing to i */
-
-  fg = gpowgs(f,s); av2 = avma; lim = stack_lim(av2,2);
-  ftest = gpowgs(p1,0);
-  for (com=0; ; com++)
-  {
-    long j1, k, l;
-    GEN a, b;
-    a = gel(ftest,1); k = _low(a);
-    b = gel(ftest,2); l = _low(b); j = k&255;
-    for (j1=index[j]; j1 < index[j+1]; j1++)
-    {
-      long j2 = hash[j1];
-      if (tabla[j2] == k && tablb[j2] == l)
-      {
-        p1 = gmul(gpowgs(f,j2),fh);
-        if (equalii(gel(p1,1), a) && absi_equal(gel(p1,2), b))
-        { /* p1 = ftest or ftest^(-1), we are done */
-          if (signe(gel(p1,2)) == signe(b)) com = -com;
-          h = addii(addis(h,j2), mulss(s,com));
-          h = end_classno(h, hin, forms);
-          return gerepileuptoint(av, shifti(mulii(h,Hf), r2));
-        }
-      }
+  /* impose q | d2^oo (d1^oo if d2 not computed), and compatible with known
+   * 2-rank */
+  if (!ok_q(q,d1,d2,r2))
+  {
+    GEN q0 = q;
+    long d;
+    if (cmpii(mulii(q,d1), hin) < 0)
+    { /* try q = q0+1,-1,+2,-2 */
+      d = 1;
+      do { q = addis(q0,d); d = d>0? -d: 1-d; } while(!ok_q(q,d1,d2,r2));
+    }
+    else
+    { /* q0-1,+1,-2,+2  */
+      d = -1;
+      do { q = addis(q0,d); d = d<0? -d: -1-d; } while(!ok_q(q,d1,d2,r2));
     }
-    ftest = gmul(ftest,fg);
-    if (equali1(gel(ftest,1))) pari_err_IMPL("classno with too small order");
-    if (low_stack(lim, stack_lim(av2,2))) ftest = gerepileupto(av2,ftest);
   }
+  d1 = mulii(d1,q);
+
+END:
+  return gerepileuptoint(av, shifti(mulii(d1,Hf), r2));
 }
 
 /* use Euler products */
diff --git a/src/basemath/arith2.c b/src/basemath/arith2.c
index 5a671c7..d1cc512 100644
--- a/src/basemath/arith2.c
+++ b/src/basemath/arith2.c
@@ -362,7 +362,7 @@ sieve_chunk(byteptr known_primes, ulong s, byteptr data, ulong n)
 static void
 initprimes0(ulong maxnum, long *lenp, ulong *lastp, byteptr p1)
 {
-  pari_sp av = avma;
+  pari_sp av = avma, bot = pari_mainstack->bot;
   long alloced, psize;
   byteptr q, end, p, end1, plast, curdiff;
   ulong last, remains, curlow, rootnum, asize;
@@ -528,7 +528,7 @@ Z_smoothen(GEN N, GEN L, GEN *pP, GEN *pe)
   GEN e = new_chunk(l), P = new_chunk(l);
   for (i = j = 1; i < l; i++)
   {
-    ulong p = (ulong)L[i];
+    ulong p = uel(L,i);
     long v = Z_lvalrem(N, p, &N);
     if (v) { P[j] = p; e[j] = v; j++; if (is_pm1(N)) { N = NULL; break; } }
   }
@@ -724,6 +724,22 @@ clean_Z_factor(GEN f)
     return mkmat2(vecslice(P,2,n), vecslice(gel(f,2),2,n));
   return f;
 }
+GEN
+fuse_Z_factor(GEN f, GEN B)
+{
+  GEN P = gel(f,1), E = gel(f,2), P2,E2;
+  long i, l = lg(P);
+  if (l == 1) return f;
+  for (i = 1; i < l; i++)
+    if (absi_cmp(gel(P,i), B) > 0) break;
+  if (i == l) return f;
+  /* tail / initial segment */
+  P2 = vecslice(P, i, l-1); P = vecslice(P, 1, i-1);
+  E2 = vecslice(E, i, l-1); E = vecslice(E, 1, i-1);
+  P = shallowconcat(P, mkvec(factorback2(P2,E2)));
+  E = shallowconcat(E, mkvec(gen_1));
+  return mkmat2(P, E);
+}
 
 /* n associated to a factorization of a positive integer: either N (t_INT)
  * a factorization matrix faN, or a t_VEC: [N, faN] */
@@ -826,7 +842,7 @@ divisors_init(GEN n, GEN *pP, GEN *pE)
       set_fact(absi_factor(n), &P,&E);
       isint = 1; break;
     case t_VEC:
-      if (lg(n) != 3) pari_err_TYPE("divisors",n);
+      if (lg(n) != 3 || typ(gel(n,2)) !=t_MAT) pari_err_TYPE("divisors",n);
       set_fact_check(gel(n,2), &P,&E, &isint);
       break;
     case t_MAT:
@@ -959,6 +975,18 @@ _mod4(GEN c) {
   return r;
 }
 
+long
+corediscs(long D, ulong *f)
+{
+  /* D = f^2 dK */
+  long dK = D>=0 ? (long) coreu(D) : -(long) coreu(-(ulong) D);
+  ulong dKmod4 = ((ulong)dK)&3UL;
+  if (dKmod4 == 2 || dKmod4 == 3)
+    dK *= 4;
+  if (f) *f = usqrt((ulong)(D/dK));
+  return D;
+}
+
 GEN
 coredisc(GEN n)
 {
@@ -1076,7 +1104,7 @@ eulerphi(GEN n)
       avma = av; return utoipos(e);
     }
   }
-  else if (lgefint(n) == 3) return utoipos(eulerphiu((ulong)n[2]));
+  else if (lgefint(n) == 3) return utoipos(eulerphiu(uel(n,2)));
   else
     F = absi_factor(n);
   if (!signe(n)) return gen_2;
@@ -1288,6 +1316,185 @@ issquarefree(GEN x)
 /**                                                                 **/
 /*********************************************************************/
 
+/* set v[i] = 1 iff B^i is needed in the digits_dac algorithm */
+static void
+set_vexp(GEN v, long l)
+{
+  long m;
+  if (v[l]) return;
+  v[l] = 1; m = l>>1;
+  set_vexp(v, m);
+  set_vexp(v, l-m);
+}
+
+/* return all needed B^i for DAC algorithm, for lz digits */
+static GEN
+get_vB(GEN T, long lz, void *E, struct bb_ring *r)
+{
+  GEN vB, vexp = const_vecsmall(lz, 0);
+  long i, l = (lz+1) >> 1;
+  vexp[1] = 1;
+  vexp[2] = 1;
+  set_vexp(vexp, lz);
+  vB = zerovec(lz); /* unneeded entries remain = 0 */
+  gel(vB, 1) = T;
+  for (i = 2; i <= l; i++)
+    if (vexp[i])
+    {
+      long j = i >> 1;
+      GEN B2j = r->sqr(E, gel(vB,j));
+      gel(vB,i) = odd(i)? r->mul(E, B2j, T): B2j;
+    }
+  return vB;
+}
+
+static void
+gen_digits_dac(GEN x, GEN vB, long l, GEN *z,
+               void *E, GEN div(void *E, GEN a, GEN b, GEN *r))
+{
+  GEN q, r;
+  long m = l>>1;
+  if (l==1) { *z=x; return; }
+  q = div(E, x, gel(vB,m), &r);
+  gen_digits_dac(r, vB, m, z, E, div);
+  gen_digits_dac(q, vB, l-m, z+m, E, div);
+}
+
+static GEN
+gen_fromdigits_dac(GEN x, GEN vB, long i, long l, void *E,
+                   GEN add(void *E, GEN a, GEN b),
+                   GEN mul(void *E, GEN a, GEN b))
+{
+  GEN a, b;
+  long m = l>>1;
+  if (l==1) return gel(x,i);
+  a = gen_fromdigits_dac(x, vB, i, m, E, add, mul);
+  b = gen_fromdigits_dac(x, vB, i+m, l-m, E, add, mul);
+  return add(E, a, mul(E, b, gel(vB, m)));
+}
+
+static GEN
+gen_digits_i(GEN x, GEN B, long n, void *E, struct bb_ring *r,
+                          GEN (*div)(void *E, GEN x, GEN y, GEN *r))
+{
+  GEN z, vB;
+  if (n==1) retmkvec(gcopy(x));
+  vB = get_vB(B, n, E, r);
+  z = cgetg(n+1, t_VEC);
+  gen_digits_dac(x, vB, n, (GEN*)(z+1), E, div);
+  return z;
+}
+
+GEN
+gen_digits(GEN x, GEN B, long n, void *E, struct bb_ring *r,
+                          GEN (*div)(void *E, GEN x, GEN y, GEN *r))
+{
+  pari_sp av = avma;
+  return gerepilecopy(av, gen_digits_i(x, B, n, E, r, div));
+}
+
+GEN
+gen_fromdigits(GEN x, GEN B, void *E, struct bb_ring *r)
+{
+  pari_sp av = avma;
+  long n = lg(x)-1;
+  GEN vB = get_vB(B, n, E, r);
+  GEN z = gen_fromdigits_dac(x, vB, 1, n, E, r->add, r->mul);
+  return gerepilecopy(av, z);
+}
+
+static GEN
+_addii(void *data /* ignored */, GEN x, GEN y)
+{ (void)data; return addii(x,y); }
+static GEN
+_sqri(void *data /* ignored */, GEN x) { (void)data; return sqri(x); }
+static GEN
+_mulii(void *data /* ignored */, GEN x, GEN y)
+ { (void)data; return mulii(x,y); }
+static GEN
+_dvmdii(void *data /* ignored */, GEN x, GEN y, GEN *r)
+ { (void)data; return dvmdii(x,y,r); }
+
+static struct bb_ring Z_ring = { _addii, _mulii, _sqri };
+
+static GEN
+check_basis(GEN B)
+{
+  if (!B) return utoipos(10);
+  if (typ(B)!=t_INT) pari_err_TYPE("digits",B);
+  if (cmpis(B,2)<0) pari_err_DOMAIN("digits","B","<",gen_2,B);
+  return B;
+}
+
+/* x has l digits in base B, write them to z[0..l-1], vB[i] = B^i */
+static void
+digits_dacsmall(GEN x, GEN vB, long l, ulong* z)
+{
+  pari_sp av = avma;
+  GEN q,r;
+  long m;
+  if (l==1) { *z=itou(x); return; }
+  m=l>>1;
+  q = dvmdii(x, gel(vB,m), &r);
+  digits_dacsmall(q,vB,l-m,z);
+  digits_dacsmall(r,vB,m,z+l-m);
+  avma = av;
+}
+
+GEN
+digits(GEN x, GEN B)
+{
+  pari_sp av=avma;
+  long lz;
+  GEN z, vB;
+  if (typ(x)!=t_INT) pari_err_TYPE("digits",x);
+  B = check_basis(B);
+  if (!signe(x))       {avma = av; return cgetg(1,t_VEC); }
+  if (absi_cmp(x,B)<0) {avma = av; retmkvec(absi(x)); }
+  if (Z_ispow2(B))
+  {
+    long k = expi(B);
+    if (k == 1) return binaire(x);
+    if (k < BITS_IN_LONG)
+    {
+      (void)new_chunk(4*(expi(x) + 2)); /* HACK */
+      z = binary_2k_zv(x, k);
+      avma = av; return Flv_to_ZV(z);
+    }
+    else
+    {
+      avma = av; return binary_2k(x, k);
+    }
+  }
+  if (signe(x) < 0) x = absi(x);
+  lz = logint(x,B,NULL);
+  if (lgefint(B)>3)
+  {
+    z = gerepileupto(av, gen_digits_i(x, B, lz, NULL, &Z_ring, _dvmdii));
+    vecreverse_inplace(z);
+    return z;
+  }
+  else
+  {
+    vB = get_vB(B, lz, NULL, &Z_ring);
+    (void)new_chunk(3*lz); /* HACK */
+    z = zero_zv(lz);
+    digits_dacsmall(x,vB,lz,(ulong*)(z+1));
+    avma = av; return vecsmall_to_vec(z);
+  }
+}
+
+GEN
+fromdigits(GEN x, GEN B)
+{
+  pari_sp av = avma;
+  if (typ(x)!=t_VEC || !RgV_is_ZV(x)) pari_err_TYPE("fromdigits",x);
+  B = check_basis(B);
+  if (lg(x)==1) { avma = av; return gen_0; }
+  x = vecreverse(x);
+  return gerepileupto(av, gen_fromdigits(x, B, NULL, &Z_ring));
+}
+
 static ulong DS[] ={
   0,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,10,2,3,4,5,6,7,8,9,10,11,3,4,5,6,7,8,
   9,10,11,12,4,5,6,7,8,9,10,11,12,13,5,6,7,8,9,10,11,12,13,14,6,7,8,9,10,11,
@@ -1381,60 +1588,33 @@ sumdigits(GEN n)
   }
 }
 
-static void
-digits_dac(GEN x, GEN B, long l, GEN* z)
-{
-  GEN q,r;
-  long m;
-  if (l==1) { *z=x; return; }
-  m=l>>1;
-  q=dvmdii(x,powiu(B,m),&r);
-  digits_dac(q,B,l-m,z);
-  digits_dac(r,B,m,z+l-m);
-}
-
-static void
-digits_dacsmall(GEN x, ulong B, long l, ulong* z)
-{
-  pari_sp av = avma;
-  GEN q,r;
-  long m;
-  if (l==1) { *z=itou(x); return; }
-  m=l>>1;
-  q=dvmdii(x,powuu(B,m),&r);
-  digits_dacsmall(q,B,l-m,z);
-  digits_dacsmall(r,B,m,z+l-m);
-  avma = av;
-}
-
 GEN
-digits(GEN x, GEN B)
+sumdigits0(GEN x, GEN B)
 {
-  pari_sp av=avma;
-  long lz;
+  pari_sp av = avma;
   GEN z;
-  if (typ(x)!=t_INT) pari_err_TYPE("digits",x);
-  if (!B)
-    B = utoi(10);
-  else {
-    if (typ(B)!=t_INT) pari_err_TYPE("digits",B);
-    if (cmpis(B,2)<0) pari_err_DOMAIN("digits","B","<",gen_2,B);
-  }
-  if (equalis(B,2))    {avma = av; return binaire(x); }
-  if (!signe(x))       {avma = av; return cgetg(1,t_VEC); }
-  if (absi_cmp(x,B)<0) {avma = av; retmkvec(absi(x)); }
-  x = absi(x); lz = logint(x,B,NULL);
-  if (lgefint(B)>3)
-  {
-    z = zerovec(lz);
-    digits_dac(x,B,lz,(GEN*)(z+1));
-    return gerepilecopy(av,z);
-  }
-  else
+  long lz;
+
+  if (!B) return sumdigits(x);
+  if (typ(x) != t_INT) pari_err_TYPE("sumdigits", x);
+  B = check_basis(B);
+  if (Z_ispow2(B))
   {
-    ulong b = B[2];
-    z = zero_zv(lz);
-    digits_dacsmall(x,b,lz,(ulong*)(z+1));
-    return gerepileupto(av,vecsmall_to_vec(z));
+    long k = expi(B);
+    if (k == 1) { avma = av; return utoi(hammingweight(x)); }
+    if (k < BITS_IN_LONG)
+    {
+      GEN z = binary_2k_zv(x, k);
+      if (lg(z)-1 > 1<<(BITS_IN_LONG-k)) /* may overflow */
+        return gerepileuptoint(av, ZV_sum(Flv_to_ZV(z)));
+      avma = av; return utoi(zv_sum(z));
+    }
+    return gerepileuptoint(av, ZV_sum(binary_2k(x, k)));
   }
+  if (!signe(x))       { avma = av; return gen_0; }
+  if (absi_cmp(x,B)<0) { avma = av; return absi(x); }
+  if (equaliu(B,10))   { avma = av; return sumdigits(x); }
+  lz = logint(x,B,NULL);
+  z = gen_digits_i(x, B, lz, NULL, &Z_ring, _dvmdii);
+  return gerepileuptoint(av, ZV_sum(z));
 }
diff --git a/src/basemath/base1.c b/src/basemath/base1.c
index 9507d4d..639d68b 100644
--- a/src/basemath/base1.c
+++ b/src/basemath/base1.c
@@ -21,11 +21,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 
 int new_galois_format = 0;
 
+int
+checkrnf_i(GEN rnf)
+{ return (typ(rnf)==t_VEC && lg(rnf)==13); }
+
 void
 checkrnf(GEN rnf)
-{
-  if (typ(rnf)!=t_VEC || lg(rnf)!=13) pari_err_TYPE("checkrnf",rnf);
-}
+{ if (!checkrnf_i(rnf)) pari_err_TYPE("checkrnf",rnf); }
 
 GEN
 checkbnf_i(GEN X)
@@ -227,6 +229,7 @@ nftyp(GEN x)
     case t_VEC:
       switch(lg(x))
       {
+        case 13: return typ_RNF;
         case 10:
           if (typ(gel(x,1))!=t_POL) break;
           return typ_NF;
@@ -502,11 +505,11 @@ polgalois(GEN x, long prec)
   if (n > 7) return galoisbig(x, prec);
   for(;;)
   {
-    double cb = cauchy_bound(x);
+    double fb = fujiwara_bound(x);
     switch(n)
     {
       case 4: z = cgetg(7,t_VEC);
-        prec = nbits2prec((long)(cb*(18./ LOG2)) + 64);
+        prec = nbits2prec((long)(fb*18.) + 64);
         for(;;)
         {
           p1=QX_complex_roots(x,prec);
@@ -538,7 +541,7 @@ polgalois(GEN x, long prec)
       case 5: z = cgetg(7,t_VEC);
         ee= cgetg(7,t_VECSMALL);
         w = cgetg(7,t_VECSMALL);
-        prec = nbits2prec((long)(cb*(21. / LOG2)) + 64);
+        prec = nbits2prec((long)(fb*21.) + 64);
         for(;;)
         {
           for(;;)
@@ -595,7 +598,7 @@ polgalois(GEN x, long prec)
         }
 
       case 6: z = cgetg(7, t_VEC);
-        prec = nbits2prec((long) (cb * (42. / LOG2)) + 64);
+        prec = nbits2prec((long) (fb * 42) + 64);
         for(;;)
         {
           for(;;)
@@ -684,7 +687,7 @@ polgalois(GEN x, long prec)
         }
 
       case 7: z = cgetg(36,t_VEC);
-        prec = nbits2prec((long)(cb*(7. / LOG2)) + 64);
+        prec = nbits2prec((long)(fb*7.) + 64);
         for(;;)
         {
           ind = 0; p1=QX_complex_roots(x,prec);
@@ -1149,8 +1152,8 @@ tests_OK(GEN a, GEN nfa, GEN b, GEN nfb, long fliso)
   for (i=1; i<nP; i++)
     if (mod2(gel(E,i)) && !dvdii(db, powiu(gel(P,i),q))) return 0;
   U = gel(P,nP);
-  if (expi(U) < 150) /* "unfactored" cofactor is small, finish */
-  {
+  if (mod2(gel(E,i)) && expi(U) < 150)
+  { /* "unfactored" cofactor is small, finish */
     if (cmpiu(U, maxprime()) > 0)
     {
       fa = Z_factor(U);
@@ -1160,7 +1163,7 @@ tests_OK(GEN a, GEN nfa, GEN b, GEN nfb, long fliso)
     else
     {
       P = mkvec(U);
-      E = mkvec(gel(E,nP));
+      E = mkvec(gen_1);
     }
     nP = lg(P) - 1;
     for (i=1; i<=nP; i++)
@@ -1176,6 +1179,7 @@ nfiso0(GEN a, GEN b, long fliso)
   pari_sp av = avma;
   long i, vb, lx;
   GEN nfa, nfb, y, la, lb;
+  int newvar;
 
   a = get_nfpol(a, &nfa);
   b = get_nfpol(b, &nfb);
@@ -1186,16 +1190,12 @@ nfiso0(GEN a, GEN b, long fliso)
 
   if (nfb) lb = gen_1; else b = ZX_Q_normalize(b,&lb);
   if (nfa) la = gen_1; else a = ZX_Q_normalize(a,&la);
-  a = leafcopy(a); setvarn(a,0);
-  b = leafcopy(b); vb = varn(b);
+  vb = varn(b); newvar = (varncmp(vb,varn(a)) <= 0);
+  if (newvar) { a = leafcopy(a); setvarn(a, fetch_var_higher()); }
   if (nfb)
-  {
-    if (vb == 0) nfb = gsubst(nfb, 0, pol_x(MAXVARN));
     y = lift_intern(nfroots(nfb,a));
-  }
   else
   {
-    if (vb == 0) setvarn(b, fetch_var());
     y = gel(polfnf(a,b),1); lx = lg(y);
     for (i=1; i<lx; i++)
     {
@@ -1203,10 +1203,10 @@ nfiso0(GEN a, GEN b, long fliso)
       if (degpol(t) != 1) { setlg(y,i); break; }
       gel(y,i) = gneg_i(lift_intern(gel(t,2)));
     }
-    if (vb == 0) (void)delete_var();
     settyp(y, t_VEC);
     gen_sort_inplace(y, (void*)&cmp_RgX, &cmp_nodata, NULL);
   }
+  if (newvar) (void)delete_var();
   lx = lg(y); if (lx==1) { avma=av; return gen_0; }
   for (i=1; i<lx; i++)
   {
@@ -1234,11 +1234,21 @@ nfisincl(GEN a, GEN b) { return nfiso0(a,b,0); }
 GEN
 get_roots(GEN x, long r1, long prec)
 {
-  GEN roo = (typ(x)!=t_POL)? leafcopy(x): QX_complex_roots(x,prec);
-  long i, ru = (lg(roo)-1 + r1) >> 1;
-
-  for (i=r1+1; i<=ru; i++) gel(roo,i) = gel(roo, (i<<1)-r1);
-  roo[0]=evaltyp(t_VEC)|evallg(ru+1); return roo;
+  long i, ru;
+  GEN z;
+  if (typ(x) != t_POL)
+  {
+    z = leafcopy(x);
+    ru = (lg(z)-1 + r1) >> 1;
+  }
+  else
+  {
+    long n = degpol(x);
+    z = (r1 == n)? realroots(x, NULL, prec): QX_complex_roots(x,prec);
+    ru = (n+r1)>>1;
+  }
+  for (i=r1+1; i<=ru; i++) gel(z,i) = gel(z, (i<<1)-r1);
+  z[0]=evaltyp(t_VEC)|evallg(ru+1); return z;
 }
 
 GEN
@@ -1398,12 +1408,16 @@ get_roots_for_M(nffp_t *F)
     double er;
     n = degpol(F->x);
     eBD = 1 + gexpo(gel(F->basden,1));
-    er  = F->ro? (1+gexpo(F->ro)): cauchy_bound(F->x)/LOG2;
+    er  = F->ro? (1+gexpo(F->ro)): fujiwara_bound(F->x);
     if (er < 0) er = 0;
-    F->extraprec = nbits2extraprec((long)(n*er + eBD + log2(n))-(BITS_IN_LONG-1));/*FIXME*/
+    F->extraprec = nbits2extraprec(n*er + eBD + log2(n));
   }
 
   PREC = F->prec + F->extraprec;
+  /* make sure that default accuracy is the same on 32/64bit */
+#ifndef LONG_IS_64BIT
+  if (odd(PREC)) PREC += EXTRAPRECWORD;
+#endif
   if (F->ro && gprecision(gel(F->ro,1)) >= PREC) return;
   F->ro = get_roots(F->x, F->r1, PREC);
 }
@@ -1423,15 +1437,12 @@ make_M(nffp_t *F, int trunc)
     for (i=1; i<l; i++) gel(m,i) = poleval(gel(bas,j), gel(ro,i));
   }
   if (den)
-  {
-    GEN invd, rd = cgetr(F->prec + F->extraprec);
     for (j=2; j<n; j++)
     {
       d = gel(den,j); if (!d) continue;
-      m = gel(M,j); affir(d,rd); invd = invr(rd);
-      for (i=1; i<l; i++) gel(m,i) = gmul(gel(m,i), invd);
+      m = gel(M,j);
+      for (i=1; i<l; i++) gel(m,i) = gdiv(gel(m,i), d);
     }
-  }
 
   if (trunc && gprecision(M) > F->prec)
   {
@@ -1583,7 +1594,7 @@ GEN
 nfcertify(GEN nf)
 {
   nf = checknf(nf);
-  return primes_certify(nf_get_disc(nf),gmael(nf, 5, 8));
+  return primes_certify(nf_get_disc(nf), nf_get_ramified_primes(nf));
 }
 
 #if 0 /* used to check benches between HNF nf.zk and LLL-reduced nf.zk */
@@ -1666,7 +1677,7 @@ get_red_G(nfbasic_t *T, GEN *pro)
     if (DEBUGLEVEL)
       err_printf("get_red_G: starting LLL, prec = %ld (%ld + %ld)\n",
                   prec + F.extraprec, prec, F.extraprec);
-    if ((u = lllfp(G, 0.99, LLL_KEEP_FIRST)))
+    if ((u = lllfp(G, 0.99, LLL_KEEP_FIRST|LLL_COMPATIBLE)))
     {
       if (lg(u)-1 == n) break;
       /* singular ==> loss of accuracy */
@@ -1691,7 +1702,8 @@ set_LLL_basis(nfbasic_t *T, GEN *pro, double DELTA)
     pari_sp av = avma;
     GEN u, basden = T->basden;
     if (!basden) basden = get_bas_den(B);
-    u = ZM_lll(make_Tr(T->x,basden), DELTA, LLL_GRAM|LLL_KEEP_FIRST|LLL_IM);
+    u = ZM_lll(make_Tr(T->x,basden), DELTA,
+               LLL_GRAM|LLL_KEEP_FIRST|LLL_IM|LLL_COMPATIBLE);
     B = gerepileupto(av, RgV_RgM_mul(B, u));
     *pro = NULL;
   }
@@ -1802,7 +1814,7 @@ nf_input_type(GEN x)
       switch(typ(V))
       {
         case t_INT: case t_MAT: return t_POL;
-        case t_VEC:
+        case t_VEC: case t_COL:
           if (RgV_is_ZV(V)) return t_POL;
           break;
         default: return -1;
@@ -1854,7 +1866,7 @@ nfbasic_init(GEN x, long flag, nfbasic_t *T)
       bas = S.basis;
       dx = S.dT;
       unscale = S.unscale;
-      r1 = sturm(x);
+      r1 = ZX_sturm(x);
       break;
     }
     case t_VEC:
@@ -1875,7 +1887,7 @@ nfbasic_init(GEN x, long flag, nfbasic_t *T)
       index = NULL;
       dx = NULL;
       dK = NULL;
-      r1 = sturm(x);
+      r1 = ZX_sturm(x);
       break;
     default: /* -1 */
       pari_err_TYPE("nfbasic_init", x);
@@ -1903,6 +1915,7 @@ nfinitall(GEN x, long flag, long prec)
   GEN nf, unscale;
   nfbasic_t T;
 
+  if (checkrnf_i(x)) return check_and_build_nfabs(x, prec);
   nfbasic_init(x, flag, &T);
   if (!ZX_is_irred(T.x)) pari_err_IRREDPOL("nfinit",x);
   if (!equali1(leading_term(T.x0)) && !(flag & nf_RED))
@@ -2220,7 +2233,7 @@ polred_init(nfbasic_t *T, nffp_t *F, CG_data *d)
   GEN ro;
   set_LLL_basis(T, &ro, 0.9999);
   /* || polchar ||_oo < 2^e ~ 2 (n * rho)^n, rho = max modulus of root */
-  log2rho = ro ? (double)gexpo(ro): cauchy_bound(T->x) / LOG2;
+  log2rho = ro ? (double)gexpo(ro): fujiwara_bound(T->x);
   e = n * (long)(log2rho + log2((double)n)) + 1;
   if (e < 0) e = 0; /* can occur if n = 1 */
   prec = chk_gen_prec(n, e);
diff --git a/src/basemath/base2.c b/src/basemath/base2.c
index 1875df1..a323df6 100644
--- a/src/basemath/base2.c
+++ b/src/basemath/base2.c
@@ -375,7 +375,7 @@ static void
 rowred(GEN a, GEN rmod, GEN rmodo2)
 {
   long j,k, c = lg(a), r = lgcols(a);
-  pari_sp av=avma, lim=stack_lim(av,1);
+  pari_sp av=avma;
 
   for (j=1; j<r; j++)
   {
@@ -393,7 +393,7 @@ rowred(GEN a, GEN rmod, GEN rmodo2)
       GEN q=diviiround(gcoeff(a,j,k),gcoeff(a,j,j));
       gel(a,k) = mtran(gel(a,k),gel(a,j),q,rmod,rmodo2, k);
     }
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       long j1,k1;
       GEN p1;
@@ -438,7 +438,7 @@ static GEN
 maxord2(GEN cf, GEN p, long epsilon)
 {
   long sp,i,n=lg(cf)-1;
-  pari_sp av=avma, av2,limit;
+  pari_sp av=avma, av2;
   GEN T,T2,Tn,m,v,delta,hard_case_exponent, *w;
   const GEN pp = sqri(p);
   const GEN ppo2 = shifti(pp,-1);
@@ -462,7 +462,7 @@ maxord2(GEN cf, GEN p, long epsilon)
   v = new_chunk(n+1);
   w = (GEN*)new_chunk(n+1);
 
-  av2 = avma; limit = stack_lim(av2,1);
+  av2 = avma;
   delta=gen_1; m=matid(n);
 
   for(;;)
@@ -599,7 +599,7 @@ maxord2(GEN cf, GEN p, long epsilon)
     if (hh) delta = diviiexact(delta,hh);
     epsilon -= 2 * Z_pval(index,p);
     if (epsilon < 2) break;
-    if (low_stack(limit,stack_lim(av2,1)))
+    if (gc_needed(av2,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"maxord2");
       gerepileall(av2, 2, &m, &delta);
@@ -721,81 +721,29 @@ nfmaxord(nfmaxord_t *S, GEN T0, long flag)
   GEN O = get_maxord(S, T0, flag);
   allbase_from_maxord(S, O);
 }
-
-static void
-_nfbasis(GEN x, long flag, GEN fa, GEN *pbas, GEN *pdK)
+GEN
+nfbasis(GEN x, GEN *pdK, GEN fa)
 {
+  pari_sp av = avma;
   nfmaxord_t S;
-  nfmaxord(&S, fa? mkvec2(x,fa): x, flag);
-  if (pbas) *pbas = RgXV_unscale(S.basis, S.unscale);
+  GEN B;
+  nfmaxord(&S, fa? mkvec2(x,fa): x, 0);
+  B = RgXV_unscale(S.basis, S.unscale);
   if (pdK)  *pdK = S.dK;
+  gerepileall(av, pdK? 2: 1, &B, pdK); return B;
 }
-static GEN
-_nfdisc(GEN x, long flag, GEN fa)
+GEN
+nfdisc(GEN x)
 {
   pari_sp av = avma;
   nfmaxord_t S;
-  GEN O = get_maxord(&S, fa? mkvec2(x,fa): x, flag);
+  GEN O = get_maxord(&S, x, 0);
   GEN D = disc_from_maxord(&S, O);
   D = icopy_avma(D, av); avma = (pari_sp)D; return D;
 }
 
-/* deprecated: backward compatibility only ! */
-GEN
-nfbasis_gp(GEN T, GEN P, GEN junk)
-{
-  if (!P || isintzero(P)) return nfbasis(T, NULL, junk);
-  if (junk) pari_err_FLAG("nfbasis");
-  /* treat specially nfbasis(T, 1): the deprecated way to initialize an nf when
-   * disc(T) is hard to factor */
-  if (typ(P) == t_INT && equali1(P)) P = utoipos(maxprime());
-  return nfbasis(T, NULL, P);
-}
-/* deprecated */
 GEN
-nfdisc_gp(GEN T, GEN P, GEN junk)
-{
-  if (!P || isintzero(P)) return _nfdisc(T, 0, junk);
-  if (junk) pari_err_FLAG("nfdisc");
-  /* treat specially nfdisc(T, 1) */
-  if (typ(P) == t_INT && equali1(P)) P = utoipos(maxprime());
-  return _nfdisc(T, 0, P);
-}
-/* backward compatibility */
-static long
-nfbasis_flag_translate(long flag)
-{
-  switch(flag) {
-    case 0: return 0;
-    case 1: return nf_PARTIALFACT;
-    case 2: return nf_ROUND2;
-    case 3: return nf_ROUND2|nf_PARTIALFACT;
-    default: pari_err_FLAG("nfbasis");
-             return 0;
-  }
-}
-/* deprecated */
-GEN
-nfbasis0(GEN x, long flag, GEN fa)
-{
-  pari_sp av = avma;
-  GEN bas; _nfbasis(x, nfbasis_flag_translate(flag), fa, &bas, NULL);
-  return gerepilecopy(av, bas);
-}
-/* deprecated */
-GEN
-nfdisc0(GEN x, long flag, GEN fa)
-{ return _nfdisc(x, nfbasis_flag_translate(flag), fa); }
-
-GEN
-nfbasis(GEN x, GEN *pdK, GEN fa)
-{
-  pari_sp av = avma;
-  GEN bas; _nfbasis(x, 0, fa, &bas, pdK);
-  gerepileall(av, pdK? 2: 1, &bas, pdK); return bas;
-}
-GEN
-nfdisc(GEN x) { return _nfdisc(x, 0, NULL); }
+nfbasis_gp(GEN x) { return nfbasis(x,NULL,NULL); }
 
 static ulong
 Flx_checkdeflate(GEN x)
@@ -950,7 +898,7 @@ ZpX_sylvester_echelon(GEN f1, GEN f2, long early_abort, GEN p, GEN pm)
   h = FpXQ_red(f2,f1,pm);
   for (j=1;; j++)
   {
-    gel(a,j) = RgX_to_RgV(h, n);
+    gel(a,j) = RgX_to_RgC(h, n);
     if (j == n) break;
     h = FpX_rem(RgX_shift_shallow(h, 1), f1, pm);
   }
@@ -963,18 +911,19 @@ Zlx_gcd(GEN f1, GEN f2, ulong p, ulong pm)
 {
   pari_sp av = avma;
   GEN a = Zlx_sylvester_echelon(f1,f2,0,p,pm);
-  long c, l = lg(a), v = varn(f1);
+  long c, l = lg(a), sv = f1[1];
   for (c = 1; c < l; c++)
   {
     ulong t = ucoeff(a,c,c);
     if (t)
     {
-      a = RgV_to_RgX(Flv_to_ZV(gel(a,c)), v);
+      a = Flx_to_ZX(Flv_to_Flx(gel(a,c), sv));
       if (t == 1) return gerepilecopy(av, a);
       return gerepileupto(av, RgX_Rg_div(a, utoipos(t)));
     }
   }
-  avma = av; return pol_0(v);
+  avma = av;
+  a = cgetg(2,t_POL); a[1] = sv; return a;
 }
 GEN
 ZpX_gcd(GEN f1, GEN f2, GEN p, GEN pm)
@@ -1263,7 +1212,7 @@ dbasis(GEN p, GEN f, long mf, GEN a, GEN U)
         h = FpXQ_mul(h, a, f, D);
         if (da) h = ZX_Z_divexact(h, da);
       }
-      gel(b,i) = RgX_to_RgV(h,n);
+      gel(b,i) = RgX_to_RgC(h,n);
     }
     return ZpM_hnfmodid(b, p, pd);
   }
@@ -1278,7 +1227,7 @@ dbasis(GEN p, GEN f, long mf, GEN a, GEN U)
     h = RgX_Rg_div(U, p);
     for ( ; i <= n; i++)
     {
-      gel(b, i) = RgX_to_RgV(h,n);
+      gel(b, i) = RgX_to_RgC(h,n);
       if (i == n) break;
       h = RgX_shift_shallow(h,1);
     }
@@ -1415,10 +1364,10 @@ Decomp(decomp_t *S, long flag)
     fred = centermod_i(S->f, D, shifti(D,-1));
     M = cgetg(n+1, t_MAT);
     for (i=1; i<=n1; i++)
-      gel(M,i) = RgX_to_RgV(FpX_rem(FpX_mul(gel(B1,i),e,D), fred, D), n);
+      gel(M,i) = RgX_to_RgC(FpX_rem(FpX_mul(gel(B1,i),e,D), fred, D), n);
     e = Z_ZX_sub(de, e); B2 -= n1;
     for (   ; i<=n; i++)
-      gel(M,i) = RgX_to_RgV(FpX_rem(FpX_mul(gel(B2,i),e,D), fred, D), n);
+      gel(M,i) = RgX_to_RgC(FpX_rem(FpX_mul(gel(B2,i),e,D), fred, D), n);
     return ZpM_hnfmodid(M, p, D);
   }
 }
@@ -1514,9 +1463,9 @@ newtonsums(GEN p, GEN a, GEN da, long vda, GEN chi, long c, GEN pp, GEN ns)
 {
   GEN va, pa, dpa, s;
   long j, k, vdpa;
-  pari_sp av, lim;
+  pari_sp av;
 
-  a = centermod(a, pp); av = avma; lim = stack_lim(av, 1);
+  a = centermod(a, pp); av = avma;
   dpa = pa = NULL; /* -Wall */
   vdpa = 0;
   va = zerovec(c);
@@ -1544,7 +1493,7 @@ newtonsums(GEN p, GEN a, GEN da, long vda, GEN chi, long c, GEN pp, GEN ns)
     }
     gel(va,j) = centermodii(s, pp, shifti(pp,-1));
 
-    if (low_stack(lim, stack_lim(av, 1)))
+    if (gc_needed(av, 1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem, "newtonsums");
       gerepileall(av, dpa?4:3, &pa, &va, &pp, &dpa);
@@ -1880,7 +1829,7 @@ get_g(decomp_t *S, long Ea, long L, long E, GEN beta, GEN *pchig,
 static int
 loop(decomp_t *S, long Ea)
 {
-  pari_sp av = avma, limit = stack_lim(av, 1);
+  pari_sp av = avma;
   GEN beta = FpXQ_powu(S->nu, Ea, S->chi, S->p);
   long N = degpol(S->f), v = varn(S->f);
   S->invnu = NULL;
@@ -1955,7 +1904,7 @@ loop(decomp_t *S, long Ea)
     if (er) d = gmul(d, gpowgs(S->nu, er));
     beta = gsub(beta, d);
 
-    if (low_stack(limit,stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM > 1) pari_warn(warnmem, "nilord");
       gerepileall(av, S->invnu? 5: 3, &beta, &(S->precns), &(S->ns), &(S->invnu), &(S->Dinvnu));
@@ -2119,23 +2068,18 @@ get_norm(norm_S *S, GEN a)
 static void
 init_norm(norm_S *S, GEN nf, GEN p)
 {
-  GEN T = nf_get_pol(nf);
-  long N = degpol(T);
+  GEN T = nf_get_pol(nf), M = nf_get_M(nf);
+  long N = degpol(T), ex = gexpo(M) + gexpo(mului(8 * N, p));
 
-  S->r1 = 0;   /* -Wall */
-  S->M = NULL; /* -Wall */
-  S->D = NULL; /* -Wall */
-  S->w = NULL; /* -Wall */
-  S->T = NULL; /* -Wall */
-  if (typ(gel(nf,5)) == t_VEC) /* beware dummy nf from rnf/makenfabs */
-  {
-    GEN M = nf_get_M(nf);
-    long ex = gexpo(M) + gexpo(mului(8 * N, p));
-    /* enough prec to use embed_norm */
-    S->r1 = nf_get_r1(nf);
-    if (N * ex <= prec2nbits(gprecision(M))) S->M = M;
+  S->r1 = nf_get_r1(nf);
+  if (N * ex <= prec2nbits(gprecision(M)))
+  { /* enough prec to use embed_norm */
+    S->M = M;
+    S->D = NULL;
+    S->w = NULL;
+    S->T = NULL;
   }
-  if (!S->M)
+  else
   {
     GEN D, w = Q_remove_denom(nf_get_zk(nf), &D), Dp = sqri(p);
     long i;
@@ -2148,6 +2092,7 @@ init_norm(norm_S *S, GEN nf, GEN p)
       gel(w, 1) = remii(w1, Dp);
     }
     for (i=2; i<=N; i++) gel(w,i) = FpX_red(gel(w,i), Dp);
+    S->M = NULL;
     S->D = D;
     S->w = w;
     S->T = T;
@@ -2368,12 +2313,13 @@ primedec_end(GEN nf, GEN L, GEN p)
   return Lpr;
 }
 
-/* prime ideal decomposition of p */
+/* prime ideal decomposition of p; if flim!=0, restrict to f(P,p) <= flim */
 static GEN
-primedec_aux(GEN nf, GEN p)
+primedec_aux(GEN nf, GEN p, long flim)
 {
   GEN E, F, L, Ip, H, phi, mat1, f, g, h, p1, UN, T = nf_get_pol(nf);
   long i, k, c, iL, N;
+  int kummer;
 
   F = FpX_factor(T, p);
   E = gel(F,2);
@@ -2384,10 +2330,15 @@ primedec_aux(GEN nf, GEN p)
   {
     L = cgetg(k,t_VEC);
     for (i=1; i<k; i++)
-      gel(L,i) = primedec_apply_kummer(nf,gel(F,i), E[i],p);
-    return L;
+    {
+      GEN t = gel(F,i);
+      if (flim && degpol(t) > flim) { setlg(L, i); break; }
+      gel(L,i) = primedec_apply_kummer(nf, t, E[i],p);
+    }
+    return gen_sort(L, (void*)&cmp_prime_over_p, &cmp_nodata);
   }
 
+  kummer = 0;
   g = FpXV_prod(F, p);
   h = FpX_div(T,g,p);
   f = FpX_red(ZX_Z_divexact(ZX_sub(ZX_mul(g,h), T), p), p);
@@ -2396,7 +2347,11 @@ primedec_aux(GEN nf, GEN p)
   L = cgetg(N+1,t_VEC); iL = 1;
   for (i=1; i<k; i++)
     if (E[i] == 1 || signe(FpX_rem(f,gel(F,i),p)))
-      gel(L,iL++) = primedec_apply_kummer(nf,gel(F,i), E[i],p);
+    {
+      GEN t = gel(F,i);
+      kummer = 1;
+      gel(L,iL++) = primedec_apply_kummer(nf, t, E[i],p);
+    }
     else /* F[i] | (f,g,h), happens at least once by Dedekind criterion */
       E[i] = 0;
 
@@ -2405,7 +2360,7 @@ primedec_aux(GEN nf, GEN p)
 
   /* split etale algebra Z_K / (p,Ip) */
   h = cgetg(N+1,t_VEC);
-  if (iL > 1)
+  if (kummer)
   { /* split off Kummer factors */
     GEN mulbeta, beta = NULL;
     for (i=1; i<k; i++)
@@ -2455,23 +2410,42 @@ primedec_aux(GEN nf, GEN p)
         gel(h,c++) = FpM_image(shallowconcat(H, I), p);
       }
       if (n == dim)
-        for (i=1; i<=n; i++) { H = gel(h,--c); gel(L,iL++) = H; }
+        for (i=1; i<=n; i++) gel(L,iL++) = gel(h,--c);
     }
     else /* A2 field ==> H maximal, f = N-k = dim(A2) */
       gel(L,iL++) = H;
   }
   setlg(L, iL);
-  return primedec_end(nf, L, p);
+  L = primedec_end(nf, L, p);
+  if (flim)
+  {
+    long k = 1;
+    for(i = 1; i < iL; i++)
+    {
+      GEN P = gel(L,i);
+      if (pr_get_f(P) <= flim) gel(L,k++) = P;
+    }
+    setlg(L,k);
+  }
+  return L;
 }
 
 GEN
-idealprimedec(GEN nf, GEN p)
+idealprimedec_limit_f(GEN nf, GEN p, long f)
 {
   pari_sp av = avma;
+  GEN v;
   if (typ(p) != t_INT) pari_err_TYPE("idealprimedec",p);
-  return gerepileupto(av, gen_sort(primedec_aux(checknf(nf),p),
-                                   (void*)&cmp_prime_over_p, &cmp_nodata));
+  v = primedec_aux(checknf(nf), p, f);
+  v = gen_sort(v, (void*)&cmp_prime_over_p, &cmp_nodata);
+  return gerepileupto(av,v);
 }
+GEN
+idealprimedec_limit_norm(GEN nf, GEN p, GEN B)
+{ return idealprimedec_limit_f(nf, p, logint(B,p,NULL)-1); }
+GEN
+idealprimedec(GEN nf, GEN p)
+{ return idealprimedec_limit_f(nf, p, 0); }
 
 /* return [Fp[x]: Fp] */
 static long
@@ -2536,8 +2510,6 @@ anti_uniformizer2(GEN nf, GEN pr)
 
 #define mpr_TAU 1
 #define mpr_FFP 2
-#define mpr_PR  3
-#define mpr_T   4
 #define mpr_NFP 5
 #define SMALLMODPR 4
 #define LARGEMODPR 6
@@ -2582,7 +2554,7 @@ get_proj_modT(GEN basis, GEN T, GEN p)
       w = Q_primitive_part(w, &cx);
       w = FpXQ_red(w, T, p);
       if (cx) w = FpX_Fp_mul(w, Rg_to_Fp(cx, p), p);
-      w = RgX_to_RgV(w, f);
+      w = RgX_to_RgC(w, f);
     }
     gel(z,i) = w; /* w_i mod (T,p) */
   }
@@ -2611,7 +2583,7 @@ modprinit(GEN nf, GEN pr, int zk)
     res = cgetg(SMALLMODPR, t_COL);
     gel(res,mpr_TAU) = tau;
     gel(res,mpr_FFP) = dim1proj(prh);
-    gel(res,mpr_PR) = pr; return gerepilecopy(av, res);
+    gel(res,3) = pr; return gerepilecopy(av, res);
   }
 
   c = cgetg(f+1, t_VECSMALL);
@@ -2640,8 +2612,8 @@ modprinit(GEN nf, GEN pr, int zk)
     res = cgetg(SMALLMODPR+1, t_COL);
     gel(res,mpr_TAU) = tau;
     gel(res,mpr_FFP) = ffproj;
-    gel(res,mpr_PR) = pr;
-    gel(res,mpr_T) = T; return gerepilecopy(av, res);
+    gel(res,3) = pr;
+    gel(res,4) = T; return gerepilecopy(av, res);
   }
 
   if (uisprime(f))
@@ -2697,8 +2669,8 @@ modprinit(GEN nf, GEN pr, int zk)
   res = cgetg(LARGEMODPR, t_COL);
   gel(res,mpr_TAU) = tau;
   gel(res,mpr_FFP) = ffproj;
-  gel(res,mpr_PR) = pr;
-  gel(res,mpr_T) = T;
+  gel(res,3) = pr;
+  gel(res,4) = T;
   gel(res,mpr_NFP) = nfproj; return gerepilecopy(av, res);
 }
 
@@ -2715,8 +2687,12 @@ void
 checkmodpr(GEN x)
 {
   if (!ok_modpr(x)) pari_err_TYPE("checkmodpr [use nfmodprinit]", x);
-  checkprid(gel(x,mpr_PR));
+  checkprid(modpr_get_pr(x));
 }
+GEN
+get_modpr(GEN x)
+{ return ok_modpr(x)? x: NULL; }
+
 static int
 is_prid(GEN x)
 {
@@ -2733,7 +2709,7 @@ get_prid(GEN x)
   if (lx == 3 && typ(x) == t_VEC) x = gel(x,1);
   if (is_prid(x)) return x;
   if (ok_modpr(x)) {
-    x = gel(x,mpr_PR);
+    x = modpr_get_pr(x);
     if (is_prid(x)) return x;
   }
   return NULL;
@@ -2743,9 +2719,9 @@ static GEN
 to_ff_init(GEN nf, GEN *pr, GEN *T, GEN *p, int zk)
 {
   GEN modpr = (typ(*pr) == t_COL)? *pr: modprinit(nf, *pr, zk);
-  *T = lg(modpr)==SMALLMODPR? NULL: gel(modpr,mpr_T);
-  *pr = gel(modpr,mpr_PR);
-  *p = gel(*pr,1); return modpr;
+  *T = modpr_get_T(modpr);
+  *pr = modpr_get_pr(modpr);
+  *p = pr_get_p(*pr); return modpr;
 }
 
 /* Return an element of O_K which is set to x Mod T */
@@ -2760,7 +2736,7 @@ modpr_genFq(GEN modpr)
       return gmael(modpr,mpr_NFP, 2);
     default: /* trivial case : p \nmid index */
     {
-      long v = varn( gel(modpr, mpr_T) );
+      long v = varn( modpr_get_T(modpr) );
       return pol_x(v);
     }
   }
@@ -2782,10 +2758,10 @@ zk_to_Fq_init(GEN nf, GEN *pr, GEN *T, GEN *p) {
 GEN
 zk_to_Fq(GEN x, GEN modpr)
 {
-  GEN pr = gel(modpr,mpr_PR), p = pr_get_p(pr);
+  GEN pr = modpr_get_pr(modpr), p = pr_get_p(pr);
   GEN ffproj = gel(modpr,mpr_FFP);
-  if (lg(modpr) == SMALLMODPR) return FpV_dotproduct(ffproj,x, p);
-  return FpM_FpC_mul_FpX(ffproj,x, p, varn(gel(modpr,mpr_T)));
+  GEN T = modpr_get_T(modpr);
+  return T? FpM_FpC_mul_FpX(ffproj,x, p, varn(T)): FpV_dotproduct(ffproj,x, p);
 }
 
 /* REDUCTION Modulo a prime ideal */
@@ -2794,7 +2770,7 @@ zk_to_Fq(GEN x, GEN modpr)
 static GEN
 Rg_to_ff(GEN nf, GEN x0, GEN modpr)
 {
-  GEN x = x0, den, pr = gel(modpr,mpr_PR), p = pr_get_p(pr);
+  GEN x = x0, den, pr = modpr_get_pr(modpr), p = pr_get_p(pr);
   long tx = typ(x);
 
   if (tx == t_POLMOD) { x = gel(x,2); tx = typ(x); }
@@ -3124,7 +3100,7 @@ rnfdedekind_i(GEN nf, GEN P, GEN pr, long vdisc, long only_maximal)
   pal = FqX_to_nfX(FqX_div(Ppr,k, T,p), modpr);
   for (   ; j<=m+d; j++)
   {
-    gel(A,j) = RgX_to_RgV(pal,m);
+    gel(A,j) = RgX_to_RgC(pal,m);
     gel(I,j) = prinvp;
     if (j < m+d) pal = RgXQX_rem(RgX_shift_shallow(pal,1),P,nfT);
   }
@@ -3217,7 +3193,7 @@ ideal_is1(GEN x) {
 static GEN
 rnfmaxord(GEN nf, GEN pol, GEN pr, long vdisc)
 {
-  pari_sp av = avma, av1, lim;
+  pari_sp av = avma, av1;
   long i, j, k, n, vpol, cmpt, sep;
   GEN q, q1, p, T, modpr, W, I, MW, C, p1;
   GEN Tauinv, Tau, prhinv, pip, nfT, rnfId;
@@ -3247,7 +3223,7 @@ rnfmaxord(GEN nf, GEN pol, GEN pr, long vdisc)
   for (j=1; j<=n*n; j++) gel(MW,j) = cgetg(n+1, t_COL);
   Tauinv = cgetg(n+1, t_VEC);
   Tau    = cgetg(n+1, t_VEC);
-  av1 = avma; lim = stack_lim(av1,1);
+  av1 = avma;
   for(cmpt=1; ; cmpt++)
   {
     GEN I0 = leafcopy(I), W0 = leafcopy(W);
@@ -3342,7 +3318,7 @@ rnfmaxord(GEN nf, GEN pol, GEN pr, long vdisc)
     if (DEBUGLEVEL>3) err_printf(" new order:\n%Ps\n%Ps\n", W, I);
     if (sep <= 3 || gequal(I,I0)) break;
 
-    if (low_stack(lim, stack_lim(av1,1)) || (cmpt & 3) == 0)
+    if (gc_needed(av1,1) || (cmpt & 3) == 0)
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"rnfmaxord");
       gerepileall(av1,2, &W,&I);
@@ -3733,16 +3709,30 @@ rnfisfree(GEN bnf, GEN order)
 /**                                                                  **/
 /**********************************************************************/
 static GEN
-compositum_fix(GEN A)
+compositum_fix(GEN nf, GEN A)
 {
-  A = Q_primpart(A); RgX_check_ZX(A,"polcompositum");
-  if (!ZX_is_squarefree(A))
-    pari_err_DOMAIN("polcompositum","issquarefree(arg)","=",gen_0,A);
+  int ok;
+  if (nf)
+  {
+    long i, l = lg(A);
+    A = shallowcopy(A);
+    for (i=2; i<l; i++) gel(A,i) = basistoalg(nf, gel(A,i));
+    ok = nfissquarefree(nf,A);
+  }
+  else
+  {
+    A = Q_primpart(A); RgX_check_ZX(A,"polcompositum");
+    ok = ZX_is_squarefree(A);
+  }
+  if (!ok) pari_err_DOMAIN("polcompositum","issquarefree(arg)","=",gen_0,A);
   return A;
 }
+INLINE long
+nextk(long k) { return k>0 ? -k : 1-k; }
+
 /* modular version */
 GEN
-polcompositum0(GEN A, GEN B, long flall)
+nfcompositum(GEN nf, GEN A, GEN B, long flag)
 {
   pari_sp av = avma;
   int same;
@@ -3755,36 +3745,81 @@ polcompositum0(GEN A, GEN B, long flall)
   v = varn(A);
   if (varn(B) != v) pari_err_VAR("polcompositum", A,B);
   same = (A == B || RgX_equal(A,B));
-  A = compositum_fix(A);
-  if (!same) B = compositum_fix(B);
+  A = compositum_fix(nf,A);
+  if (!same) B = compositum_fix(nf,B);
 
-  D = NULL; /* -Wall */
+  D = LPRS = NULL; /* -Wall */
   k = same? -1: 1;
-  C = ZX_ZXY_resultant_all(A, B, &k, flall? &LPRS: NULL);
+  if (nf)
+  {
+    long v0 = fetch_var();
+    GEN q;
+    for(;; k = nextk(k))
+    {
+      GEN chgvar = deg1pol_shallow(stoi(k),pol_x(v0),v);
+      GEN B1 = poleval(B,chgvar);
+      C = RgX_resultant_all(A,B1,&q);
+      C = gsubst(C,v0,pol_x(v));
+      if (nfissquarefree(nf,C)) break;
+    }
+    C = lift_if_rational(C);
+    if (flag&1)
+    {
+      GEN H0, H1;
+      H0 = gsubst(gel(q,2),v0,pol_x(v));
+      H1 = gsubst(gel(q,3),v0,pol_x(v));
+      if (typ(H0) != t_POL) H0 = scalarpol_shallow(H0,v);
+      if (typ(H1) != t_POL) H1 = scalarpol_shallow(H1,v);
+      H0 = lift_if_rational(H0);
+      H1 = lift_if_rational(H1);
+      LPRS = mkvec2(H0,H1);
+    }
+  }
+  else
+  {
+    B = leafcopy(B); setvarn(B,fetch_var_higher());
+    C = ZX_ZXY_resultant_all(A, B, &k, (flag&1)? &LPRS: NULL);
+    setvarn(C, v);
+  }
+  /* C = Res_Y (A(Y), B(X + kY)) guaranteed squarefree */
   if (same)
   {
     D = RgX_rescale(A, stoi(1 - k));
     C = RgX_div(C, D);
-    if (degpol(C) <= 0) C = mkvec(D); else C = shallowconcat(ZX_DDF(C), D);
+    if (degpol(C) <= 0)
+      C = mkvec(D);
+    else
+      C = shallowconcat(nf? gel(nffactor(nf,C),1): ZX_DDF(C), D);
   }
+  else if (flag & 2)
+    C = mkvec(C);
   else
-    C = ZX_DDF(C); /* C = Res_Y (A(Y), B(X + kY)) guaranteed squarefree */
-  gen_sort_inplace(C, (void*)&cmpii, &gen_cmp_RgX, NULL);
-  if (flall)
+    C = nf? gel(nffactor(nf,C),1): ZX_DDF(C);
+  gen_sort_inplace(C, (void*)(nf?&cmp_RgX: &cmpii), &gen_cmp_RgX, NULL);
+  if (flag&1)
   { /* a,b,c root of A,B,C = compositum, c = b - k a */
     long i, l = lg(C);
     GEN a, b, mH0 = RgX_neg(gel(LPRS,1)), H1 = gel(LPRS,2);
+    setvarn(mH0,v);
+    setvarn(H1,v);
     for (i=1; i<l; i++)
     {
       GEN D = gel(C,i);
-      a = RgXQ_mul(mH0, QXQ_inv(H1, D), D);
+      a = RgXQ_mul(mH0, nf? RgXQ_inv(H1,D): QXQ_inv(H1,D), D);
       b = gadd(pol_x(v), gmulsg(k,a));
       gel(C,i) = mkvec4(D, mkpolmod(a,D), mkpolmod(b,D), stoi(-k));
     }
   }
-  settyp(C, t_VEC); return gerepilecopy(av, C);
+  (void)delete_var();
+  settyp(C, t_VEC);
+  if (flag&2) C = gel(C,1);
+  return gerepilecopy(av, C);
 }
 GEN
+polcompositum0(GEN A, GEN B, long flag)
+{ return nfcompositum(NULL,A,B,flag); }
+
+GEN
 compositum(GEN pol1,GEN pol2) { return polcompositum0(pol1,pol2,0); }
 GEN
 compositum2(GEN pol1,GEN pol2) { return polcompositum0(pol1,pol2,1); }
@@ -3797,3 +3832,47 @@ ZX_compositum_disjoint(GEN A, GEN B)
   long k = 1;
   return ZX_ZXY_resultant_all(A, B, &k, NULL);
 }
+
+GEN
+nfsplitting(GEN T, GEN D)
+{
+  pari_sp av = avma;
+  long d, v;
+  GEN F, K;
+  T = get_nfpol(T,&K);
+  if (!K)
+  {
+    if (typ(T) != t_POL) pari_err_TYPE("nfsplitting",T);
+    T = Q_primpart(T);
+    RgX_check_ZX(T,"nfsplitting");
+  }
+  d = degpol(T);
+  if (d<=1) return pol_x(0);
+  if (!K) {
+    if (!isint1(leading_term(T))) K = T = polredbest(T,0);
+    K = T;
+  }
+  if (D)
+  {
+    if (typ(D) != t_INT || signe(D) < 1) pari_err_TYPE("nfsplitting",D);
+  }
+  else
+  {
+    char *data = stack_strcat(pari_datadir, "/galdata");
+    long dmax = pari_is_dir(data)? 11: 7;
+    D = (d <= dmax)? gel(polgalois(T,DEFAULTPREC), 1): mpfact(d);
+  }
+  d = itos_or_0(D);
+  v = varn(T);
+  T = leafcopy(T); setvarn(T, fetch_var_higher());
+  for(F = T;;)
+  {
+    GEN P = gel(nffactor(K, F), 1), Q = gel(P,lg(P)-1);
+    if (degpol(gel(P,1)) == degpol(Q)) break;
+    F = rnfequation(K,Q);
+    if (degpol(F) == d) break;
+  }
+  (void)delete_var();
+  setvarn(F,v);
+  return gerepilecopy(av, F);
+}
diff --git a/src/basemath/base3.c b/src/basemath/base3.c
index 8871dd9..4ad7341 100644
--- a/src/basemath/base3.c
+++ b/src/basemath/base3.c
@@ -650,6 +650,7 @@ ZC_nfvalrem(GEN nf, GEN x, GEN pr, GEN *newx)
   long i, v, l;
   GEN r, y, p = pr_get_p(pr), mul = zk_scalar_or_multable(nf, pr_get_tau(pr));
 
+  /* p inert */
   if (typ(mul) == t_INT) return newx? ZV_pvalrem(x, p, newx):ZV_pval(x, p);
   y = cgetg_copy(x, &l); /* will hold the new x */
   x = leafcopy(x);
@@ -761,6 +762,12 @@ nfvalrem(GEN nf, GEN x, GEN pr, GEN *py)
     *py = gerepilecopy(av, *py);
   return w;
 }
+GEN
+gpnfvalrem(GEN nf, GEN x, GEN pr, GEN *py)
+{
+  long v = nfvalrem(nf,x,pr,py);
+  return v == LONG_MAX? mkoo(): stoi(v);
+}
 
 GEN
 coltoalg(GEN nf, GEN x)
@@ -874,7 +881,7 @@ nf_to_scalar_or_alg(GEN nf, GEN x)
   return NULL; /* not reached */
 }
 
-/* gmul(A, RgX_to_Rg(x)), A t_MAT (or t_VEC) of compatible dimensions */
+/* gmul(A, RgX_to_RgC(x)), A t_MAT (or t_VEC) of compatible dimensions */
 GEN
 mulmat_pol(GEN A, GEN x)
 {
@@ -1156,12 +1163,37 @@ eval_sign(GEN M, GEN x, long k)
 {
   long i, l = lg(x);
   GEN z = gel(x,1); /* times M[k,1], which is 1 */
-  for (i = 2; i < l; i++)
-    z = mpadd(z, mpmul(gcoeff(M,k,i), gel(x,i)));
+  for (i = 2; i < l; i++) z = mpadd(z, mpmul(gcoeff(M,k,i), gel(x,i)));
   if (realprec(z) < DEFAULTPREC) pari_err_PREC("nfsign_arch");
   return signe(z);
 }
 
+/* sigma_k(x) */
+GEN
+nfembed(GEN nf, GEN x, long k)
+{
+  pari_sp av = avma;
+  long i, l;
+  GEN z, M;
+  nf = checknf(nf);
+  x = nf_to_scalar_or_basis(nf,x);
+  if (typ(x) != t_COL) return gerepilecopy(av, x);
+  M = nf_get_M(nf); l = lg(M); /* > 2 */
+  z = gel(x,1);
+  for (i=2; i<l; i++) z = gadd(z, gmul(gcoeff(M,k,i), gel(x,i)));
+  return gerepileupto(av, z);
+}
+
+GEN
+vecsmall01_to_indices(GEN v)
+{
+  long i, k, l = lg(v);
+  GEN p = new_chunk(l) + l;
+  for (k=1, i=l-1; i; i--)
+    if (v[i]) { *--p = i; k++; }
+  *--p = evallg(k) | evaltyp(t_VECSMALL);
+  avma = (pari_sp)p; return p;
+}
 GEN
 vec01_to_indices(GEN v)
 {
@@ -1322,7 +1354,7 @@ GEN
 famat_to_nf_modideal_coprime(GEN nf, GEN g, GEN e, GEN id, GEN EX)
 {
   GEN plus = NULL, minus = NULL, idZ = gcoeff(id,1,1);
-  pari_sp av = avma, lim = stack_lim(av,2);
+  pari_sp av = avma;
   long i, lx = lg(g);
   GEN EXo2 = (expi(EX) > 10)? shifti(EX,-1): NULL;
 
@@ -1351,7 +1383,7 @@ famat_to_nf_modideal_coprime(GEN nf, GEN g, GEN e, GEN id, GEN EX)
     else /* sn < 0 */
       minus = elt_mulpow_modideal(nf, minus, h, absi(n), id);
 
-    if (low_stack(lim, stack_lim(av, 2)))
+    if (gc_needed(av, 2))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"famat_to_nf_modideal_coprime");
       if (!plus) plus = gen_0;
@@ -2305,7 +2337,7 @@ zlog_units(GEN nf, GEN U, GEN sgnU, GEN bid)
   GEN m = cgetg(l, t_MAT);
   zlog_S S; init_zlog_bid(&S, bid);
   for (j = 1; j < l; j++)
-    gel(m,j) = zlog(nf, gel(U,j), vecpermute(gel(sgnU,j), S.archp), &S);
+    gel(m,j) = zlog(nf, gel(U,j), vecsmallpermute(gel(sgnU,j), S.archp), &S);
   return m;
 }
 /* compute matrix of zlogs of units, assuming S.archp = [] */
@@ -2337,9 +2369,9 @@ Ideallist(GEN bnf, ulong bound, long flag)
 {
   const long do_units = flag & 2, big_id = !(flag & 4);
   const long istar_flag = (flag & nf_GEN) | nf_INIT;
-  pari_sp lim, av, av0 = avma;
+  pari_sp av, av0 = avma;
   long i, j, l;
-  GEN nf, z, p, fa, id, U, empty = cgetg(1,t_VEC);
+  GEN nf, z, p, fa, id, BOUND, U, empty = cgetg(1,t_VEC);
   forprime_t S;
   ideal_data ID;
   GEN (*join_z)(ideal_data*, GEN) =
@@ -2355,6 +2387,7 @@ Ideallist(GEN bnf, ulong bound, long flag)
    * an ideal, a bid, or a couple [bid, log(units)]. Such objects are stored
    * in vectors, computed one primary component at a time; join_z
    * reconstructs the global object */
+  BOUND = utoipos(bound);
   z = cgetg(bound+1,t_VEC);
   if (do_units) {
     U = init_units(bnf);
@@ -2368,17 +2401,15 @@ Ideallist(GEN bnf, ulong bound, long flag)
 
   p = cgetipos(3);
   u_forprime_init(&S, 2, bound);
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
   while ((p[2] = u_forprime_next(&S)))
   {
     if (DEBUGLEVEL>1) { err_printf("%ld ",p[2]); err_flush(); }
-    fa = idealprimedec(nf, p);
+    fa = idealprimedec_limit_norm(nf, p, BOUND);
     for (j=1; j<lg(fa); j++)
     {
       GEN pr = gel(fa,j), z2;
-      long f = pr_get_f(pr);
-      ulong q, Q = upowuu(p[2], f);
-      if (!Q || Q > bound) break;
+      ulong q, Q = upowuu(p[2], pr_get_f(pr));
 
       z2 = leafcopy(z);
       q = Q;
@@ -2396,7 +2427,7 @@ Ideallist(GEN bnf, ulong bound, long flag)
           concat_join(&gel(z,iQ), gel(z2,i), join_z, &ID);
       }
     }
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"Ideallist");
       z = gerepilecopy(av, z);
diff --git a/src/basemath/base4.c b/src/basemath/base4.c
index e2aea86..1e2088f 100644
--- a/src/basemath/base4.c
+++ b/src/basemath/base4.c
@@ -96,7 +96,7 @@ idealhnf_principal(GEN nf, GEN x)
     case t_INT:  if (!signe(x)) return cgetg(1,t_MAT);
       return scalarmat(absi(x), nf_get_degree(nf));
     case t_FRAC:
-      return scalarmat(Q_abs(x), nf_get_degree(nf));
+      return scalarmat(Q_abs_shallow(x), nf_get_degree(nf));
     default: pari_err_TYPE("idealhnf",x);
   }
   x = Q_primitive_part(x, &cx);
@@ -458,7 +458,8 @@ idealtwoelt(GEN nf, GEN x)
   if (tx == id_PRIME) return mkvec2copy(gel(x,1), gel(x,2));
   /* id_PRINCIPAL */
   av = avma; x = nf_to_scalar_or_basis(nf, x);
-  return gerepilecopy(av, typ(x)==t_COL? mkvec2(gen_0,x): mkvec2(Q_abs(x),gen_0));
+  return gerepilecopy(av, typ(x)==t_COL? mkvec2(gen_0,x):
+                                         mkvec2(Q_abs_shallow(x),gen_0));
 }
 
 /*******************************************************************/
@@ -580,7 +581,7 @@ idealfactor(GEN nf, GEN x)
       GEN c1, c2;
       long lfa, i,j;
       if (isintzero(y)) pari_err_DOMAIN("idealfactor", "ideal", "=",gen_0,x);
-      f = factor(Q_abs(y));
+      f = factor(Q_abs_shallow(y));
       c1 = gel(f,1); lfa = lg(c1);
       if (lfa == 1) { avma = av; return trivial_fact(); }
       c2 = gel(f,2);
@@ -618,7 +619,7 @@ idealfactor(GEN nf, GEN x)
 long
 idealval(GEN nf, GEN ix, GEN P)
 {
-  pari_sp av = avma, av1, lim;
+  pari_sp av = avma, av1;
   long N, vmax, vd, v, e, f, i, j, k, tx = typ(ix);
   GEN mul, B, a, x, y, r, p, pk, cx, vals;
 
@@ -672,7 +673,7 @@ idealval(GEN nf, GEN ix, GEN P)
     gel(B,j) = Q_primitive_part(gel(B,j), &cx);
     vals[j] = cx? 1 + e * Q_pval(cx, p): 1;
   }
-  av1 = avma; lim = stack_lim(av1,3);
+  av1 = avma;
   y = cgetg(N+1,t_COL);
   /* can compute mod p^ceil((vmax-v)/e) */
   for (v = 1; v < vmax; v++)
@@ -693,7 +694,7 @@ idealval(GEN nf, GEN ix, GEN P)
         gel(y,i) = gerepileuptoint(av2, a);
       }
       gel(B,j) = y; y = x;
-      if (low_stack(lim,stack_lim(av1,3)))
+      if (gc_needed(av1,3))
       {
         if(DEBUGMEM>1) pari_warn(warnmem,"idealval");
         gerepileall(av1,3, &y,&B,&pk);
@@ -702,6 +703,12 @@ idealval(GEN nf, GEN ix, GEN P)
   }
   avma = av; return v + vd;
 }
+GEN
+gpidealval(GEN nf, GEN ix, GEN P)
+{
+  long v = idealval(nf,ix,P);
+  return v == LONG_MAX? mkoo(): stoi(v);
+}
 
 /* gcd and generalized Bezout */
 
@@ -998,6 +1005,29 @@ famat_pow(GEN f, GEN n)
   return h;
 }
 
+GEN
+famat_Z_gcd(GEN M, GEN n)
+{
+  pari_sp av=avma;
+  long i, j, l=lgcols(M);
+  GEN F=cgetg(3,t_MAT);
+  gel(F,1)=cgetg(l,t_COL);
+  gel(F,2)=cgetg(l,t_COL);
+  for (i=1, j=1; i<l; i++)
+  {
+    GEN p = gcoeff(M,i,1);
+    GEN e = gminsg(Z_pval(n,p),gcoeff(M,i,2));
+    if (signe(e))
+    {
+      gcoeff(F,j,1)=p;
+      gcoeff(F,j,2)=e;
+      j++;
+    }
+  }
+  setlg(gel(F,1),j); setlg(gel(F,2),j);
+  return gerepilecopy(av,F);
+}
+
 /* x assumed to be a t_MATs (factorization matrix), or compatible with
  * the element_* functions. */
 static GEN
@@ -1171,11 +1201,20 @@ nf_to_Fp_simple(GEN x, GEN modpr, GEN p)
   if (c) r = Rg_to_Fp(gmul(r, c), p);
   return r;
 }
+/* assume pr coprime to numerator(x) */
+static GEN
+nf_to_Fq_simple(GEN nf, GEN x, GEN pr)
+{
+  GEN T, p, modpr = zk_to_Fq_init(nf, &pr, &T, &p);
+  GEN c, r = zk_to_Fq(Q_primitive_part(x, &c), modpr);
+  if (c) r = Fq_Fp_mul(r, Rg_to_Fp(c,p), T,p);
+  return r;
+}
 
 static GEN
 famat_to_Fp_simple(GEN nf, GEN x, GEN modpr, GEN p)
 {
-  GEN h, n, t = gen_1, g = gel(x,1), e = gel(x,2), q = subis(p,1);
+  GEN h, n, t = gen_1, g = gel(x,1), e = gel(x,2), q = subiu(p,1);
   long i, l = lg(g);
 
   for (i=1; i<l; i++)
@@ -1194,6 +1233,29 @@ famat_to_Fp_simple(GEN nf, GEN x, GEN modpr, GEN p)
   }
   return modii(t, p);
 }
+static GEN
+famat_to_Fq_simple(GEN nf, GEN x, GEN pr)
+{
+  GEN T, p, modpr = zk_to_Fq_init(nf, &pr, &T, &p);
+  GEN h, n, t = gen_1, g = gel(x,1), e = gel(x,2), q = subiu(pr_norm(pr),1);
+  long i, l = lg(g);
+
+  for (i=1; i<l; i++)
+  {
+    n = gel(e,i); n = modii(n,q);
+    if (!signe(n)) continue;
+
+    h = gel(g,i);
+    switch(typ(h))
+    {
+      case t_POL: case t_POLMOD: h = algtobasis(nf, h);  /* fall through */
+      case t_COL: h = nf_to_Fq_simple(nf, h, modpr); break;
+      default: h = nf_to_Fq(nf, h, modpr);
+    }
+    t = Fq_mul(t, Fq_pow(h, n, T, p), T,p);
+  }
+  return t;
+}
 
 /* cf famat_to_nf_modideal_coprime, but id is a prime of degree 1 (=pr) */
 GEN
@@ -1207,6 +1269,17 @@ to_Fp_simple(GEN nf, GEN x, GEN pr)
     default: return Rg_to_Fp(x, p);
   }
 }
+GEN
+to_Fq_simple(GEN nf, GEN x, GEN pr)
+{
+  GEN T, p, modpr = zk_to_Fq_init(nf, &pr, &T, &p);
+  switch(typ(x))
+  {
+    case t_COL: return nf_to_Fq_simple(nf,x,modpr);
+    case t_MAT: return famat_to_Fq_simple(nf,x,modpr);
+    default: return nf_to_Fq(x, p, modpr);
+  }
+}
 
 /* Compute A = prod g[i]^e[i] mod pr^k, assuming (A, pr) = 1.
  * Method: modify each g[i] so that it becomes coprime to pr :
@@ -1221,7 +1294,7 @@ famat_makecoprime(GEN nf, GEN g, GEN e, GEN pr, GEN prk, GEN EX)
 {
   long i, l = lg(g);
   GEN prkZ, u, vden = gen_0, p = pr_get_p(pr);
-  pari_sp av = avma, lim = stack_lim(av, 2);
+  pari_sp av = avma;
   GEN newg = cgetg(l+1, t_VEC); /* room for z */
 
   prkZ = gcoeff(prk, 1,1);
@@ -1247,7 +1320,7 @@ famat_makecoprime(GEN nf, GEN g, GEN e, GEN pr, GEN prk, GEN EX)
       x =  ZC_hnfrem(x, prk);
     }
     gel(newg,i) = x;
-    if (low_stack(lim, stack_lim(av, 2)))
+    if (gc_needed(av, 2))
     {
       GEN dummy = cgetg(1,t_VEC);
       long j;
@@ -1344,7 +1417,7 @@ idealmulelt(GEN nf, GEN x, GEN v)
   if (lg(v) == 1) return cgetg(1, t_MAT);
   x = nf_to_scalar_or_basis(nf,x);
   if (typ(x) != t_COL)
-    return isintzero(x)? cgetg(1,t_MAT): RgM_Rg_mul(v, Q_abs(x));
+    return isintzero(x)? cgetg(1,t_MAT): RgM_Rg_mul(v, Q_abs_shallow(x));
   x = nfC_nf_mul(nf, v, x);
   x = Q_primitive_part(x, &cx);
   settyp(x, t_MAT); lx = lg(x);
@@ -1384,7 +1457,7 @@ idealmul_aux(GEN nf, GEN x, GEN y, long tx, long ty)
               if (!signe(x)) return cgetg(1,t_MAT);
               return ZM_Z_mul(idealhnf_two(nf,y), absi(x));
             case t_FRAC:
-              return RgM_Rg_mul(idealhnf_two(nf,y), Q_abs(x));
+              return RgM_Rg_mul(idealhnf_two(nf,y), Q_abs_shallow(x));
           }
           /* t_COL */
           x = Q_primitive_part(x, &cx);
@@ -1490,7 +1563,7 @@ idealinv_HNF_aux(GEN nf, GEN I)
   return ZM_hnfmodid(dual, IZ);
 }
 /* I HNF with rational coefficients (denominator d). */
-static GEN
+GEN
 idealinv_HNF(GEN nf, GEN I)
 {
   GEN J, IQ = gcoeff(I,1,1); /* I \cap Q; d IQ = dI \cap Z */
@@ -1835,11 +1908,15 @@ idealdiv(GEN nf, GEN x, GEN y)
  * Hence v_p (x + Nx/Nz) = v_p(x).  Likewise for the denominators.  QED.
  *
  *                Peter Montgomery.  July, 1994. */
+static void
+err_divexact(GEN x, GEN y)
+{ pari_err_DOMAIN("idealdivexact","denominator(x/y)", "!=",
+                  gen_1,mkvec2(x,y)); }
 GEN
 idealdivexact(GEN nf, GEN x0, GEN y0)
 {
   pari_sp av = avma;
-  GEN x, y, yZ, Nx, Ny, Nz, cy;
+  GEN x, y, yZ, Nx, Ny, Nz, cy, q, r;
 
   nf = checknf(nf);
   x = idealhnf_shallow(nf, x0);
@@ -1850,18 +1927,20 @@ idealdivexact(GEN nf, GEN x0, GEN y0)
   if (cy) x = RgM_Rg_div(x,cy);
   Nx = idealnorm(nf,x);
   Ny = idealnorm(nf,y);
-  if (typ(Nx) != t_INT || typ(Ny) != t_INT || !dvdii(Nx,Ny))
-    pari_err_DOMAIN("idealdivexact","denominator(x/y)", "!=",
-                    gen_1,mkvec2(x,y));
+  if (typ(Nx) != t_INT) err_divexact(x,y);
+  q = dvmdii(Nx,Ny, &r);
+  if (signe(r)) err_divexact(x,y);
+  if (is_pm1(q)) { avma = av; return matid(nf_get_degree(nf)); }
   /* Find a norm Nz | Ny such that gcd(Nx/Nz, Nz) = 1 */
-  for (Nz = Ny;;)
+  for (Nz = Ny;;) /* q = Nx/Nz */
   {
-    GEN p1 = gcdii(Nz, diviiexact(Nx,Nz));
+    GEN p1 = gcdii(Nz, q);
     if (is_pm1(p1)) break;
     Nz = diviiexact(Nz,p1);
+    q = mulii(q,p1);
   }
   /* Replace x/y  by  x+(Nx/Nz) / y+(Ny/Nz) */
-  x = ZM_hnfmodid(x, diviiexact(Nx,Nz));
+  x = ZM_hnfmodid(x, q);
   /* y reduced to unit ideal ? */
   if (Nz == Ny) return gerepileupto(av, x);
 
@@ -2449,370 +2528,6 @@ idealcoprime(GEN nf, GEN x, GEN y)
   return gerepileupto(av, idealcoprimefact(nf, x, idealfactor(nf,y)));
 }
 
-/*******************************************************************/
-/*                                                                 */
-/*                  LINEAR ALGEBRA OVER Z_K  (HNF,SNF)             */
-/*                                                                 */
-/*******************************************************************/
-/* A torsion-free module M over Z_K is given by [A,I].
- * I=[a_1,...,a_k] is a row vector of k fractional ideals given in HNF.
- * A is an n x k matrix (same k) such that if A_j is the j-th column of A then
- * M=a_1 A_1+...+a_k A_k. We say that [A,I] is a pseudo-basis if k=n */
-
-/* Given an element x and an ideal I in HNF, gives an r such that x-r is in H
- * and r is small */
-GEN
-nfreduce(GEN nf, GEN x, GEN I)
-{
-  pari_sp av = avma;
-  GEN aI;
-  x = nf_to_scalar_or_basis(checknf(nf), x);
-  if (idealtyp(&I,&aI) != id_MAT || lg(I)==1) pari_err_TYPE("nfreduce",I);
-  if (typ(x) != t_COL) x = scalarcol( gmod(x, gcoeff(I,1,1)), lg(I)-1 );
-  else x = reducemodinvertible(x, I);
-  return gerepileupto(av, x);
-}
-/* Given an element x and an ideal in HNF, gives an a in ideal such that
- * x-a is small. No checks */
-static GEN
-element_close(GEN nf, GEN x, GEN ideal)
-{
-  pari_sp av = avma;
-  GEN y = gcoeff(ideal,1,1);
-  x = nf_to_scalar_or_basis(nf, x);
-  if (typ(y) == t_INT && is_pm1(y)) return ground(x);
-  if (typ(x) == t_COL)
-    x = closemodinvertible(x, ideal);
-  else
-    x = gmul(y, gdivround(x,y));
-  return gerepileupto(av, x);
-}
-
-/* A + v B */
-static GEN
-colcomb1(GEN nf, GEN v, GEN A, GEN B)
-{
-  if (isintzero(v)) return A;
-  return RgC_to_nfC(nf, RgC_add(A, nfC_nf_mul(nf,B,v)));
-}
-/* u A + v B */
-static GEN
-colcomb(GEN nf, GEN u, GEN v, GEN A, GEN B)
-{
-  if (isintzero(u)) return nfC_nf_mul(nf,B,v);
-  if (u != gen_1) A = nfC_nf_mul(nf,A,u);
-  return colcomb1(nf, v, A, B);
-}
-
-/* return m[i,1..lim] * x */
-static GEN
-element_mulvecrow(GEN nf, GEN x, GEN m, long i, long lim)
-{
-  long j, l = minss(lg(m), lim+1);
-  GEN dx, y = cgetg(l, t_VEC);
-  x = nf_to_scalar_or_basis(nf, x);
-  if (typ(x) == t_COL)
-  {
-    x = zk_multable(nf, Q_remove_denom(x, &dx));
-    for (j=1; j<l; j++)
-    {
-      GEN t = gcoeff(m,i,j);
-      if (!isintzero(t))
-      {
-        if (typ(t) == t_COL)
-          t = RgM_RgC_mul(x, t);
-        else
-          t = RgC_Rg_mul(gel(x,1), t);
-        if (dx) t = gdiv(t, dx);
-        t = nf_to_scalar_or_basis(nf,t);
-      }
-      gel(y,j) = t;
-    }
-  }
-  else
-  {
-    for (j=1; j<l; j++) gel(y,j) = gmul(x, gcoeff(m,i,j));
-  }
-  return y;
-}
-
-/* u Z[s,] + v Z[t,], limitied to the first lim entries */
-static GEN
-rowcomb(GEN nf, GEN u, GEN v, long s, long t, GEN Z, long lim)
-{
-  GEN z;
-  if (gequal0(u))
-    z = element_mulvecrow(nf,v,Z,t, lim);
-  else
-  {
-    z = element_mulvecrow(nf,u,Z,s, lim);
-    if (!gequal0(v)) z = gadd(z, element_mulvecrow(nf,v,Z,t, lim));
-  }
-  return z;
-}
-
-/* nfbezout(0,b,A,B). Either bB = NULL or b*B */
-static GEN
-zero_nfbezout(GEN nf,GEN bB, GEN b, GEN A,GEN B,GEN *u,GEN *v,GEN *w,GEN *di)
-{
-  GEN d;
-  if (isint1(b))
-  {
-    *v = gen_1;
-    *w = A;
-    d = B;
-    *di = idealinv(nf,d);
-  }
-  else
-  {
-    *v = nfinv(nf,b);
-    *w = idealmul(nf,A,*v);
-    d = bB? bB: idealmul(nf,b,B);
-    *di = idealinv_HNF(nf,d);
-  }
-  *u = gen_0; return d;
-}
-
-/* Given elements a,b and ideals A, B, outputs d = a.A+b.B and gives
- * di=d^-1, w=A.B.di, u, v such that au+bv=1 and u in A.di, v in B.di.
- * Assume A, B non-zero, but a or b can be zero (not both) */
-static GEN
-nfbezout(GEN nf,GEN a,GEN b, GEN A,GEN B, GEN *pu,GEN *pv,GEN *pw,GEN *pdi)
-{
-  GEN w, u,v,uv, d, di, aA, bB;
-
-  if (isintzero(a)) return zero_nfbezout(nf,NULL,b,A,B,pu,pv,pw,pdi);
-  if (isintzero(b)) return zero_nfbezout(nf,NULL,a,B,A,pv,pu,pw,pdi);
-
-  if (a != gen_1) /* frequently called with a = gen_1 */
-  {
-    a = nf_to_scalar_or_basis(nf,a);
-    if (isint1(a)) a = gen_1;
-  }
-  aA = (a == gen_1)? A: idealmul(nf,a,A);
-  bB = idealmul(nf,b,B);
-  d = idealadd(nf,aA,bB);
-  if (gequal(aA, d)) return zero_nfbezout(nf,aA, a,B,A,pv,pu,pw,pdi);
-  if (gequal(bB, d)) return zero_nfbezout(nf,bB, b,A,B,pu,pv,pw,pdi);
-  /* general case is slow */
-  di = idealinv_HNF(nf,d);
-  w = idealmul(nf,aA,di); /* integral */
-  uv = idealaddtoone(nf, w, idealmul(nf,bB,di));
-  w = idealmul(nf,w,B);
-  u = gel(uv,1);
-  v = nfdiv(nf,gel(uv,2),b);
-  if (a != gen_1)
-  {
-    GEN inva = nfinv(nf, a);
-    u =  nfmul(nf,u,inva);
-    w = idealmul(nf, inva, w); /* AB/d */
-  }
-  *pu = u;
-  *pv = v;
-  *pw = w;
-  *pdi = di; return d;
-}
-/* v a vector of ideals, simplify in place the ones generated by elts of Q */
-static void
-idV_simplify(GEN v)
-{
-  long i, l = lg(v);
-  for (i = 1; i < l; i++)
-  {
-    GEN M = gel(v,i);
-    if (typ(M)==t_MAT && RgM_isscalar(M,NULL)) gel(v,i) = Q_abs(gcoeff(M,1,1));
-  }
-}
-/* Given a torsion-free module x outputs a pseudo-basis for x in HNF */
-GEN
-nfhnf(GEN nf, GEN x)
-{
-  long i, j, def, idef, m, n;
-  pari_sp av0 = avma, av, lim;
-  GEN y, A, I, J;
-
-  nf = checknf(nf);
-  check_ZKmodule(x, "nfhnf");
-  A = gel(x,1); RgM_dimensions(A, &m, &n);
-  I = gel(x,2);
-  if (!n) return gcopy(x);
-  idef = (n < m)? m-n : 0;
-  av = avma; lim = stack_lim(av, 2);
-  A = RgM_to_nfM(nf,A);
-  I = leafcopy(I);
-  J = zerovec(n); def = n;
-  for (i=m; i>idef; i--)
-  {
-    GEN d, di = NULL;
-
-    j=def; while (j>=1 && isintzero(gcoeff(A,i,j))) j--;
-    if (!j)
-    { /* no pivot on line i */
-      if (idef) idef--;
-      continue;
-    }
-    if (j==def) j--;
-    else {
-      swap(gel(A,j), gel(A,def));
-      swap(gel(I,j), gel(I,def));
-    }
-    for (  ; j; j--)
-    {
-      GEN a,b, u,v,w, S, T, S0, T0 = gel(A,j);
-      b = gel(T0,i); if (isintzero(b)) continue;
-
-      S0 = gel(A,def); a = gel(S0,i);
-      d = nfbezout(nf, a,b, gel(I,def),gel(I,j), &u,&v,&w,&di);
-      S = colcomb(nf, u,v, S0,T0);
-      T = colcomb(nf, a,gneg(b), T0,S0);
-      gel(A,def) = S; gel(A,j) = T;
-      gel(I,def) = d; gel(I,j) = w;
-    }
-    y = gcoeff(A,i,def);
-    if (!isint1(y))
-    {
-      gel(A,def) = nfC_nf_mul(nf, gel(A,def), nfinv(nf,y));
-      gel(I,def) = idealmul(nf, y, gel(I,def));
-      di = NULL;
-    }
-    if (!di) di = idealinv(nf,gel(I,def));
-    d = gel(I,def);
-    gel(J,def) = di;
-    for (j=def+1; j<=n; j++)
-    {
-      GEN c = gcoeff(A,i,j); if (isintzero(c)) continue;
-      c = element_close(nf, c, idealmul(nf,d,gel(J,j)));
-      gel(A,j) = colcomb1(nf, gneg(c), gel(A,j),gel(A,def));
-    }
-    def--;
-    if (low_stack(lim, stack_lim(av,2)))
-    {
-      if(DEBUGMEM>1) pari_warn(warnmem,"nfhnf, i = %ld", i);
-      gerepileall(av,3, &A,&I,&J);
-    }
-  }
-  n -= def;
-  A += def; A[0] = evaltyp(t_MAT)|evallg(n+1);
-  I += def; I[0] = evaltyp(t_VEC)|evallg(n+1);
-  idV_simplify(I);
-  return gerepilecopy(av0, mkvec2(A, I));
-}
-
-static long
-RgV_find_denom(GEN x)
-{
-  long l = lg(x), i = 1;
-  while (i < l && Q_denom(gel(x,i)) == gen_1) i++;
-  return i;
-}
-/* A torsion module M over Z_K will be given by a row vector [A,I,J] with
- * three components. I=[b_1,...,b_n] is a row vector of n fractional ideals
- * given in HNF, J=[a_1,...,a_n] is a row vector of n fractional ideals in
- * HNF. A is an nxn matrix (same n) such that if A_j is the j-th column of A
- * and e_n is the canonical basis of K^n, then
- * M=(b_1e_1+...+b_ne_n)/(a_1A_1+...a_nA_n) */
-
-/* x=[A,I,J] a torsion module as above. Output the
- * smith normal form as K=[c_1,...,c_n] such that x = Z_K/c_1+...+Z_K/c_n */
-GEN
-nfsnf(GEN nf, GEN x)
-{
-  long i, j, k, l, c, n, m, N;
-  pari_sp av, lim;
-  GEN z,u,v,w,d,dinv,A,I,J;
-
-  nf = checknf(nf); N = nf_get_degree(nf);
-  if (typ(x)!=t_VEC || lg(x)!=4) pari_err_TYPE("nfsnf",x);
-  A = gel(x,1);
-  I = gel(x,2);
-  J = gel(x,3);
-  if (typ(A)!=t_MAT) pari_err_TYPE("nfsnf",A);
-  n = lg(A)-1;
-  if (typ(I)!=t_VEC) pari_err_TYPE("nfsnf",I);
-  if (typ(J)!=t_VEC) pari_err_TYPE("nfsnf",J);
-  if (lg(I)!=n+1 || lg(J)!=n+1) pari_err_DIM("nfsnf");
-  RgM_dimensions(A, &m, &n);
-  if (!n || n != m) pari_err_IMPL("nfsnf for empty or non square matrices");
-
-  av = avma; lim = stack_lim(av,1);
-  A = RgM_to_nfM(nf, A);
-  I = leafcopy(I);
-  J = leafcopy(J); for (i = 1; i <= n; i++) gel(J,i) = idealinv(nf, gel(J,i));
-  for (i=n; i>=2; i--)
-  {
-    do
-    {
-      GEN Aii, a, b, db;
-      c = 0;
-      for (j=i-1; j>=1; j--)
-      {
-        GEN S, T, S0, T0 = gel(A,j);
-        b = gel(T0,i); if (gequal0(b)) continue;
-
-        S0 = gel(A,i); a = gel(S0,i);
-        d = nfbezout(nf, a,b, gel(J,i),gel(J,j), &u,&v,&w,&dinv);
-        S = colcomb(nf, u,v, S0,T0);
-        T = colcomb(nf, a,gneg(b), T0,S0);
-        gel(A,i) = S; gel(A,j) = T;
-        gel(J,i) = d; gel(J,j) = w;
-      }
-      for (j=i-1; j>=1; j--)
-      {
-        GEN ri, rj;
-        b = gcoeff(A,j,i); if (gequal0(b)) continue;
-
-        a = gcoeff(A,i,i);
-        d = nfbezout(nf, a,b, gel(I,i),gel(I,j), &u,&v,&w,&dinv);
-        ri = rowcomb(nf, u,v,       i,j, A, i);
-        rj = rowcomb(nf, a,gneg(b), j,i, A, i);
-        for (k=1; k<=i; k++) {
-          gcoeff(A,j,k) = gel(rj,k);
-          gcoeff(A,i,k) = gel(ri,k);
-        }
-        gel(I,i) = d; gel(I,j) = w; c = 1;
-      }
-      if (c) continue;
-
-      Aii = gcoeff(A,i,i); if (gequal0(Aii)) break;
-      gel(J,i) = idealmul(nf, gel(J,i), Aii);
-      gcoeff(A,i,i) = gen_1;
-      b = idealmul(nf,gel(J,i),gel(I,i));
-      b = Q_remove_denom(b, &db);
-      for (k=1; k<i; k++)
-        for (l=1; l<i; l++)
-        {
-          GEN D, p1, p2, p3, Akl = gcoeff(A,k,l);
-          if (gequal0(Akl)) continue;
-
-          p1 = idealmul(nf,Akl,gel(J,l));
-          p3 = idealmul(nf, p1, gel(I,k));
-          if (db) p3 = RgM_Rg_mul(p3, db);
-          if (RgM_is_ZM(p3) && hnfdivide(b, p3)) continue;
-
-          /* find d in D = I[k]/I[i] not in J[i]/(a[k,l] J[l]) */
-          D = idealdiv(nf,gel(I,k),gel(I,i));
-          p2 = idealdiv(nf,gel(J,i), p1);
-          l = RgV_find_denom( RgM_solve(p2, D) );
-          if (l>N) pari_err_BUG("nfsnf");
-          p1 = element_mulvecrow(nf,gel(D,l),A,k,i);
-          for (l=1; l<=i; l++) gcoeff(A,i,l) = gadd(gcoeff(A,i,l),gel(p1,l));
-
-          k = i; c = 1; break;
-        }
-      if (low_stack(lim, stack_lim(av,1)))
-      {
-        if(DEBUGMEM>1) pari_warn(warnmem,"nfsnf");
-        gerepileall(av,3, &A,&I,&J);
-      }
-    }
-    while (c);
-  }
-  gel(J,1) = idealmul(nf, gcoeff(A,1,1), gel(J,1));
-  z = cgetg(n+1,t_VEC);
-  for (i=1; i<=n; i++) gel(z,i) = idealmul(nf,gel(I,i),gel(J,i));
-  return gerepileupto(av, z);
-}
-
 GEN
 nfmulmodpr(GEN nf, GEN x, GEN y, GEN modpr)
 {
@@ -2887,224 +2602,3 @@ nfsolvemodpr(GEN nf, GEN a, GEN b, GEN pr)
   }
   return gerepilecopy(av, a);
 }
-
-/* Given a pseudo-basis x, outputs a multiple of its ideal determinant */
-GEN
-nfdetint(GEN nf, GEN x)
-{
-  GEN pass,c,v,det1,piv,pivprec,vi,p1,A,I,id,idprod;
-  long i, j, k, rg, n, m, m1, cm=0, N;
-  pari_sp av = avma, av1, lim;
-
-  nf = checknf(nf); N = nf_get_degree(nf);
-  check_ZKmodule(x, "nfdetint");
-  A = gel(x,1);
-  I = gel(x,2);
-  n = lg(A)-1; if (!n) return gen_1;
-
-  m1 = lgcols(A); m = m1-1;
-  id = matid(N);
-  c = new_chunk(m1); for (k=1; k<=m; k++) c[k] = 0;
-  piv = pivprec = gen_1;
-
-  av1 = avma; lim = stack_lim(av1,1);
-  det1 = idprod = gen_0; /* dummy for gerepileall */
-  pass = cgetg(m1,t_MAT);
-  v = cgetg(m1,t_COL);
-  for (j=1; j<=m; j++)
-  {
-    gel(pass,j) = zerocol(m);
-    gel(v,j) = gen_0; /* dummy */
-  }
-  for (rg=0,k=1; k<=n; k++)
-  {
-    long t = 0;
-    for (i=1; i<=m; i++)
-      if (!c[i])
-      {
-        vi=nfmul(nf,piv,gcoeff(A,i,k));
-        for (j=1; j<=m; j++)
-          if (c[j]) vi=gadd(vi,nfmul(nf,gcoeff(pass,i,j),gcoeff(A,j,k)));
-        gel(v,i) = vi; if (!t && !gequal0(vi)) t=i;
-      }
-    if (t)
-    {
-      pivprec = piv;
-      if (rg == m-1)
-      {
-        if (!cm)
-        {
-          cm=1; idprod = id;
-          for (i=1; i<=m; i++)
-            if (i!=t)
-              idprod = (idprod==id)? gel(I,c[i])
-                                   : idealmul(nf,idprod,gel(I,c[i]));
-        }
-        p1 = idealmul(nf,gel(v,t),gel(I,k)); c[t]=0;
-        det1 = (typ(det1)==t_INT)? p1: idealadd(nf,p1,det1);
-      }
-      else
-      {
-        rg++; piv=gel(v,t); c[t]=k;
-        for (i=1; i<=m; i++)
-          if (!c[i])
-          {
-            for (j=1; j<=m; j++)
-              if (c[j] && j!=t)
-              {
-                p1 = gsub(nfmul(nf,piv,gcoeff(pass,i,j)),
-                          nfmul(nf,gel(v,i),gcoeff(pass,t,j)));
-                gcoeff(pass,i,j) = rg>1? nfdiv(nf,p1,pivprec)
-                                       : p1;
-              }
-            gcoeff(pass,i,t) = gneg(gel(v,i));
-          }
-      }
-    }
-    if (low_stack(lim, stack_lim(av1,1)))
-    {
-      if(DEBUGMEM>1) pari_warn(warnmem,"nfdetint");
-      gerepileall(av1,6, &det1,&piv,&pivprec,&pass,&v,&idprod);
-    }
-  }
-  if (!cm) { avma = av; return cgetg(1,t_MAT); }
-  return gerepileupto(av, idealmul(nf,idprod,det1));
-}
-
-/* reduce in place components of x[1..lim] mod D (destroy x). D in HNF */
-static void
-nfcleanmod(GEN nf, GEN x, long lim, GEN D)
-{
-  long i;
-  GEN DZ, DZ2, dD;
-  D = Q_remove_denom(D, &dD);
-  if (dD) x = RgC_Rg_mul(x, dD);
-  DZ = gcoeff(D,1,1);
-  DZ2 = shifti(DZ,-1);
-  for (i=1; i<=lim; i++) {
-    GEN c = gel(x,i);
-    c = nf_to_scalar_or_basis(nf, c);
-    switch(typ(c)) /* c = centermod(c, D) */
-    {
-      case t_INT:
-        if (!signe(c)) break;
-        c = centermodii(c, DZ, DZ2);
-        if (dD) c = gred_frac2(c,dD);
-        break;
-      case t_FRAC: {
-        GEN dc = gel(c,2), nc = gel(c,1), N = mulii(DZ, dc);
-        c = centermodii(nc, N, shifti(N,-1));
-        c = gred_frac2(c, dD ? mulii(dc,dD): dc);
-        break;
-      }
-      case t_COL: {
-        GEN dc;
-        c = Q_remove_denom(c, &dc);
-        c = ZC_hnfrem(c, dc? ZM_Z_mul(D,dc): D);
-        if (ZV_isscalar(c))
-        {
-          c = gel(c,1);
-          if (dD) c = gred_frac2(c,dD);
-        }
-        else
-          if (dD) c = RgC_Rg_div(c, dD);
-        break;
-      }
-    }
-    gel(x,i) = c;
-  }
-}
-
-GEN
-nfhnfmod(GEN nf, GEN x, GEN detmat)
-{
-  long li, co, i, j, def, ldef;
-  pari_sp av0=avma, av, lim;
-  GEN dA, dI, d0, w, p1, d, u, v, A, I, J, di;
-
-  nf = checknf(nf);
-  check_ZKmodule(x, "nfhnfmod");
-  A = gel(x,1);
-  I = gel(x,2);
-  co = lg(A); if (co==1) return cgetg(1,t_MAT);
-
-  li = lgcols(A);
-  if (typ(detmat)!=t_MAT) detmat = idealhnf_shallow(nf, detmat);
-  detmat = Q_remove_denom(detmat, NULL);
-  RgM_check_ZM(detmat, "nfhnfmod");
-
-  av = avma; lim = stack_lim(av,2);
-  A = RgM_to_nfM(nf, A);
-  A = Q_remove_denom(A, &dA);
-  I = Q_remove_denom(leafcopy(I), &dI);
-  dA = mul_denom(dA,dI);
-  if (dA) detmat = ZM_Z_mul(detmat, powiu(dA, minss(li,co)));
-
-  def = co; ldef = (li>co)? li-co+1: 1;
-  for (i=li-1; i>=ldef; i--)
-  {
-    def--; j=def; while (j>=1 && isintzero(gcoeff(A,i,j))) j--;
-    if (!j) continue;
-    if (j==def) j--;
-    else {
-      swap(gel(A,j), gel(A,def));
-      swap(gel(I,j), gel(I,def));
-    }
-    for (  ; j; j--)
-    {
-      GEN a, b, S, T, S0, T0 = gel(A,j);
-      b = gel(T0,i); if (isintzero(b)) continue;
-
-      S0 = gel(A,def); a = gel(S0,i);
-      d = nfbezout(nf, a,b, gel(I,def),gel(I,j), &u,&v,&w,&di);
-      S = colcomb(nf, u,v, S0,T0);
-      T = colcomb(nf, a,gneg(b), T0,S0);
-      if (u != gen_0 && v != gen_0) /* already reduced otherwise */
-        nfcleanmod(nf, S, i, idealmul(nf,detmat,di));
-      nfcleanmod(nf, T, i, idealdiv(nf,detmat,w));
-      gel(A,def) = S; gel(A,j) = T;
-      gel(I,def) = d; gel(I,j) = w;
-    }
-    if (low_stack(lim, stack_lim(av,2)))
-    {
-      if(DEBUGMEM>1) pari_warn(warnmem,"[1]: nfhnfmod, i = %ld", i);
-      gerepileall(av,dA? 4: 3, &A,&I,&detmat,&dA);
-    }
-  }
-  def--; d0 = detmat;
-  A += def; A[0] = evaltyp(t_MAT)|evallg(li);
-  I += def; I[0] = evaltyp(t_VEC)|evallg(li);
-  J = cgetg(li,t_VEC);
-  for (i=li-1; i>=1; i--)
-  {
-    GEN b = gcoeff(A,i,i);
-    d = nfbezout(nf, gen_1,b, d0,gel(I,i), &u,&v,&w,&di);
-    p1 = nfC_nf_mul(nf,gel(A,i),v);
-    if (i > 1)
-    {
-      d0 = idealmul(nf,d0,di);
-      nfcleanmod(nf, p1, i, d0);
-    }
-    gel(A,i) = p1; gel(p1,i) = gen_1;
-    gel(I,i) = d;
-    gel(J,i) = di;
-  }
-  for (i=li-2; i>=1; i--)
-  {
-    d = gel(I,i);
-    for (j=i+1; j<li; j++)
-    {
-      GEN c = gcoeff(A,i,j); if (isintzero(c)) continue;
-      c = element_close(nf, c, idealmul(nf,d,gel(J,j)));
-      gel(A,j) = colcomb1(nf, gneg(c), gel(A,j),gel(A,i));
-    }
-    if (low_stack(lim, stack_lim(av,2)))
-    {
-      if(DEBUGMEM>1) pari_warn(warnmem,"[2]: nfhnfmod, i = %ld", i);
-      gerepileall(av,dA? 4: 3, &A,&I,&J,&dA);
-    }
-  }
-  idV_simplify(I);
-  if (dA) I = gdiv(I,dA);
-  return gerepilecopy(av0, mkvec2(A, I));
-}
diff --git a/src/basemath/base5.c b/src/basemath/base5.c
index c8db641..42c6c91 100644
--- a/src/basemath/base5.c
+++ b/src/basemath/base5.c
@@ -13,8 +13,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 
 /*******************************************************************/
 /*                                                                 */
-/*                       BASIC NF OPERATIONS                       */
-/*                          (continued 2)                          */
+/*                     RNF STRUCTURE AND OPERATIONS                */
 /*                                                                 */
 /*******************************************************************/
 #include "pari.h"
@@ -152,7 +151,6 @@ END:
   return gerepilecopy(av, eltabstorel(rnf_get_map(rnf), x));
 }
 
-
 /* x a t_VEC of rnf elements in 'alg' form (t_POL). Assume maximal rank or 0 */
 static GEN
 modulereltoabs(GEN rnf, GEN x)
@@ -210,37 +208,26 @@ rnf_basM(GEN rnf)
   return M;
 }
 
-/* only fill in nf[1,3,4,7,8,9] */
-static GEN
-makenfabs(GEN rnf)
-{
-  GEN nf = rnf_get_nf(rnf), pol = rnf_get_polabs(rnf), NF = zerovec(9);
-  GEN M = rnf_basM(rnf);
-  gel(NF,1) = pol;
-  gel(NF,3) = mulii(powiu(nf_get_disc(nf), rnf_get_degree(rnf)),
-                    idealnorm(nf, rnf_get_disc(rnf)));
-  nf_set_multable(NF, M, NULL);
-  gel(NF,4) = get_nfindex(nf_get_zk(NF));
-  return NF;
-}
+const long NFABS = 1;
 
 static GEN
-makenorms(GEN rnf)
+rnfnfabs(GEN rnf, long prec)
 {
-  GEN f = rnf_get_index(rnf);
-  return typ(f) == t_INT? gen_1: RgM_det_triangular(f);
+  GEN nf, pol, bas;
+  if ((nf = obj_check(rnf,NFABS)))
+  {
+    if (nf_get_prec(nf) < prec) nf = nfnewprec_shallow(nf,prec);
+    return nf;
+  }
+  nf = rnf_get_nf(rnf);
+  pol = rnf_get_polabs(rnf);
+  bas = modulereltoabs(rnf, rnf_get_zk(rnf));
+  return nfinit(mkvec2(pol, bas), nf_get_prec(nf));
 }
 
-#define NFABS 1
-#define NORMS 2
-GEN
-check_and_build_nfabs(GEN rnf) {
-  return obj_checkbuild(rnf, NFABS, &makenfabs);
-}
 GEN
-check_and_build_norms(GEN rnf) {
-  return obj_checkbuild(rnf, NORMS, &makenorms);
-}
+check_and_build_nfabs(GEN rnf, long prec)
+{ return obj_checkbuild_prec(rnf, NFABS, &rnfnfabs, &nf_get_prec, prec); }
 
 void
 nf_nfzk(GEN nf, GEN rnfeq, GEN *zknf, GEN *czknf)
@@ -262,7 +249,7 @@ rnfinit(GEN nf, GEN polrel)
   gel(bas,1) = lift_if_rational( RgM_to_RgXV(B,varn(polrel)) );
   rnfeq = nf_rnfeq(nf,polrel);
   nf_nfzk(nf, rnfeq, &basnf, &cobasnf);
-  rnf = cgetg(13, t_VEC);
+  rnf = obj_init(11, 1);
   gel(rnf,1) = polrel;
   gel(rnf,2) = mkvec2(basnf, cobasnf);
   gel(rnf,3) = mkvec2(D, d);
@@ -270,11 +257,10 @@ rnfinit(GEN nf, GEN polrel)
   gel(rnf,5) = cgetg(1, t_VEC); /* dummy */
   gel(rnf,6) = cgetg(1, t_VEC); /* dummy */
   gel(rnf,7) = bas;
-  gel(rnf,8) = lift_if_rational( RgM_inv(B) );
-  gel(rnf,9) = cgetg(1,t_VEC); /* dummy */
+  gel(rnf,8) = lift_if_rational( RgM_inv_upper(B) );
+  gel(rnf,9) = typ(f) == t_INT? gen_1: RgM_det_triangular(f);
   gel(rnf,10)= nf;
   gel(rnf,11)= rnfeq;
-  gel(rnf,12)= zerovec(2);
   return gerepilecopy(av, rnf);
 }
 
@@ -440,7 +426,7 @@ rnfidealnormabs(GEN rnf, GEN id)
   GEN nf, z = gel(rnfidealhnf(rnf,id), 2);
   if (lg(z) == 1) return gen_0;
   nf = rnf_get_nf(rnf); z = prodidnorm(nf, z);
-  return gerepileupto(av, gmul(z, check_and_build_norms(rnf)));
+  return gerepileupto(av, gmul(z, gel(rnf,9)));
 }
 
 GEN
@@ -519,7 +505,7 @@ rnfidealtwoelement(GEN rnf, GEN x)
   GEN y, cy, z, NF;
 
   y = rnfidealreltoabs(rnf,x);
-  NF = check_and_build_nfabs(rnf);
+  NF = check_and_build_nfabs(rnf, nf_get_prec(rnf_get_nf(rnf)));
   y = matalgtobasis(NF, y); settyp(y, t_MAT);
   y = Q_primitive_part(y, &cy);
   y = ZM_hnf(y);
@@ -549,18 +535,6 @@ rnfidealmul(GEN rnf,GEN x,GEN y)
   return gerepileupto(av, nfhnf(nf,z));
 }
 
-int
-nfissquarefree(GEN nf, GEN x)
-{
-  pari_sp av = avma;
-  GEN g, y = RgX_deriv(x);
-  if (RgX_is_rational(x))
-    g = QX_gcd(x, y);
-  else
-    g = nfgcd(x, y, nf, NULL);
-  avma = av; return (degpol(g) == 0);
-}
-
 GEN
 rnfequationall(GEN A, GEN B, long *pk, GEN *pLPRS)
 {
@@ -624,6 +598,11 @@ nf_rnfeqsimple(GEN nf, GEN relpol)
   return mkvec5(pol,gen_0/*dummy*/,stoi(sa),get_nfpol(nf, &junk),relpol);
 }
 
+/*******************************************************************/
+/*                                                                 */
+/*                            RELATIVE LLL                         */
+/*                                                                 */
+/*******************************************************************/
 static GEN
 nftau(long r1, GEN x)
 {
@@ -847,7 +826,7 @@ rel_T2(GEN nf, GEN pol, long lx, long prec)
 GEN
 rnflllgram(GEN nf, GEN pol, GEN order,long prec)
 {
-  pari_sp av = avma, lim = stack_lim(av,2);
+  pari_sp av = avma;
   long j, k, l, kmax, r1, lx, count = 0;
   GEN M, I, h, H, mth, MC, MPOL, MCS, B, mu;
   const long alpha = 10, MAX_COUNT = 4;
@@ -920,7 +899,7 @@ PRECPB:
         if (!RED(k, l, h, mu, MC, nf, I, &Ik_inv)) goto PRECPB;
       k++;
     }
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"rnflllgram");
       gerepileall(av, H?10:9, &nf,&mth,&h,&MPOL,&B,&MC,&MCS,&mu,&I,&H);
@@ -990,3 +969,639 @@ rnfpolred(GEN nf, GEN pol, long prec)
   }
   return gerepilecopy(av,w);
 }
+
+/*******************************************************************/
+/*                                                                 */
+/*                  LINEAR ALGEBRA OVER Z_K  (HNF,SNF)             */
+/*                                                                 */
+/*******************************************************************/
+/* A torsion-free module M over Z_K is given by [A,I].
+ * I=[a_1,...,a_k] is a row vector of k fractional ideals given in HNF.
+ * A is an n x k matrix (same k) such that if A_j is the j-th column of A then
+ * M=a_1 A_1+...+a_k A_k. We say that [A,I] is a pseudo-basis if k=n */
+
+/* Given an element x and an ideal I in HNF, gives an r such that x-r is in H
+ * and r is small */
+GEN
+nfreduce(GEN nf, GEN x, GEN I)
+{
+  pari_sp av = avma;
+  GEN aI;
+  x = nf_to_scalar_or_basis(checknf(nf), x);
+  if (idealtyp(&I,&aI) != id_MAT || lg(I)==1) pari_err_TYPE("nfreduce",I);
+  if (typ(x) != t_COL) x = scalarcol( gmod(x, gcoeff(I,1,1)), lg(I)-1 );
+  else x = reducemodinvertible(x, I);
+  return gerepileupto(av, x);
+}
+/* Given an element x and an ideal in HNF, gives an a in ideal such that
+ * x-a is small. No checks */
+static GEN
+element_close(GEN nf, GEN x, GEN ideal)
+{
+  pari_sp av = avma;
+  GEN y = gcoeff(ideal,1,1);
+  x = nf_to_scalar_or_basis(nf, x);
+  if (typ(y) == t_INT && is_pm1(y)) return ground(x);
+  if (typ(x) == t_COL)
+    x = closemodinvertible(x, ideal);
+  else
+    x = gmul(y, gdivround(x,y));
+  return gerepileupto(av, x);
+}
+
+/* A + v B */
+static GEN
+colcomb1(GEN nf, GEN v, GEN A, GEN B)
+{
+  if (isintzero(v)) return A;
+  return RgC_to_nfC(nf, RgC_add(A, nfC_nf_mul(nf,B,v)));
+}
+/* u A + v B */
+static GEN
+colcomb(GEN nf, GEN u, GEN v, GEN A, GEN B)
+{
+  if (isintzero(u)) return nfC_nf_mul(nf,B,v);
+  if (u != gen_1) A = nfC_nf_mul(nf,A,u);
+  return colcomb1(nf, v, A, B);
+}
+
+/* return m[i,1..lim] * x */
+static GEN
+element_mulvecrow(GEN nf, GEN x, GEN m, long i, long lim)
+{
+  long j, l = minss(lg(m), lim+1);
+  GEN dx, y = cgetg(l, t_VEC);
+  x = nf_to_scalar_or_basis(nf, x);
+  if (typ(x) == t_COL)
+  {
+    x = zk_multable(nf, Q_remove_denom(x, &dx));
+    for (j=1; j<l; j++)
+    {
+      GEN t = gcoeff(m,i,j);
+      if (!isintzero(t))
+      {
+        if (typ(t) == t_COL)
+          t = RgM_RgC_mul(x, t);
+        else
+          t = RgC_Rg_mul(gel(x,1), t);
+        if (dx) t = gdiv(t, dx);
+        t = nf_to_scalar_or_basis(nf,t);
+      }
+      gel(y,j) = t;
+    }
+  }
+  else
+  {
+    for (j=1; j<l; j++) gel(y,j) = gmul(x, gcoeff(m,i,j));
+  }
+  return y;
+}
+
+/* u Z[s,] + v Z[t,], limitied to the first lim entries */
+static GEN
+rowcomb(GEN nf, GEN u, GEN v, long s, long t, GEN Z, long lim)
+{
+  GEN z;
+  if (gequal0(u))
+    z = element_mulvecrow(nf,v,Z,t, lim);
+  else
+  {
+    z = element_mulvecrow(nf,u,Z,s, lim);
+    if (!gequal0(v)) z = gadd(z, element_mulvecrow(nf,v,Z,t, lim));
+  }
+  return z;
+}
+
+/* nfbezout(0,b,A,B). Either bB = NULL or b*B */
+static GEN
+zero_nfbezout(GEN nf,GEN bB, GEN b, GEN A,GEN B,GEN *u,GEN *v,GEN *w,GEN *di)
+{
+  GEN d;
+  if (isint1(b))
+  {
+    *v = gen_1;
+    *w = A;
+    d = B;
+    *di = idealinv(nf,d);
+  }
+  else
+  {
+    *v = nfinv(nf,b);
+    *w = idealmul(nf,A,*v);
+    d = bB? bB: idealmul(nf,b,B);
+    *di = idealinv_HNF(nf,d);
+  }
+  *u = gen_0; return d;
+}
+
+/* Given elements a,b and ideals A, B, outputs d = a.A+b.B and gives
+ * di=d^-1, w=A.B.di, u, v such that au+bv=1 and u in A.di, v in B.di.
+ * Assume A, B non-zero, but a or b can be zero (not both) */
+static GEN
+nfbezout(GEN nf,GEN a,GEN b, GEN A,GEN B, GEN *pu,GEN *pv,GEN *pw,GEN *pdi)
+{
+  GEN w, u,v,uv, d, di, aA, bB;
+
+  if (isintzero(a)) return zero_nfbezout(nf,NULL,b,A,B,pu,pv,pw,pdi);
+  if (isintzero(b)) return zero_nfbezout(nf,NULL,a,B,A,pv,pu,pw,pdi);
+
+  if (a != gen_1) /* frequently called with a = gen_1 */
+  {
+    a = nf_to_scalar_or_basis(nf,a);
+    if (isint1(a)) a = gen_1;
+  }
+  aA = (a == gen_1)? A: idealmul(nf,a,A);
+  bB = idealmul(nf,b,B);
+  d = idealadd(nf,aA,bB);
+  if (gequal(aA, d)) return zero_nfbezout(nf,aA, a,B,A,pv,pu,pw,pdi);
+  if (gequal(bB, d)) return zero_nfbezout(nf,bB, b,A,B,pu,pv,pw,pdi);
+  /* general case is slow */
+  di = idealinv_HNF(nf,d);
+  w = idealmul(nf,aA,di); /* integral */
+  uv = idealaddtoone(nf, w, idealmul(nf,bB,di));
+  w = idealmul(nf,w,B);
+  u = gel(uv,1);
+  v = nfdiv(nf,gel(uv,2),b);
+  if (a != gen_1)
+  {
+    GEN inva = nfinv(nf, a);
+    u =  nfmul(nf,u,inva);
+    w = idealmul(nf, inva, w); /* AB/d */
+  }
+  *pu = u;
+  *pv = v;
+  *pw = w;
+  *pdi = di; return d;
+}
+/* v a vector of ideals, simplify in place the ones generated by elts of Q */
+static void
+idV_simplify(GEN v)
+{
+  long i, l = lg(v);
+  for (i = 1; i < l; i++)
+  {
+    GEN M = gel(v,i);
+    if (typ(M)==t_MAT && RgM_isscalar(M,NULL))
+      gel(v,i) = Q_abs_shallow(gcoeff(M,1,1));
+  }
+}
+/* Given a torsion-free module x outputs a pseudo-basis for x in HNF */
+GEN
+nfhnf0(GEN nf, GEN x, long flag)
+{
+  long i, j, def, idef, m, n;
+  pari_sp av0 = avma, av;
+  GEN y, A, I, J, U;
+
+  nf = checknf(nf);
+  check_ZKmodule(x, "nfhnf");
+  A = gel(x,1); RgM_dimensions(A, &m, &n);
+  I = gel(x,2);
+  if (!n) {
+    if (!flag) return gcopy(x);
+    retmkvec2(gcopy(x), cgetg(1,t_MAT));
+  }
+  U = flag? matid(n): NULL;
+  idef = (n < m)? m-n : 0;
+  av = avma;
+  A = RgM_to_nfM(nf,A);
+  I = leafcopy(I);
+  J = zerovec(n); def = n;
+  for (i=m; i>idef; i--)
+  {
+    GEN d, di = NULL;
+
+    j=def; while (j>=1 && isintzero(gcoeff(A,i,j))) j--;
+    if (!j)
+    { /* no pivot on line i */
+      if (idef) idef--;
+      continue;
+    }
+    if (j==def) j--;
+    else {
+      swap(gel(A,j), gel(A,def));
+      swap(gel(I,j), gel(I,def));
+      if (U) swap(gel(U,j), gel(U,def));
+    }
+    for (  ; j; j--)
+    {
+      GEN a,b, u,v,w, S, T, S0, T0 = gel(A,j);
+      b = gel(T0,i); if (isintzero(b)) continue;
+
+      S0 = gel(A,def); a = gel(S0,i);
+      d = nfbezout(nf, a,b, gel(I,def),gel(I,j), &u,&v,&w,&di);
+      S = colcomb(nf, u,v, S0,T0);
+      T = colcomb(nf, a,gneg(b), T0,S0);
+      gel(A,def) = S; gel(A,j) = T;
+      gel(I,def) = d; gel(I,j) = w;
+      if (U)
+      {
+        S0 = gel(U,def);
+        T0 = gel(U,j);
+        gel(U,def) = colcomb(nf, u,v, S0,T0);
+        gel(U,j) = colcomb(nf, a,gneg(b), T0,S0);
+      }
+    }
+    y = gcoeff(A,i,def);
+    if (!isint1(y))
+    {
+      GEN yi = nfinv(nf,y);
+      gel(A,def) = nfC_nf_mul(nf, gel(A,def), yi);
+      gel(I,def) = idealmul(nf, y, gel(I,def));
+      if (U) gel(U,def) = nfC_nf_mul(nf, gel(U,def), yi);
+      di = NULL;
+    }
+    if (!di) di = idealinv(nf,gel(I,def));
+    d = gel(I,def);
+    gel(J,def) = di;
+    for (j=def+1; j<=n; j++)
+    {
+      GEN mc, c = gcoeff(A,i,j); if (isintzero(c)) continue;
+      c = element_close(nf, c, idealmul(nf,d,gel(J,j)));
+      mc = gneg(c);
+      gel(A,j) = colcomb1(nf, mc, gel(A,j),gel(A,def));
+      if (U) gel(U,j) = colcomb1(nf, mc, gel(U,j),gel(U,def));
+    }
+    def--;
+    if (gc_needed(av,2))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"nfhnf, i = %ld", i);
+      gerepileall(av,U?4:3, &A,&I,&J,&U);
+    }
+  }
+  n -= def;
+  A += def; A[0] = evaltyp(t_MAT)|evallg(n+1);
+  I += def; I[0] = evaltyp(t_VEC)|evallg(n+1);
+  idV_simplify(I);
+  x = mkvec2(A,I);
+  if (U) x = mkvec2(x,U);
+  return gerepilecopy(av0, x);
+}
+
+GEN
+nfhnf(GEN nf, GEN x) { return nfhnf0(nf, x, 0); }
+
+static GEN
+RgV_find_denom(GEN x)
+{
+  long i, l = lg(x);
+  for (i = 1; i < l; i++)
+    if (Q_denom(gel(x,i)) != gen_1) return gel(x,i);
+  return NULL;
+}
+/* A torsion module M over Z_K will be given by a row vector [A,I,J] with
+ * three components. I=[b_1,...,b_n] is a row vector of n fractional ideals
+ * given in HNF, J=[a_1,...,a_n] is a row vector of n fractional ideals in
+ * HNF. A is an nxn matrix (same n) such that if A_j is the j-th column of A
+ * and e_n is the canonical basis of K^n, then
+ * M=(b_1e_1+...+b_ne_n)/(a_1A_1+...a_nA_n) */
+
+/* x=[A,I,J] a torsion module as above. Output the
+ * smith normal form as K=[c_1,...,c_n] such that x = Z_K/c_1+...+Z_K/c_n */
+GEN
+nfsnf0(GEN nf, GEN x, long flag)
+{
+  long i, j, k, l, n, m;
+  pari_sp av;
+  GEN z,u,v,w,d,dinv,A,I,J, U,V;
+
+  nf = checknf(nf);
+  if (typ(x)!=t_VEC || lg(x)!=4) pari_err_TYPE("nfsnf",x);
+  A = gel(x,1);
+  I = gel(x,2);
+  J = gel(x,3);
+  if (typ(A)!=t_MAT) pari_err_TYPE("nfsnf",A);
+  n = lg(A)-1;
+  if (typ(I)!=t_VEC) pari_err_TYPE("nfsnf",I);
+  if (typ(J)!=t_VEC) pari_err_TYPE("nfsnf",J);
+  if (lg(I)!=n+1 || lg(J)!=n+1) pari_err_DIM("nfsnf");
+  RgM_dimensions(A, &m, &n);
+  if (!n || n != m) pari_err_IMPL("nfsnf for empty or non square matrices");
+
+  av = avma;
+  if (!flag) U = V = NULL;
+  else
+  {
+    U = matid(m);
+    V = matid(n);
+  }
+  A = RgM_to_nfM(nf, A);
+  I = leafcopy(I);
+  J = leafcopy(J);
+  for (i = 1; i <= n; i++) gel(J,i) = idealinv(nf, gel(J,i));
+  z = zerovec(n);
+  for (i=n; i>=1; i--)
+  {
+    GEN Aii, a, b, db;
+    long c = 0;
+    for (j=i-1; j>=1; j--)
+    {
+      GEN S, T, S0, T0 = gel(A,j);
+      b = gel(T0,i); if (gequal0(b)) continue;
+
+      S0 = gel(A,i); a = gel(S0,i);
+      d = nfbezout(nf, a,b, gel(J,i),gel(J,j), &u,&v,&w,&dinv);
+      S = colcomb(nf, u,v, S0,T0);
+      T = colcomb(nf, a,gneg(b), T0,S0);
+      gel(A,i) = S; gel(A,j) = T;
+      gel(J,i) = d; gel(J,j) = w;
+      if (V)
+      {
+        T0 = gel(V,j);
+        S0 = gel(V,i);
+        gel(V,i) = colcomb(nf, u,v, S0,T0);
+        gel(V,j) = colcomb(nf, a,gneg(b), T0,S0);
+      }
+    }
+    for (j=i-1; j>=1; j--)
+    {
+      GEN ri, rj;
+      b = gcoeff(A,j,i); if (gequal0(b)) continue;
+
+      a = gcoeff(A,i,i);
+      d = nfbezout(nf, a,b, gel(I,i),gel(I,j), &u,&v,&w,&dinv);
+      ri = rowcomb(nf, u,v,       i,j, A, i);
+      rj = rowcomb(nf, a,gneg(b), j,i, A, i);
+      for (k=1; k<=i; k++) {
+        gcoeff(A,j,k) = gel(rj,k);
+        gcoeff(A,i,k) = gel(ri,k);
+      }
+      if (U)
+      {
+        ri = rowcomb(nf, u,v,       i,j, U, m);
+        rj = rowcomb(nf, a,gneg(b), j,i, U, m);
+        for (k=1; k<=m; k++) {
+          gcoeff(U,j,k) = gel(rj,k);
+          gcoeff(U,i,k) = gel(ri,k);
+        }
+      }
+      gel(I,i) = d; gel(I,j) = w; c = 1;
+    }
+    if (c) { i++; continue; }
+
+    Aii = gcoeff(A,i,i); if (gequal0(Aii)) continue;
+    gel(J,i) = idealmul(nf, gel(J,i), Aii);
+    gcoeff(A,i,i) = gen_1;
+    if (V) gel(V,i) = nfC_nf_mul(nf, gel(V,i), nfinv(nf,Aii));
+    gel(z,i) = idealmul(nf,gel(J,i),gel(I,i));
+    b = Q_remove_denom(gel(z,i), &db);
+    for (k=1; k<i; k++)
+      for (l=1; l<i; l++)
+      {
+        GEN d, D, p1, p2, p3, Akl = gcoeff(A,k,l);
+        long t;
+        if (gequal0(Akl)) continue;
+
+        p1 = idealmul(nf,Akl,gel(J,l));
+        p3 = idealmul(nf, p1, gel(I,k));
+        if (db) p3 = RgM_Rg_mul(p3, db);
+        if (RgM_is_ZM(p3) && hnfdivide(b, p3)) continue;
+
+        /* find d in D = I[k]/I[i] not in J[i]/(A[k,l] J[l]) */
+        D = idealdiv(nf,gel(I,k),gel(I,i));
+        p2 = idealdiv(nf,gel(J,i), p1);
+        d = RgV_find_denom( RgM_solve(p2, D) );
+        if (!d) pari_err_BUG("nfsnf");
+        p1 = element_mulvecrow(nf,d,A,k,i);
+        for (t=1; t<=i; t++) gcoeff(A,i,t) = gadd(gcoeff(A,i,t),gel(p1,t));
+        if (U)
+        {
+          p1 = element_mulvecrow(nf,d,U,k,i);
+          for (t=1; t<=i; t++) gcoeff(U,i,t) = gadd(gcoeff(U,i,t),gel(p1,t));
+        }
+
+        k = i; c = 1; break;
+      }
+    if (gc_needed(av,1))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"nfsnf");
+      gerepileall(av,U?4:6, &A,&I,&J,&z,&U,&V);
+    }
+    if (c) i++; /* iterate on row/column i */
+  }
+  if (U) z = mkvec3(z,U,V);
+  return gerepilecopy(av, z);
+}
+GEN
+nfsnf(GEN nf, GEN x) { return nfsnf0(nf,x,0); }
+
+/* Given a pseudo-basis x, outputs a multiple of its ideal determinant */
+GEN
+nfdetint(GEN nf, GEN x)
+{
+  GEN pass,c,v,det1,piv,pivprec,vi,p1,A,I,id,idprod;
+  long i, j, k, rg, n, m, m1, cm=0, N;
+  pari_sp av = avma, av1;
+
+  nf = checknf(nf); N = nf_get_degree(nf);
+  check_ZKmodule(x, "nfdetint");
+  A = gel(x,1);
+  I = gel(x,2);
+  n = lg(A)-1; if (!n) return gen_1;
+
+  m1 = lgcols(A); m = m1-1;
+  id = matid(N);
+  c = new_chunk(m1); for (k=1; k<=m; k++) c[k] = 0;
+  piv = pivprec = gen_1;
+
+  av1 = avma;
+  det1 = idprod = gen_0; /* dummy for gerepileall */
+  pass = cgetg(m1,t_MAT);
+  v = cgetg(m1,t_COL);
+  for (j=1; j<=m; j++)
+  {
+    gel(pass,j) = zerocol(m);
+    gel(v,j) = gen_0; /* dummy */
+  }
+  for (rg=0,k=1; k<=n; k++)
+  {
+    long t = 0;
+    for (i=1; i<=m; i++)
+      if (!c[i])
+      {
+        vi=nfmul(nf,piv,gcoeff(A,i,k));
+        for (j=1; j<=m; j++)
+          if (c[j]) vi=gadd(vi,nfmul(nf,gcoeff(pass,i,j),gcoeff(A,j,k)));
+        gel(v,i) = vi; if (!t && !gequal0(vi)) t=i;
+      }
+    if (t)
+    {
+      pivprec = piv;
+      if (rg == m-1)
+      {
+        if (!cm)
+        {
+          cm=1; idprod = id;
+          for (i=1; i<=m; i++)
+            if (i!=t)
+              idprod = (idprod==id)? gel(I,c[i])
+                                   : idealmul(nf,idprod,gel(I,c[i]));
+        }
+        p1 = idealmul(nf,gel(v,t),gel(I,k)); c[t]=0;
+        det1 = (typ(det1)==t_INT)? p1: idealadd(nf,p1,det1);
+      }
+      else
+      {
+        rg++; piv=gel(v,t); c[t]=k;
+        for (i=1; i<=m; i++)
+          if (!c[i])
+          {
+            for (j=1; j<=m; j++)
+              if (c[j] && j!=t)
+              {
+                p1 = gsub(nfmul(nf,piv,gcoeff(pass,i,j)),
+                          nfmul(nf,gel(v,i),gcoeff(pass,t,j)));
+                gcoeff(pass,i,j) = rg>1? nfdiv(nf,p1,pivprec)
+                                       : p1;
+              }
+            gcoeff(pass,i,t) = gneg(gel(v,i));
+          }
+      }
+    }
+    if (gc_needed(av1,1))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"nfdetint");
+      gerepileall(av1,6, &det1,&piv,&pivprec,&pass,&v,&idprod);
+    }
+  }
+  if (!cm) { avma = av; return cgetg(1,t_MAT); }
+  return gerepileupto(av, idealmul(nf,idprod,det1));
+}
+
+/* reduce in place components of x[1..lim] mod D (destroy x). D in HNF */
+static void
+nfcleanmod(GEN nf, GEN x, long lim, GEN D)
+{
+  long i;
+  GEN DZ, DZ2, dD;
+  D = Q_remove_denom(D, &dD);
+  if (dD) x = RgC_Rg_mul(x, dD);
+  DZ = gcoeff(D,1,1);
+  DZ2 = shifti(DZ,-1);
+  for (i=1; i<=lim; i++) {
+    GEN c = gel(x,i);
+    c = nf_to_scalar_or_basis(nf, c);
+    switch(typ(c)) /* c = centermod(c, D) */
+    {
+      case t_INT:
+        if (!signe(c)) break;
+        c = centermodii(c, DZ, DZ2);
+        if (dD) c = gred_frac2(c,dD);
+        break;
+      case t_FRAC: {
+        GEN dc = gel(c,2), nc = gel(c,1), N = mulii(DZ, dc);
+        c = centermodii(nc, N, shifti(N,-1));
+        c = gred_frac2(c, dD ? mulii(dc,dD): dc);
+        break;
+      }
+      case t_COL: {
+        GEN dc;
+        c = Q_remove_denom(c, &dc);
+        c = ZC_hnfrem(c, dc? ZM_Z_mul(D,dc): D);
+        if (ZV_isscalar(c))
+        {
+          c = gel(c,1);
+          if (dD) c = gred_frac2(c,dD);
+        }
+        else
+          if (dD) c = RgC_Rg_div(c, dD);
+        break;
+      }
+    }
+    gel(x,i) = c;
+  }
+}
+
+GEN
+nfhnfmod(GEN nf, GEN x, GEN detmat)
+{
+  long li, co, i, j, def, ldef;
+  pari_sp av0=avma, av;
+  GEN dA, dI, d0, w, p1, d, u, v, A, I, J, di;
+
+  nf = checknf(nf);
+  check_ZKmodule(x, "nfhnfmod");
+  A = gel(x,1);
+  I = gel(x,2);
+  co = lg(A); if (co==1) return cgetg(1,t_MAT);
+
+  li = lgcols(A);
+  if (typ(detmat)!=t_MAT) detmat = idealhnf_shallow(nf, detmat);
+  detmat = Q_remove_denom(detmat, NULL);
+  RgM_check_ZM(detmat, "nfhnfmod");
+
+  av = avma;
+  A = RgM_to_nfM(nf, A);
+  A = Q_remove_denom(A, &dA);
+  I = Q_remove_denom(leafcopy(I), &dI);
+  dA = mul_denom(dA,dI);
+  if (dA) detmat = ZM_Z_mul(detmat, powiu(dA, minss(li,co)));
+
+  def = co; ldef = (li>co)? li-co+1: 1;
+  for (i=li-1; i>=ldef; i--)
+  {
+    def--; j=def; while (j>=1 && isintzero(gcoeff(A,i,j))) j--;
+    if (!j) continue;
+    if (j==def) j--;
+    else {
+      swap(gel(A,j), gel(A,def));
+      swap(gel(I,j), gel(I,def));
+    }
+    for (  ; j; j--)
+    {
+      GEN a, b, S, T, S0, T0 = gel(A,j);
+      b = gel(T0,i); if (isintzero(b)) continue;
+
+      S0 = gel(A,def); a = gel(S0,i);
+      d = nfbezout(nf, a,b, gel(I,def),gel(I,j), &u,&v,&w,&di);
+      S = colcomb(nf, u,v, S0,T0);
+      T = colcomb(nf, a,gneg(b), T0,S0);
+      if (u != gen_0 && v != gen_0) /* already reduced otherwise */
+        nfcleanmod(nf, S, i, idealmul(nf,detmat,di));
+      nfcleanmod(nf, T, i, idealdiv(nf,detmat,w));
+      gel(A,def) = S; gel(A,j) = T;
+      gel(I,def) = d; gel(I,j) = w;
+    }
+    if (gc_needed(av,2))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"[1]: nfhnfmod, i = %ld", i);
+      gerepileall(av,dA? 4: 3, &A,&I,&detmat,&dA);
+    }
+  }
+  def--; d0 = detmat;
+  A += def; A[0] = evaltyp(t_MAT)|evallg(li);
+  I += def; I[0] = evaltyp(t_VEC)|evallg(li);
+  J = cgetg(li,t_VEC);
+  for (i=li-1; i>=1; i--)
+  {
+    GEN b = gcoeff(A,i,i);
+    d = nfbezout(nf, gen_1,b, d0,gel(I,i), &u,&v,&w,&di);
+    p1 = nfC_nf_mul(nf,gel(A,i),v);
+    if (i > 1)
+    {
+      d0 = idealmul(nf,d0,di);
+      nfcleanmod(nf, p1, i, d0);
+    }
+    gel(A,i) = p1; gel(p1,i) = gen_1;
+    gel(I,i) = d;
+    gel(J,i) = di;
+  }
+  for (i=li-2; i>=1; i--)
+  {
+    d = gel(I,i);
+    for (j=i+1; j<li; j++)
+    {
+      GEN c = gcoeff(A,i,j); if (isintzero(c)) continue;
+      c = element_close(nf, c, idealmul(nf,d,gel(J,j)));
+      gel(A,j) = colcomb1(nf, gneg(c), gel(A,j),gel(A,i));
+    }
+    if (gc_needed(av,2))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"[2]: nfhnfmod, i = %ld", i);
+      gerepileall(av,dA? 4: 3, &A,&I,&J,&dA);
+    }
+  }
+  idV_simplify(I);
+  if (dA) I = gdiv(I,dA);
+  return gerepilecopy(av0, mkvec2(A, I));
+}
diff --git a/src/basemath/bb_group.c b/src/basemath/bb_group.c
index df74483..ebb0330 100644
--- a/src/basemath/bb_group.c
+++ b/src/basemath/bb_group.c
@@ -44,14 +44,14 @@ static GEN
 sliding_window_powu(GEN x, ulong n, long e, void *E, GEN (*sqr)(void*,GEN),
                                                      GEN (*mul)(void*,GEN,GEN))
 {
-  pari_sp av, lim;
+  pari_sp av;
   long i, l = expu(n), u = (1UL<<(e-1));
   long w, v;
   GEN tab = cgetg(1+u, t_VEC);
   GEN x2 = sqr(E, x), z = NULL, tw;
   gel(tab, 1) = x;
   for (i=2; i<=u; i++) gel(tab,i) = mul(E, gel(tab,i-1), x2);
-  av = avma; lim = stack_lim(av, 1);
+  av = avma;
   while (l>=0)
   {
     if (e > l+1) e = l+1;
@@ -65,7 +65,7 @@ sliding_window_powu(GEN x, ulong n, long e, void *E, GEN (*sqr)(void*,GEN),
     for (i=1; i<=v; i++) z = sqr(E, z);
     while (l>=0)
     {
-      if (low_stack(lim, stack_lim(av,1)))
+      if (gc_needed(av,1))
       {
         if (DEBUGMEM>1) pari_warn(warnmem,"sliding_window_powu (%ld)", l);
         z = gerepilecopy(av, z);
@@ -83,14 +83,14 @@ static GEN
 sliding_window_pow(GEN x, GEN n, long e, void *E, GEN (*sqr)(void*,GEN),
                                                   GEN (*mul)(void*,GEN,GEN))
 {
-  pari_sp av, lim;
+  pari_sp av;
   long i, l = expi(n), u = (1UL<<(e-1));
   long w, v;
   GEN tab = cgetg(1+u, t_VEC);
   GEN x2 = sqr(E, x), z = NULL, tw;
   gel(tab, 1) = x;
   for (i=2; i<=u; i++) gel(tab,i) = mul(E, gel(tab,i-1), x2);
-  av = avma; lim = stack_lim(av, 1);
+  av = avma;
   while (l>=0)
   {
     if (e > l+1) e = l+1;
@@ -104,7 +104,7 @@ sliding_window_pow(GEN x, GEN n, long e, void *E, GEN (*sqr)(void*,GEN),
     for (i=1; i<=v; i++) z = sqr(E, z);
     while (l>=0)
     {
-      if (low_stack(lim, stack_lim(av,1)))
+      if (gc_needed(av,1))
       {
         if (DEBUGMEM>1) pari_warn(warnmem,"sliding_window_pow (%ld)", l);
         z = gerepilecopy(av, z);
@@ -121,7 +121,7 @@ static GEN
 leftright_binary_powu(GEN x, ulong n, void *E, GEN (*sqr)(void*,GEN),
                                               GEN (*mul)(void*,GEN,GEN))
 {
-  pari_sp av = avma, lim = stack_lim(av, 1);
+  pari_sp av = avma;
   GEN  y;
   int j;
 
@@ -134,7 +134,7 @@ leftright_binary_powu(GEN x, ulong n, void *E, GEN (*sqr)(void*,GEN),
   {
     y = sqr(E,y);
     if (n & HIGHBIT) y = mul(E,y,x); /* first bit set: multiply by base */
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"leftright_powu (%d)", j);
       y = gerepilecopy(av, y);
@@ -170,7 +170,7 @@ gen_pow_i(GEN x, GEN n, void *E, GEN (*sqr)(void*,GEN),
                                  GEN (*mul)(void*,GEN,GEN))
 {
   long l, e;
-  if (lgefint(n)==3) return gen_powu_i(x,(ulong)n[2],E,sqr,mul);
+  if (lgefint(n)==3) return gen_powu_i(x, uel(n,2), E, sqr, mul);
   l = expi(n);
   if      (l<=64)  e = 3;
   else if (l<=160) e = 4;
@@ -193,7 +193,7 @@ GEN
 gen_powu_fold_i(GEN x, ulong n, void *E, GEN  (*sqr)(void*,GEN),
                                          GEN (*msqr)(void*,GEN))
 {
-  pari_sp av = avma, lim = stack_lim(av, 1);
+  pari_sp av = avma;
   GEN y;
   int j;
 
@@ -206,7 +206,7 @@ gen_powu_fold_i(GEN x, ulong n, void *E, GEN  (*sqr)(void*,GEN),
   {
     if (n & HIGHBIT) y = msqr(E,y); /* first bit set: multiply by base */
     else y = sqr(E,y);
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"gen_powu_fold (%d)", j);
       y = gerepilecopy(av, y);
@@ -236,7 +236,7 @@ gen_pow_fold_i(GEN x, GEN N, void *E, GEN (*sqr)(void*,GEN),
     ulong n = *nd;
     long i;
     int j = 1+bfffo(n);
-    pari_sp av = avma, lim = stack_lim(av, 1);
+    pari_sp av = avma;
 
     /* normalize, i.e set highest bit to 1 (we know n != 0) */
     n<<=j; j = BITS_IN_LONG-j;
@@ -247,7 +247,7 @@ gen_pow_fold_i(GEN x, GEN N, void *E, GEN (*sqr)(void*,GEN),
       {
         if (n & HIGHBIT) y = msqr(E,y); /* first bit set: multiply by base */
         else y = sqr(E,y);
-        if (low_stack(lim, stack_lim(av,1)))
+        if (gc_needed(av,1))
         {
           if (DEBUGMEM>1) pari_warn(warnmem,"gen_pow_fold (%d)", j);
           y = gerepilecopy(av, y);
@@ -313,7 +313,7 @@ iter_rho(GEN x, GEN g, GEN q, GEN A, ulong h, void *E, const struct bb_group *gr
 static GEN
 gen_Pollard_log(GEN x, GEN g, GEN q, void *E, const struct bb_group *grp)
 {
-  pari_sp av=avma, lim=stack_lim(av,2);
+  pari_sp av=avma;
   GEN A, B, l, sqrt4q = sqrti(shifti(q,4));
   ulong i, h = 0, imax = itou_or_0(sqrt4q);
   if (!imax) imax = ULONG_MAX;
@@ -332,7 +332,7 @@ gen_Pollard_log(GEN x, GEN g, GEN q, void *E, const struct bb_group *grp)
       A = iter_rho(x, g, q, A, h, E, grp);
       B = iter_rho(x, g, q, B, h, E, grp);
       B = iter_rho(x, g, q, B, h, E, grp);
-      if (low_stack(lim, stack_lim(av,2)))
+      if (gc_needed(av,2))
       {
         if(DEBUGMEM>1) pari_warn(warnmem,"gen_Pollard_log");
         gerepileall(av, 2, &A, &B);
@@ -347,25 +347,82 @@ gen_Pollard_log(GEN x, GEN g, GEN q, void *E, const struct bb_group *grp)
   return gerepileuptoint(av, l);
 }
 
-/*Generic Shanks baby-step/giant-step algorithm*/
+/* compute a hash of g^(i-1), 1<=i<=n. Return [sorted hash, perm, g^-n] */
+GEN
+gen_Shanks_init(GEN g, long n, void *E, const struct bb_group *grp)
+{
+  GEN p1 = g, G, perm, table = cgetg(n+1,t_VECSMALL);
+  pari_sp av=avma;
+  long i;
+  table[1] = grp->hash(grp->pow(E,g,gen_0));
+  for (i=2; i<=n; i++)
+  {
+    table[i] = grp->hash(p1);
+    p1 = grp->mul(E,p1,g);
+    if (gc_needed(av,2))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"gen_Shanks_log, baby = %ld", i);
+      p1 = gerepileupto(av, p1);
+    }
+  }
+  G = gerepileupto(av, grp->pow(E,p1,gen_m1)); /* g^-n */
+  perm = vecsmall_indexsort(table);
+  table = vecsmallpermute(table,perm);
+  return mkvec4(table,perm,g,G);
+}
+/* T from gen_Shanks_init(g,n). Return v < n*N such that x = g^v or NULL */
+GEN
+gen_Shanks(GEN T, GEN x, ulong N, void *E, const struct bb_group *grp)
+{
+  pari_sp av=avma;
+  GEN table = gel(T,1), perm = gel(T,2), g = gel(T,3), G = gel(T,4);
+  GEN p1 = x;
+  long n = lg(table)-1;
+  ulong k;
+  for (k=0; k<N; k++)
+  { /* p1 = x G^k, G = g^-n */
+    long h = grp->hash(p1), i = zv_search(table, h);
+    if (i)
+    {
+      do i--; while (i && table[i] == h);
+      for (i++; i <= n && table[i] == h; i++)
+      {
+        GEN v = addiu(muluu(n,k), perm[i]-1);
+        if (grp->equal(grp->pow(E,g,v),x)) return gerepileuptoint(av,v);
+        if (DEBUGLEVEL)
+          err_printf("gen_Shanks_log: false positive %lu, %lu\n", k,h);
+      }
+    }
+    p1 = grp->mul(E,p1,G);
+    if (gc_needed(av,2))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"gen_Shanks_log, k = %lu", k);
+      p1 = gerepileupto(av, p1);
+    }
+  }
+  return NULL;
+}
+/* Generic Shanks baby-step/giant-step algorithm. Return log_g(x), ord g = q.
+ * One-shot: use gen_Shanks_init/log if many logs are desired; early abort
+ * if log < sqrt(q) */
 static GEN
-gen_Shanks_log(GEN x, GEN g0,GEN q, void *E, const struct bb_group *grp)
+gen_Shanks_log(GEN x, GEN g, GEN q, void *E, const struct bb_group *grp)
 {
-  pari_sp av=avma,av1,lim;
-  long lbaby,i,k;
-  GEN p1,table,giant,perm,g0inv;
+  pari_sp av=avma, av1;
+  long lbaby, i, k;
+  GEN p1, table, giant, perm, ginv;
   p1 = sqrti(q);
   if (cmpiu(p1,LGBITS) >= 0)
-    pari_err_OVERFLOW("gen_Shanks_log() [order too large]");
+    pari_err_OVERFLOW("gen_Shanks_log [order too large]");
   lbaby = itos(p1)+1; table = cgetg(lbaby+1,t_VECSMALL);
-  g0inv = grp->pow(E,g0,gen_m1);
-  av1 = avma; lim=stack_lim(av1,2);
+  ginv = grp->pow(E,g,gen_m1);
+  av1 = avma;
   for (p1=x, i=1;;i++)
   {
     if (grp->equal1(p1)) { avma = av; return stoi(i-1); }
     table[i] = grp->hash(p1); if (i==lbaby) break;
-    p1 = grp->mul(E,p1,g0inv);
-    if (low_stack(lim, stack_lim(av1,2)))
+    p1 = grp->mul(E,p1,ginv);
+    if (gc_needed(av1,2))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"gen_Shanks_log, baby = %ld", i);
       p1 = gerepileupto(av1, p1);
@@ -373,29 +430,26 @@ gen_Shanks_log(GEN x, GEN g0,GEN q, void *E, const struct bb_group *grp)
   }
   p1 = giant = gerepileupto(av1, grp->mul(E,x,grp->pow(E, p1, gen_m1)));
   perm = vecsmall_indexsort(table);
-  table = perm_mul(table,perm);
-  av1 = avma; lim=stack_lim(av1,2);
+  table = vecsmallpermute(table,perm);
+  av1 = avma;
   for (k=1; k<= lbaby; k++)
   {
-    long h = grp->hash(p1);
-    long i = zv_search(table, h);
+    long h = grp->hash(p1), i = zv_search(table, h);
     if (i)
     {
       while (table[i] == h && i) i--;
       for (i++; i <= lbaby && table[i] == h; i++)
       {
-        GEN v=addis(mulss(lbaby-1,k),perm[i]-1);
-        if (grp->equal(grp->pow(E,g0,v),x))
-          return gerepileuptoint(av,v);
-        else if (DEBUGLEVEL)
-          err_printf("gen_Shanks_log: false positive, giant = %ld: %lu: %Ps\n", k,h,p1);
+        GEN v = addiu(mulss(lbaby-1,k),perm[i]-1);
+        if (grp->equal(grp->pow(E,g,v),x)) return gerepileuptoint(av,v);
+        if (DEBUGLEVEL)
+          err_printf("gen_Shanks_log: false positive %ld, %lu\n", k,h);
       }
     }
     p1 = grp->mul(E,p1,giant);
-
-    if (low_stack(lim, stack_lim(av1,2)))
+    if (gc_needed(av1,2))
     {
-      if(DEBUGMEM>1) pari_warn(warnmem,"gen_Shanks_log, giant = %ld", k);
+      if(DEBUGMEM>1) pari_warn(warnmem,"gen_Shanks_log, k = %ld", k);
       p1 = gerepileupto(av1, p1);
     }
   }
@@ -610,8 +664,8 @@ gen_factored_order(GEN a, GEN o, void *E, const struct bb_group *grp)
       ind++;
     }
   }
-  setlg(P, ind);
-  setlg(F, ind);
+  setlg(P, ind); P = vecreverse(P);
+  setlg(F, ind); F = vecreverse(F);
   return gerepilecopy(av, mkvec2(o, mkmat2(P,F)));
 }
 
@@ -686,12 +740,12 @@ gen_lgener(GEN l, long e, GEN r,GEN *zeta, void *E, const struct bb_group *grp)
 GEN
 gen_gener(GEN o, void *E, const struct bb_group *grp)
 {
-  pari_sp ltop = avma, av, lim;
+  pari_sp ltop = avma, av;
   long i, lpr;
   GEN F, N, pr, z=NULL;
   F = dlog_get_ordfa(o);
   N = gel(F,1); pr = gel(F,2); lpr = lgcols(pr);
-  av = avma; lim = stack_lim(av,2);
+  av = avma;
 
   for (i = 1; i < lpr; i++)
   {
@@ -700,7 +754,7 @@ gen_gener(GEN o, void *E, const struct bb_group *grp)
     GEN r = diviiexact(N,powis(l,e));
     GEN zetan, zl = gen_lgener(l,e,r,&zetan,E,grp);
     z = i==1 ? zl: grp->mul(E,z,zl);
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     { /* n can have lots of prime factors*/
       if(DEBUGMEM>1) pari_warn(warnmem,"gen_gener");
       z = gerepileupto(av, z);
@@ -718,7 +772,7 @@ static GEN
 gen_Shanks_sqrtl(GEN a, GEN l, long e, GEN r, GEN y, GEN m,void *E,
                  const struct bb_group *grp)
 {
-  pari_sp av = avma,lim;
+  pari_sp av = avma;
   long k;
   GEN p1, u1, u2, v, w, z, dl;
 
@@ -726,7 +780,6 @@ gen_Shanks_sqrtl(GEN a, GEN l, long e, GEN r, GEN y, GEN m,void *E,
   v = grp->pow(E,a,u2);
   w = grp->pow(E,v,l);
   w = grp->mul(E,w,grp->pow(E,a,gen_m1));
-  lim = stack_lim(av,1);
   while (!grp->equal1(w))
   {
     k = 0;
@@ -746,7 +799,7 @@ gen_Shanks_sqrtl(GEN a, GEN l, long e, GEN r, GEN y, GEN m,void *E,
     v = grp->mul(E,p1,v);
     y = grp->pow(E,p1,l);
     w = grp->mul(E,y,w);
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"gen_Shanks_sqrtl");
       gerepileall(av,4, &y,&v,&w,&m);
@@ -765,7 +818,7 @@ gen_Shanks_sqrtl(GEN a, GEN l, long e, GEN r, GEN y, GEN m,void *E,
 GEN
 gen_Shanks_sqrtn(GEN a, GEN n, GEN q, GEN *zetan, void *E, const struct bb_group *grp)
 {
-  pari_sp ltop = avma, lim;
+  pari_sp ltop = avma;
   GEN m, u1, u2, z;
   int is_1;
 
@@ -779,7 +832,6 @@ gen_Shanks_sqrtn(GEN a, GEN n, GEN q, GEN *zetan, void *E, const struct bb_group
 
   m = bezout(n,q,&u1,&u2);
   z = grp->pow(E,a,gen_0);
-  lim = stack_lim(ltop,1);
   if (!is_pm1(m))
   {
     GEN F = Z_factor(m);
@@ -800,7 +852,7 @@ gen_Shanks_sqrtn(GEN a, GEN n, GEN q, GEN *zetan, void *E, const struct bb_group
           if (!a) { avma = ltop; return NULL;}
         } while (--j);
       }
-      if (low_stack(lim, stack_lim(ltop,1)))
+      if (gc_needed(ltop,1))
       { /* n can have lots of prime factors*/
         if(DEBUGMEM>1) pari_warn(warnmem,"gen_Shanks_sqrtn");
         gerepileall(av1, zetan? 2: 1, &a, &z);
diff --git a/src/basemath/bibli1.c b/src/basemath/bibli1.c
index e579b9f..93cf5a1 100644
--- a/src/basemath/bibli1.c
+++ b/src/basemath/bibli1.c
@@ -164,9 +164,16 @@ matqr(GEN x, long flag, long prec)
 {
   pari_sp av = avma;
   GEN B, Q, L;
+  long n = lg(x)-1;
   if (typ(x) != t_MAT) pari_err_TYPE("matqr",x);
+  if (!n)
+  {
+    if (!flag) retmkvec2(cgetg(1,t_MAT),cgetg(1,t_MAT));
+    retmkvec2(cgetg(1,t_VEC),cgetg(1,t_MAT));
+  }
+  if (n != nbrows(x)) pari_err_DIM("matqr");
   if (!RgM_QR_init(x, &B,&Q,&L, prec)) pari_err_PREC("matqr");
-  if (!flag) Q = shallowtrans(mathouseholder(Q, matid(lg(x)-1)));
+  if (!flag) Q = shallowtrans(mathouseholder(Q, matid(n)));
   return gerepilecopy(av, mkvec2(Q, shallowtrans(L)));
 }
 
@@ -214,7 +221,6 @@ R_from_QR(GEN x, long prec)
 /**             QR Factorization via Gram-Schmidt                  **/
 /********************************************************************/
 
-#if 0
 /* return Gram-Schmidt orthogonal basis (f) associated to (e), B is the
  * vector of the (f_i . f_i)*/
 GEN
@@ -243,7 +249,6 @@ gram_schmidt(GEN e, GEN *ptB)
   }
   *ptB = B; return f;
 }
-#endif
 
 /********************************************************************/
 /**                                                                **/
@@ -376,7 +381,7 @@ lllintpartialall(GEN m, long flag)
    /* For each pair of column vectors v and w in mid * tm2,
     * try to replace (v, w) by (v, v - q*w) for some q.
     * We compute all inner products and check them repeatedly. */
-    const pari_sp av3 = avma, lim = stack_lim(av3,2);
+    const pari_sp av3 = avma;
     long i, j, npass = 0, e = LONG_MAX;
     GEN dot = cgetg(ncol+1, t_MAT); /* scalar products */
 
@@ -414,7 +419,7 @@ lllintpartialall(GEN m, long flag)
                                     mulii(q, gcoeff(dot,k2,k1)));
           for (d = 1; d <= ncol; d++) gcoeff(dot,k1,d) = gcoeff(dot,d,k1);
         } /* for ijdif */
-        if (low_stack(lim, stack_lim(av3,2)))
+        if (gc_needed(av3,2))
         {
           if(DEBUGMEM>1) pari_warn(warnmem,"lllintpartialall");
           gerepileall(av3, 2, &dot,&tm2);
@@ -446,13 +451,6 @@ lllintpartialall(GEN m, long flag)
         swap(gcoeff(dot,i,i), gcoeff(dot,s,s));
       }
     }
-    i = 1;
-    while (i <= ncol && !signe(gcoeff(dot,i,i))) i++;
-    if (i > 1)
-    {
-      tm2 += (i - 1);
-      tm2[0] = evaltyp(t_MAT)|evallg(ncol - i);
-    }
   } /* local block */
   return gerepileupto(av, ZM_mul(tm1? tm1: mid, tm2));
 }
@@ -1111,7 +1109,7 @@ minim0_dolll(GEN a, GEN BORNE, GEN STOCKMAX, long flag, long dolll)
 {
   GEN x, u, r, L, gnorme, invp, V;
   long n = lg(a), i, j, k, s, maxrank, sBORNE;
-  pari_sp av = avma, av1, lim;
+  pari_sp av = avma, av1;
   double p,maxnorm,BOUND,*v,*y,*z,**q;
   const double eps = 1e-10;
   int stockall = 0;
@@ -1203,7 +1201,7 @@ minim0_dolll(GEN a, GEN BORNE, GEN STOCKMAX, long flag, long dolll)
       V = cgetg(1+maxrank, t_VECSMALL);
   }
 
-  s = 0; av1 = avma; lim = stack_lim(av1,1);
+  s = 0; av1 = avma;
   k = n; y[n] = z[n] = 0;
   x[n] = (long)sqrt(BOUND/v[n]);
   for(;;x[1]--)
@@ -1299,7 +1297,7 @@ minim0_dolll(GEN a, GEN BORNE, GEN STOCKMAX, long flag, long dolll)
           s--; avma=av2; continue;
         }
         if (DEBUGLEVEL>1) { err_printf("*"); err_flush(); }
-        if (low_stack(lim, stack_lim(av1,1)))
+        if (gc_needed(av1,1))
         {
           if(DEBUGMEM>1) pari_warn(warnmem,"minim0, rank>=%ld",s);
           invp = gerepilecopy(av1, invp);
@@ -1501,7 +1499,7 @@ static GEN
 smallvectors(GEN q, GEN BORNE, long maxnum, FP_chk_fun *CHECK)
 {
   long N = lg(q), n = N-1, i, j, k, s, stockmax, checkcnt = 1;
-  pari_sp av, av1, lim;
+  pari_sp av, av1;
   GEN inc, S, x, y, z, v, p1, alpha, norms;
   GEN norme1, normax1, borne1, borne2;
   GEN (*check)(void *,GEN) = CHECK? CHECK->f: NULL;
@@ -1515,7 +1513,7 @@ smallvectors(GEN q, GEN BORNE, long maxnum, FP_chk_fun *CHECK)
   v = cgetg(N,t_VEC);
   inc = const_vecsmall(n, 1);
 
-  av = avma; lim = stack_lim(av,2);
+  av = avma;
   stockmax = stockall? 2000: maxnum;
   norms = cgetg(check?(stockmax+1): 1,t_VEC); /* unused if (!check) */
   S = cgetg(stockmax+1,t_VEC);
@@ -1589,7 +1587,7 @@ smallvectors(GEN q, GEN BORNE, long maxnum, FP_chk_fun *CHECK)
         if (++k > n) goto END;
       }
 
-      if (low_stack(lim, stack_lim(av,2)))
+      if (gc_needed(av,2))
       {
         if(DEBUGMEM>1) pari_warn(warnmem,"smallvectors");
         if (stockmax) S = clonefill(S, s, stockmax);
diff --git a/src/basemath/bibli2.c b/src/basemath/bibli2.c
index a3e44a1..f985d08 100644
--- a/src/basemath/bibli2.c
+++ b/src/basemath/bibli2.c
@@ -604,23 +604,44 @@ gprec_wtrunc(GEN x, long pr)
 /********************************************************************/
 /**                  LAPLACE TRANSFORM (OF A SERIES)               **/
 /********************************************************************/
-GEN
-laplace(GEN x)
+static GEN
+serlaplace(GEN x)
 {
-  pari_sp av = avma;
   long i, l = lg(x), e = valp(x);
-  GEN y, t;
-
-  if (typ(x) != t_SER) pari_err_TYPE("laplace",x);
+  GEN t, y = cgetg(l,t_SER);
   if (e < 0) pari_err_DOMAIN("laplace","valuation","<",gen_0,stoi(e));
-  y = cgetg(l,t_SER);
   t = mpfact(e); y[1] = x[1];
   for (i=2; i<l; i++)
   {
     gel(y,i) = gmul(t, gel(x,i));
     e++; t = mului(e,t);
   }
-  return gerepilecopy(av,y);
+  return y;
+}
+static GEN
+pollaplace(GEN x)
+{
+  long i, e = 0, l = lg(x);
+  GEN t = gen_1, y = cgetg(l,t_POL);
+  y[1] = x[1];
+  for (i=2; i<l; i++)
+  {
+    gel(y,i) = gmul(t, gel(x,i));
+    e++; t = mului(e,t);
+  }
+  return y;
+}
+GEN
+laplace(GEN x)
+{
+  pari_sp av = avma;
+  switch(typ(x))
+  {
+    case t_POL: x = pollaplace(x); break;
+    case t_SER: x = serlaplace(x); break;
+    default: pari_err_TYPE("laplace",x);
+  }
+  return gerepilecopy(av, x);
 }
 
 /********************************************************************/
@@ -635,8 +656,12 @@ convol(GEN x, GEN y)
   if (typ(x) != t_SER) pari_err_TYPE("convol",x);
   if (typ(y) != t_SER) pari_err_TYPE("convol",y);
   if (varn(y) != vx) pari_err_VAR("convol", x,y);
-  ex = valp(x); lx = lg(x) + ex; x -= ex;
-  ey = valp(y); ly = lg(y) + ey; y -= ey;
+  ex = valp(x);
+  ey = valp(y);
+  if (ser_isexactzero(x))
+    return scalarser(gadd(RgX_get_0(x), RgX_get_0(y)), varn(x), maxss(ex,ey));
+  lx = lg(x) + ex; x -= ex;
+  ly = lg(y) + ey; y -= ey;
   /* inputs shifted: x[i] and y[i] now correspond to monomials of same degree */
   if (ly < lx) lx = ly; /* min length */
   if (ex < ey) ex = ey; /* max valuation */
@@ -663,7 +688,7 @@ dirval(GEN x)
 GEN
 dirmul(GEN x, GEN y)
 {
-  pari_sp av = avma, lim = stack_lim(av, 1);
+  pari_sp av = avma;
   long nx, ny, nz, dx, dy, i, j, k;
   GEN z;
 
@@ -684,9 +709,9 @@ dirmul(GEN x, GEN y)
       for (k=dy,i=j*dy; i<=nz; i+=j,k++) gel(z,i) = gsub(gel(z,i),gel(y,k));
     else
       for (k=dy,i=j*dy; i<=nz; i+=j,k++) gel(z,i) = gadd(gel(z,i),gmul(c,gel(y,k)));
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,2))
     {
-      if (DEBUGLEVEL) err_printf("doubling stack in dirmul\n");
+      if (DEBUGMEM>1) pari_warn(warnmem,"dirmul, %ld/%ld",j,nx);
       z = gerepilecopy(av,z);
     }
   }
@@ -696,7 +721,7 @@ dirmul(GEN x, GEN y)
 GEN
 dirdiv(GEN x, GEN y)
 {
-  pari_sp av = avma;
+  pari_sp av = avma, av2;
   long nx,ny,nz,dx,dy,i,j;
   GEN z,p1;
 
@@ -706,11 +731,19 @@ dirdiv(GEN x, GEN y)
   dy = dirval(y); ny = lg(y)-1;
   if (dy != 1 || !ny) pari_err_INV("dirdiv",y);
   nz = minss(nx,ny*dx); p1 = gel(y,1);
-  if (!gequal1(p1)) { y = gdiv(y,p1); x = gdiv(x,p1); } else x = leafcopy(x);
-  z = zerovec(nz);
+  if (!gequal1(p1))
+  {
+    y = gdiv(y,p1);
+    av2 = avma;
+    x = gdiv(x,p1);
+  } else
+  {
+    av2 = avma;
+    x = leafcopy(x);
+  }
   for (j=dx; j<=nz; j++)
   {
-    GEN c = gel(x,j); gel(z,j) = c;
+    GEN c = gel(x,j);
     if (gequal0(c)) continue;
     if (gequal1(c))
       for (i=j+j; i<=nz; i+=j) gel(x,i) = gsub(gel(x,i),gel(y,i/j));
@@ -718,7 +751,17 @@ dirdiv(GEN x, GEN y)
       for (i=j+j; i<=nz; i+=j) gel(x,i) = gadd(gel(x,i),gel(y,i/j));
     else
       for (i=j+j; i<=nz; i+=j) gel(x,i) = gsub(gel(x,i),gmul(c,gel(y,i/j)));
+    if (gc_needed(av2,2))
+    {
+      if (DEBUGMEM>1) pari_warn(warnmem,"dirdiv, %ld/%ld",j,nz);
+      x = gerepilecopy(av2,x);
+    }
   }
+  z = cgetg(nz+1,t_VEC);
+  for (j=1; j<dx; j++)
+   gel(z,j) = gen_0;
+  for (j=dx; j<=nz; j++)
+   gel(z,j) = gel(x,j);
   return gerepilecopy(av,z);
 }
 
@@ -829,7 +872,7 @@ vecbinome(long n)
 GEN
 stirling2(ulong n, ulong m)
 {
-  pari_sp av = avma, lim = stack_lim(av, 2);
+  pari_sp av = avma;
   GEN s, bmk;
   ulong k;
   if (n==0) return (m == 0)? gen_1: gen_0;
@@ -845,7 +888,7 @@ stirling2(ulong n, ulong m)
     c = odd(m)? subii(mkn,kn): addii(mkn,kn);
     c = mulii(bmk, c);
     s = odd(k)? subii(s, c): addii(s, c);
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"stirling2");
       gerepileall(av, 2, &s, &bmk);
@@ -911,27 +954,27 @@ stirling(long n, long m, long flag)
 GEN
 numtoperm(long n, GEN x)
 {
-  pari_sp av, lim;
+  pari_sp av;
   ulong i, r;
   GEN v;
 
   if (n < 0) pari_err_DOMAIN("numtoperm", "n", "<", gen_0, stoi(n));
   if (typ(x) != t_INT) pari_err_TYPE("numtoperm",x);
   v = cgetg(n+1, t_VEC); if (n==0) return v;
-  v[n] = 1; av = avma; lim = stack_lim(av,2);
+  uel(v,n) = 1; av = avma;
   if (signe(x) <= 0) x = modii(x, mpfact(n));
   for (r=n-1; r>=1; r--)
   {
     ulong a;
     x = diviu_rem(x, n+1-r,&a);
     for (i=r+1; i<=(ulong)n; i++)
-      if((ulong)v[i]>a) v[i]++;
-    v[r] = a+1;
-    if (low_stack(lim, stack_lim(av,2)))
+      if (uel(v,i) > a) uel(v,i)++;
+    uel(v,r) = a+1;
+    if (gc_needed(av,2))
       x = gerepileuptoint(av, x);
   }
   avma = av;
-  for (i=1; i<=(ulong)n; i++) gel(v,i) = utoipos(v[i]);
+  for (i=1; i<=(ulong)n; i++) gel(v,i) = utoipos(uel(v,i));
   return v;
 }
 
@@ -939,7 +982,7 @@ GEN
 permtonum(GEN p)
 {
   long n = lg(p)-1, i, r;
-  pari_sp av = avma, av2, lim;
+  pari_sp av = avma, av2;
   GEN v, x;
 
   if (!is_vec_t(typ(p))) pari_err_TYPE("permtonum",p);
@@ -950,14 +993,14 @@ permtonum(GEN p)
     if (typ(pi) != t_INT) pari_err_TYPE("permtonum",pi);
     v[i] = itos(pi);
   }
-  x = gen_0; av2 = avma; lim = stack_lim(av2,2);
+  x = gen_0; av2 = avma;
   for (i=1; i<=n; i++)
   {
     long vi = v[i];
     x = i==1 ? stoi(v[1]-1): addiu(mulis(x,n+1-i),vi-1);
     for (r=i+1; r<=n; r++)
       if (v[r]>vi) v[r]--;
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
       x = gerepileuptoint(av2, x);
   }
   return gerepileuptoint(av, x);
@@ -985,7 +1028,7 @@ polrecip(GEN x)
 GEN
 RgV_polint(GEN X, GEN Y, long v)
 {
-  pari_sp av0 = avma, av, lim;
+  pari_sp av0 = avma, av;
   GEN Q, P = NULL;
   long i, l = lg(Y);
   if (!X)
@@ -993,7 +1036,7 @@ RgV_polint(GEN X, GEN Y, long v)
     X = cgetg(l, t_VEC);
     for (i=1; i<l; i++) gel(X,i) = utoipos(i);
   }
-  Q = roots_to_pol(X, v); av = avma; lim = stack_lim(av,2);
+  Q = roots_to_pol(X, v); av = avma;
   for (i=1; i<l; i++)
   {
     GEN inv, T, dP;
@@ -1002,7 +1045,7 @@ RgV_polint(GEN X, GEN Y, long v)
     inv = ginv(poleval(T,gel(X,i)));
     dP = RgX_Rg_mul(T, gmul(gel(Y,i),inv));
     P = P? RgX_add(P, dP): dP;
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"FpV_polint");
       P = gerepileupto(av, P);
@@ -1449,7 +1492,7 @@ sort_function(void **E, GEN x, GEN k)
     case t_VEC: case t_COL: k = ZV_to_zv(k); break;
     case t_VECSMALL: break;
     case t_CLOSURE:
-     if (closure_arity(k) != 2)
+     if (closure_arity(k) != 2 || closure_is_variadic(k))
        pari_err_TYPE("sort_function, cmp. fun. needs exactly 2 arguments",k);
      *E = (void*)k;
      return &closurecmp;
@@ -1641,7 +1684,7 @@ cmp_RgX(GEN x, GEN y)
 /**                   MERGE & SORT FACTORIZATIONS                  **/
 /********************************************************************/
 /* merge fx, fy two factorizations, whose 1st column is sorted in strictly
- * increasing order wrt cmp. Keep 0 exponents. */
+ * increasing order wrt cmp */
 GEN
 merge_factor(GEN fx, GEN fy, void *data, int (*cmp)(void *,GEN,GEN))
 {
@@ -1659,7 +1702,11 @@ merge_factor(GEN fx, GEN fy, void *data, int (*cmp)(void *,GEN,GEN))
     if (s < 0)
     { gel(M,m) = gel(x,ix); gel(E,m) = gel(e,ix); ix++; }
     else if (s == 0)
-    { gel(M,m) = gel(x,ix); gel(E,m) = addii(gel(e,ix), gel(f,iy)); iy++; ix++; }
+    {
+      GEN z = gel(x,ix), g = addii(gel(e,ix), gel(f,iy));
+      iy++; ix++; if (!signe(g)) continue;
+      gel(M,m) = z; gel(E,m) = g;
+    }
     else
     { gel(M,m) = gel(y,iy); gel(E,m) = gel(f,iy); iy++; }
     m++;
@@ -1880,7 +1927,7 @@ setbinop(GEN f, GEN x, GEN y)
   pari_sp av = avma;
   long i, j, lx, ly, k = 1;
   GEN z;
-  if (typ(f) != t_CLOSURE || closure_arity(f) != 2)
+  if (typ(f) != t_CLOSURE || closure_arity(f) != 2 || closure_is_variadic(f))
     pari_err_TYPE("setbinop [function needs exactly 2 arguments]",f);
   lx = lg(x);
   if (typ(x) != t_VEC) pari_err_TYPE("setbinop", x);
diff --git a/src/basemath/bit.c b/src/basemath/bit.c
index 0d7dd86..6e9e253 100644
--- a/src/basemath/bit.c
+++ b/src/basemath/bit.c
@@ -23,6 +23,65 @@ INLINE GEN
 inegate(GEN z) { return subsi(-1,z); }
 
 GEN
+binary_zv(GEN x)
+{
+  GEN xp, z;
+  long i, k, lx;
+  if (!signe(x)) return cgetg(1,t_VECSMALL);
+  xp = int_LSW(x);
+  lx = lgefint(x);
+  k = expi(x)+2;
+  z = cgetg(k, t_VECSMALL);
+  k--;
+  for(i = 2; i < lx; i++)
+  {
+    ulong u = *xp;
+    long j;
+    for (j=0; j<BITS_IN_LONG && k; j++) z[k--] = (u>>j)&1UL;
+    if (!k) break;
+    xp = int_nextW(xp);
+  }
+  return z;
+}
+static GEN
+F2v_to_ZV_inplace(GEN v)
+{
+  long i, l = lg(v);
+  v[0] = evaltyp(t_VEC) | _evallg(l);
+  for (i = 1; i < l; i++) gel(v,i) = v[i]? gen_1: gen_0;
+  return v;
+}
+/* "vector" of l bits (possibly no code word) to non-negative t_INT */
+GEN
+bits_to_int(GEN x, long l)
+{
+  long i, j, lz;
+  GEN z, zp;
+
+  if (!l) return gen_0;
+  lz = nbits2lg(l);
+  z = cgetg(lz, t_INT);
+  z[1] = evalsigne(1) | evallgefint(lz);
+  zp = int_LSW(z); *zp = 0;
+  for(i=l,j=0; i; i--,j++)
+  {
+    if (j==BITS_IN_LONG) { j=0; zp = int_nextW(zp); *zp = 0; }
+    if (x[i]) *zp |= 1UL<<j;
+  }
+  return int_normalize(z, 0);
+}
+/* "vector" of l < BITS_IN_LONG bits (possibly no code word) to non-negative
+ * ulong */
+ulong
+bits_to_u(GEN v, long l)
+{
+  ulong u = 0;
+  long i;
+  for (i = 1; i <= l; i++) u = (u <<1) | v[i];
+  return u;
+}
+
+GEN
 binaire(GEN x)
 {
   ulong m,u;
@@ -32,24 +91,9 @@ binaire(GEN x)
   switch(tx)
   {
     case t_INT:
-    if (!signe(x))
-      return cgetg(1,t_VEC);
-    else
-    {
-      GEN xp=int_MSW(x);
-      lx=lgefint(x);
-      y = cgetg(2 + expi(x), t_VEC); ly=1;
-      m=HIGHBIT>>bfffo(*xp); u=*xp;
-      do { gel(y,ly) = m & u ? gen_1 : gen_0; ly++; } while (m>>=1);
-      for (i=3; i<lx; i++)
-      {
-        m=HIGHBIT; xp=int_precW(xp); u=*xp;
-        do { gel(y,ly) = m & u ? gen_1 : gen_0; ly++; } while (m>>=1);
-      }
-      break;
-    }
+      return F2v_to_ZV_inplace( binary_zv(x) );
     case t_REAL:
-      ex=expo(x);
+      ex = expo(x);
       if (!signe(x)) return const_vec(maxss(-ex,0), gen_0);
 
       lx=lg(x); y=cgetg(3,t_VEC);
@@ -95,6 +139,43 @@ binaire(GEN x)
   return y;
 }
 
+/* assume k < BITS_IN_LONG */
+GEN
+binary_2k_zv(GEN x, long k)
+{
+  long iv, j, n, nmodk, nk;
+  GEN v, vk;
+  if (k == 1) return binary_zv(x);
+  if (!signe(x)) return cgetg(1,t_VECSMALL);
+  v = binary_zv(x);
+  n = lg(v)-1;
+  nk = n / k; nmodk = n % k;
+  if (nmodk) nk++;
+  vk = cgetg(nk+1, t_VECSMALL);
+  iv = n - k;
+  if (!nmodk) nmodk = k;
+  for (j = nk; j >= 2; j--,iv-=k) vk[j] = bits_to_u(v+iv, k);
+  vk[1] = bits_to_u(v,nmodk);
+  return vk;
+}
+GEN
+binary_2k(GEN x, long k)
+{
+  long iv, j, n, nmodk, nk;
+  GEN v, vk;
+  if (!signe(x)) return cgetg(1,t_VEC);
+  v = binary_zv(x);
+  n = lg(v)-1;
+  nk = n / k; nmodk = n % k;
+  if (nmodk) nk++;
+  vk = cgetg(nk+1, t_VEC);
+  iv = n - k;
+  if (!nmodk) nmodk = k;
+  for (j = nk; j >= 2; j--,iv-=k) gel(vk,j) = bits_to_int(v+iv, k);
+  gel(vk,1) = bits_to_int(v, nmodk);
+  return vk;
+}
+
 /* return 1 if bit n of x is set, 0 otherwise */
 long
 bittest(GEN x, long n)
diff --git a/src/basemath/buch1.c b/src/basemath/buch1.c
index ff7c31e..86338db 100644
--- a/src/basemath/buch1.c
+++ b/src/basemath/buch1.c
@@ -96,11 +96,11 @@ static GEN
 qfr5_rho_pow(GEN x, long n, struct qfr_data *S)
 {
   long i;
-  pari_sp av = avma, lim = stack_lim(av, 1);
+  pari_sp av = avma;
   for (i=1; i<=n; i++)
   {
     x = qfr5_rho(x,S);
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"qfr5_rho_pow");
       x = gerepilecopy(av, x);
@@ -191,7 +191,7 @@ check_LIMC(long LIMC, long LIMCMAX)
 static int
 isless_iu(GEN q, ulong p) {
   long l = lgefint(q);
-  return l==2 || (l == 3 && (ulong)q[2] <= p);
+  return l==2 || (l == 3 && uel(q,2) <= p);
 }
 
 static long
@@ -203,7 +203,7 @@ factorquad(struct buch_quad *B, GEN f, long nFB, ulong limp)
 
   for (i=1; lgefint(x) > 3; i++)
   {
-    ulong p = (ulong)FB[i], r;
+    ulong p = uel(FB,i), r;
     GEN q = diviu_rem(x, p, &r);
     if (!r)
     {
@@ -212,16 +212,16 @@ factorquad(struct buch_quad *B, GEN f, long nFB, ulong limp)
       lo++; P[lo] = p; E[lo] = k;
     }
     if (isless_iu(q,p)) {
-      if (lgefint(x) == 3) { X = (ulong)x[2]; goto END; }
+      if (lgefint(x) == 3) { X = uel(x,2); goto END; }
       return 0;
     }
     if (i == nFB) return 0;
   }
-  X = (ulong)x[2];
+  X = uel(x,2);
   if (X == 1) { P[0] = 0; return 1; }
   for (;; i++)
   { /* single precision affair, split for efficiency */
-    ulong p = (ulong)FB[i];
+    ulong p = uel(FB,i);
     ulong q = X / p, r = X % p; /* gcc makes a single div */
     if (!r)
     {
@@ -302,10 +302,10 @@ static void
 cache_prime_quad(GRHcheck_t *S, ulong LIM, GEN D)
 {
   GRHprime_t *pr;
-  double nb;
+  long nb;
 
   if (S->limp >= LIM) return;
-  nb = primepi_upper_bound((double)LIM); /* #{p <= LIM} <= nb */
+  nb = (long)primepi_upper_bound((double)LIM); /* #{p <= LIM} <= nb */
   GRH_ensure(S, nb+1); /* room for one extra prime */
   for (pr = S->primes + S->nprimes;;)
   {
@@ -369,11 +369,8 @@ nthidealquad(GEN D, long n)
   forprime_t S;
   ulong p;
   (void)u_forprime_init(&S, 2, ULONG_MAX);
-  while (n > 0)
-  {
-    p = u_forprime_next(&S);
+  while ((p = u_forprime_next(&S)) && n > 0)
     if (!is_bad(D, p) && kroiu(D, p) >= 0) n--;
-  }
   avma = av; return p;
 }
 
@@ -468,7 +465,7 @@ subFBquad(struct buch_quad *B, GEN D, double PROD, long minSFB)
   no    = cgetg(lv, t_VECSMALL);
   for (j = 1; j < lv; j++)
   {
-    ulong p = B->FB[j];
+    ulong p = uel(B->FB,j);
     if (!umodiu(D, p)) no[ino++] = j; /* ramified */
     else
     {
@@ -615,7 +612,7 @@ imag_relations(struct buch_quad *B, long need, long *pc, ulong LIMC, GEN mat)
   GEN col, form, ex = cgetg(lgsub, t_VECSMALL);
 
   if (!current) current = 1;
-  if (DEBUGLEVEL) timer_start(&T);
+  if (DEBUGLEVEL>2) timer_start(&T);
   av = avma;
   for(;;)
   {
@@ -626,7 +623,7 @@ imag_relations(struct buch_quad *B, long need, long *pc, ulong LIMC, GEN mat)
     nbtest++; fpc = factorquad(B,form,B->KC,LIMC);
     if (!fpc)
     {
-      if (DEBUGLEVEL>1) err_printf(".");
+      if (DEBUGLEVEL>3) err_printf(".");
       if ((nbtest & 0xff) == 0 && ++current > B->KC) current = 1;
       continue;
     }
@@ -637,7 +634,7 @@ imag_relations(struct buch_quad *B, long need, long *pc, ulong LIMC, GEN mat)
       GEN form2;
       if (!fpd)
       {
-        if (DEBUGLEVEL>1) err_printf(".");
+        if (DEBUGLEVEL>3) err_printf(".");
         continue;
       }
       form2 = qficomp(qfi_factorback(B,fpd), qfi_pf(B->QFR->D, B->FB[fpd[-2]]));
@@ -659,19 +656,19 @@ imag_relations(struct buch_quad *B, long need, long *pc, ulong LIMC, GEN mat)
         for (i=1; i<lgsub; i++) col[B->subFB[i]] += -fpd[i]-ex[i];
         add_fact(B, col, form2); col[fpd[-2]]--;
       }
-      if (DEBUGLEVEL) err_printf(" %ldP",s);
+      if (DEBUGLEVEL>2) err_printf(" %ldP",s);
     }
     else
     {
       col = gel(mat,++s);
       for (i=1; i<lgsub; i++) col[B->subFB[i]] = -ex[i];
       add_fact(B, col, form);
-      if (DEBUGLEVEL) err_printf(" %ld",s);
+      if (DEBUGLEVEL>2) err_printf(" %ld",s);
     }
     col[current]--;
     if (++current > B->KC) current = 1;
   }
-  if (DEBUGLEVEL) dbg_all(&T, "random", s, nbtest);
+  if (DEBUGLEVEL>2) dbg_all(&T, "random", s, nbtest);
   *pc = current;
 }
 
@@ -684,7 +681,7 @@ imag_be_honest(struct buch_quad *B)
 
   while (s<B->KC2)
   {
-    p = B->FB[s+1]; if (DEBUGLEVEL) err_printf(" %ld",p);
+    p = B->FB[s+1]; if (DEBUGLEVEL>2) err_printf(" %ld",p);
     F = qficomp(qfi_pf(B->QFR->D, p), qfi_random(B, ex));
     fpc = factorquad(B,F,s,p-1);
     if (fpc == 1) { nbtest=0; s++; }
@@ -706,19 +703,19 @@ real_relations(struct buch_quad *B, long need, long *pc, long lim, ulong LIMC, G
   /* in a 2nd phase, don't include FB[current] but run along the cyle
    * ==> get more units */
   int first = (current == 0);
-  pari_sp av, av1, limstack;
+  pari_sp av, av1;
   GEN d, col, form, form0, form1, ex = cgetg(lgsub, t_VECSMALL);
 
-  if (DEBUGLEVEL) timer_start(&T);
+  if (DEBUGLEVEL>2) timer_start(&T);
   if (!current) current = 1;
   if (lim > need) lim = need;
-  av = avma; limstack = stack_lim(av,1);
+  av = avma;
   for(;;)
   {
     if (s >= need) break;
     if (first && s >= lim) {
       first = 0;
-      if (DEBUGLEVEL) dbg_all(&T, "initial", s, nbtest);
+      if (DEBUGLEVEL>2) dbg_all(&T, "initial", s, nbtest);
     }
     avma = av; form = qfr3_random(B, ex);
     if (!first)
@@ -734,7 +731,7 @@ CYCLE:
       if (++current > B->KC) current = 1;
       continue;
     }
-    if (low_stack(limstack, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"real_relations");
       gerepileall(av1, form1? 2: 1, &form, &form1);
@@ -765,7 +762,7 @@ CYCLE:
     nbtest++; fpc = factorquad(B,form,B->KC,LIMC);
     if (!fpc)
     {
-      if (DEBUGLEVEL>1) err_printf(".");
+      if (DEBUGLEVEL>3) err_printf(".");
       goto CYCLE;
     }
     if (fpc > 1)
@@ -775,7 +772,7 @@ CYCLE:
       GEN form2;
       if (!fpd)
       {
-        if (DEBUGLEVEL>1) err_printf(".");
+        if (DEBUGLEVEL>3) err_printf(".");
         goto CYCLE;
       }
       if (!form1)
@@ -820,7 +817,7 @@ CYCLE:
         d = qfr5_dist(addii(gel(form1,4),gel(form2,4)),
                       mulrr(gel(form1,5),gel(form2,5)), prec);
       }
-      if (DEBUGLEVEL) err_printf(" %ldP",s);
+      if (DEBUGLEVEL>2) err_printf(" %ldP",s);
     }
     else
     { /* standard relation */
@@ -837,7 +834,7 @@ CYCLE:
       for (i=1; i<lgsub; i++) col[B->subFB[i]] = -ex[i];
       add_fact(B, col, form1);
       d = qfr5_dist(gel(form1,4), gel(form1,5), prec);
-      if (DEBUGLEVEL) err_printf(" %ld",s);
+      if (DEBUGLEVEL>2) err_printf(" %ld",s);
     }
     affrr(d, gel(C,s));
     if (first)
@@ -851,7 +848,7 @@ CYCLE:
       if (++current > B->KC) current = 1;
     }
   }
-  if (DEBUGLEVEL) dbg_all(&T, "random", s, nbtest);
+  if (DEBUGLEVEL>2) dbg_all(&T, "random", s, nbtest);
   *pc = current;
 }
 
@@ -864,7 +861,7 @@ real_be_honest(struct buch_quad *B)
 
   while (s<B->KC2)
   {
-    p = B->FB[s+1]; if (DEBUGLEVEL) err_printf(" %ld",p);
+    p = B->FB[s+1]; if (DEBUGLEVEL>2) err_printf(" %ld",p);
     F = QFR3_comp(qfr3_random(B, ex), qfr3_pf(B->QFR, p), B->QFR);
     for (F0 = F;;)
     {
@@ -922,10 +919,10 @@ get_R(struct buch_quad *B, GEN C, long sreg, GEN z, GEN *ptR)
     }
     if (gexpo(R) <= -3)
     {
-      if (DEBUGLEVEL) err_printf("regulator is zero.\n");
+      if (DEBUGLEVEL>2) err_printf("regulator is zero.\n");
       return fupb_RELAT;
     }
-    if (DEBUGLEVEL) err_printf("#### Tentative regulator: %Ps\n",R);
+    if (DEBUGLEVEL>2) err_printf("#### Tentative regulator: %Ps\n",R);
   }
   c = gtodouble(gmul(z, R));
   if (c < 0.8 || c > 1.3) return fupb_RELAT;
@@ -937,10 +934,10 @@ quad_be_honest(struct buch_quad *B)
 {
   int r;
   if (B->KC2 <= B->KC) return 1;
-  if (DEBUGLEVEL)
+  if (DEBUGLEVEL>2)
     err_printf("be honest for primes from %ld to %ld\n", B->FB[B->KC+1],B->FB[B->KC2]);
   r = B->PRECREG? real_be_honest(B): imag_be_honest(B);
-  if (DEBUGLEVEL) err_printf("\n");
+  if (DEBUGLEVEL>2) err_printf("\n");
   return r;
 }
 
@@ -973,11 +970,11 @@ Buchquad(GEN D, double cbach, double cbach2, long prec)
       gel(z,1) = gel(z,4) = gen_1; gel(z,2) = gel(z,3) = cgetg(1,t_VEC);
       return z;
     }
-    BQ.PRECREG = 0;
+    prec = BQ.PRECREG = 0;
   } else {
     BQ.PRECREG = maxss(prec+EXTRAPRECWORD, nbits2prec(2*expi(QFR.D) + 128));
   }
-  if (DEBUGLEVEL) timer_start(&T);
+  if (DEBUGLEVEL>2) timer_start(&T);
   BQ.primfact   = new_chunk(100);
   BQ.exprimfact = new_chunk(100);
   BQ.hashtab = (long**) new_chunk(HASHT);
@@ -1032,7 +1029,7 @@ START:
   do
   {
     if (!FIRST) LIMC = check_LIMC(LIMC,LIMCMAX);
-    if (DEBUGLEVEL && LIMC > LIMC0)
+    if (DEBUGLEVEL>2 && LIMC > LIMC0)
       err_printf("%s*** Bach constant: %f\n", FIRST?"":"\n", LIMC/LOGD2);
     FIRST = 0; avma = av;
     if (BQ.subFB) gunclone(BQ.subFB);
@@ -1043,17 +1040,17 @@ START:
     if (BQ.PRECREG) qfr_data_init(QFR.D, BQ.PRECREG, &QFR);
 
     FBquad(&BQ, LIMC2, LIMC, &GRHcheck);
-    if (DEBUGLEVEL) timer_printf(&T, "factor base");
+    if (DEBUGLEVEL>2) timer_printf(&T, "factor base");
     BQ.subFB = subFBquad(&BQ, QFR.D, lim + 0.5, minSFB);
-    if (DEBUGLEVEL) timer_printf(&T, "subFBquad = %Ps",
+    if (DEBUGLEVEL>2) timer_printf(&T, "subFBquad = %Ps",
                                  vecpermute(BQ.FB, BQ.subFB));
     nsubFB = lg(BQ.subFB) - 1;
   }
   while (nsubFB < (expi(D) > 15 ? 3 : 2));
   /* invhr = 2^r1 (2pi)^r2 / sqrt(D) w ~ L(chi,1) / hR */
-  invhr = gmul(dbltor((BQ.PRECREG?2.:PI)/sdrc), compute_invresquad(&GRHcheck));
+  invhr = gmul(dbltor((BQ.PRECREG?2.:M_PI)/sdrc), compute_invresquad(&GRHcheck));
   BQ.powsubFB = powsubFBquad(&BQ,CBUCH+1);
-  if (DEBUGLEVEL) timer_printf(&T, "powsubFBquad");
+  if (DEBUGLEVEL>2) timer_printf(&T, "powsubFBquad");
   BQ.limhash = (LIMC & HIGHMASK)? (HIGHBIT>>1): LIMC*LIMC;
 
   need = BQ.KC + RELSUP - 2;
@@ -1066,12 +1063,12 @@ START:
   do
   {
     if ((nreldep & 3) == 1 || (nrelsup & 7) == 1) {
-      if (DEBUGLEVEL) err_printf("*** Changing sub factor base\n");
+      if (DEBUGLEVEL>2) err_printf("*** Changing sub factor base\n");
       gunclone(BQ.subFB);
       gunclone(BQ.powsubFB);
       BQ.subFB = gclone(vecslice(BQ.vperm, 1, nsubFB));
       BQ.powsubFB = powsubFBquad(&BQ,CBUCH+1);
-      if (DEBUGLEVEL) timer_printf(&T, "powsubFBquad");
+      if (DEBUGLEVEL>2) timer_printf(&T, "powsubFBquad");
       clearhash(BQ.hashtab);
     }
     need += 2;
@@ -1080,10 +1077,10 @@ START:
     if (!W) { /* first time */
       C = extraC;
       triv = trivial_relations(&BQ, mat, C);
-      if (DEBUGLEVEL) err_printf("KC = %ld, need %ld relations\n", BQ.KC, need);
+      if (DEBUGLEVEL>2) err_printf("KC = %ld, need %ld relations\n", BQ.KC, need);
     } else {
       triv = 0;
-      if (DEBUGLEVEL) err_printf("...need %ld more relations\n", need);
+      if (DEBUGLEVEL>2) err_printf("...need %ld more relations\n", need);
     }
     if (BQ.PRECREG) {
       for (i = triv+1; i<=need; i++) {
@@ -1112,7 +1109,7 @@ START:
     }
 
     h = ZM_det_triangular(W);
-    if (DEBUGLEVEL) err_printf("\n#### Tentative class number: %Ps\n", h);
+    if (DEBUGLEVEL>2) err_printf("\n#### Tentative class number: %Ps\n", h);
 
     switch(get_R(&BQ, C, (lg(C)-1) - (lg(B)-1) - (lg(W)-1), mulir(h,invhr), &R))
     {
@@ -1132,11 +1129,11 @@ START:
   while (need);
   /* DONE */
   if (!quad_be_honest(&BQ)) goto START;
-  if (DEBUGLEVEL) timer_printf(&T, "be honest");
+  if (DEBUGLEVEL>2) timer_printf(&T, "be honest");
   clearhash(BQ.hashtab);
   free_GRHcheck(&GRHcheck);
 
-  gen = get_clgp(&BQ,W,&cyc,BQ.PRECREG);
+  gen = get_clgp(&BQ,W,&cyc,prec);
   gunclone(BQ.subFB);
   gunclone(BQ.powsubFB);
   res = cgetg(5,t_VEC);
diff --git a/src/basemath/buch2.c b/src/basemath/buch2.c
index 87a354a..09186b8 100644
--- a/src/basemath/buch2.c
+++ b/src/basemath/buch2.c
@@ -73,13 +73,11 @@ typedef struct FB_t {
   GEN subFB; /* LP o subFB =  part of FB used to build random relations */
   int sfb_chg; /* need to change subFB ? */
   int newpow; /* need to compute powFB */
-  int newarc; /* need to compute archimedean components */
   GEN perm; /* permutation of LP used to represent relations [updated by
                hnfspec/hnfadd: dense rows come first] */
   GEN vecG, G0;
   GEN idealperm; /* permutation of ideals under field automorphisms */
   GEN minidx; /* minidx[i] min ideal in orbit of LP[i] under field autom */
-  long orbits; /* number of ideal orbits */
   subFB_t *allsubFB; /* all subFB's used */
   GEN embperm; /* permutations of the complex embeddings */
   GEN invs; /* inverse of automorphism */
@@ -238,7 +236,6 @@ assign_subFB(FB_t *F, GEN yes, long iyes)
   for (i = 0; i < iyes; i++) sub->subFB[i] = yes[i];
   F->subFB = sub->subFB;
   F->newpow = 1;
-  F->newarc = 1;
 }
 
 /*
@@ -254,12 +251,10 @@ FB_aut_perm(FB_t *F, GEN nf, GEN auts, GEN cyclic)
   if (nauts == 1)
   {
     for (i = 1; i <= KC; i++) minidx[i] = i;
-    F->orbits = KC;
   }
   else
   {
     long j, m;
-    F->orbits = 0;
     for (m = 1; m < lg(cyclic); m++)
     {
       GEN thiscyc = gel(cyclic, m);
@@ -300,7 +295,6 @@ FB_aut_perm(FB_t *F, GEN nf, GEN auts, GEN cyclic)
     for (j = 1; j <= KC; j++)
     {
       if (minidx[j]) continue;
-      F->orbits++;
       minidx[j] = j;
       for (i = 1; i < nauts; i++) minidx[coeff(perm, j, i)] = j;
     }
@@ -440,12 +434,12 @@ pre_allocate(RELCACHE_t *cache, size_t n)
 void
 init_GRHcheck(GRHcheck_t *S, long N, long R1, double LOGD)
 {
-  const double c1 = PI*PI/2;
+  const double c1 = M_PI*M_PI/2;
   const double c2 = 3.663862376709;
   const double c3 = 3.801387092431; /* Euler + log(8*Pi)*/
   S->clone = 0;
   S->cN = R1*c2 + N*c1;
-  S->cD = LOGD - N*c3 - R1*PI/2;
+  S->cD = LOGD - N*c3 - R1*M_PI/2;
   S->maxprimes = 16000; /* sufficient for LIMC=176081*/
   S->primes = (GRHprime_t*)pari_malloc(S->maxprimes*sizeof(*S->primes));
   S->nprimes = 0;
@@ -536,18 +530,69 @@ cache_prime_dec(GRHcheck_t *S, ulong LIM, GEN nf)
   avma = av;
 }
 
-static GEN
-compute_invres(GRHcheck_t *S)
+static double
+tailresback(long LIMC, long LIMC2, long LIMC3, long R1, long R2, double rK, double r1K, double r2K, double logLIMC, double logLIMC2, double logLIMC3)
 {
-  pari_sp av = avma;
-  GEN invres = real_1(DEFAULTPREC);
-  GRHprime_t *pr = S->primes;
-  long i = S->nprimes, LIMC = GRH_last_prime(S)+diffptr[i]-1; /* nextprime(p+1)-1*/
-  double llimc = log(LIMC);
+  const double  rQ = 1.83787706641;
+  const double r1Q = 1.98505372441;
+  const double r2Q = 1.07991541347;
+  return fabs((R1+R2-1)*(12*logLIMC3+4*logLIMC2-9*logLIMC-6)/(2*LIMC*logLIMC3)
+         + (rK-rQ)*(6*logLIMC2 + 5*logLIMC + 2)/(LIMC*logLIMC3)
+         - R2*(6*logLIMC2+11*logLIMC+6)/(LIMC2*logLIMC2)
+         - 2*(r1K-r1Q)*(3*logLIMC2 + 4*logLIMC + 2)/(LIMC2*logLIMC3)
+         + (R1+R2-1)*(12*logLIMC3+40*logLIMC2+45*logLIMC+18)/(6*LIMC3*logLIMC3)
+         + (r2K-r2Q)*(2*logLIMC2 + 3*logLIMC + 2)/(LIMC3*logLIMC3));
+}
+
+static double
+tailres(long R1, long R2, double al2K, double rKm, double rKM, double r1Km, double r1KM, double r2Km, double r2KM, long LIMC)
+{
+  const double logLIMC = log(LIMC), logLIMC2 = logLIMC*logLIMC;
+  const double logLIMC3 = logLIMC*logLIMC2;
+  const double E1 = rtodbl(eint1(dbltor(logLIMC/2), DEFAULTPREC));
+  const long LIMC2 = LIMC*LIMC, LIMC3 = LIMC*LIMC2;
+  return
+    al2K*((33*logLIMC2+22*logLIMC+8)/(8*logLIMC3*sqrt(LIMC))+15*E1/16)
+     + maxdd(
+            tailresback(LIMC,LIMC2,LIMC3,R1,R2,rKm,r1KM,r2Km,logLIMC,logLIMC2,logLIMC3),
+            tailresback(LIMC,LIMC2,LIMC3,R1,R2,rKM,r1Km,r2KM,logLIMC,logLIMC2,logLIMC3)
+       )/2
+     + ((R1+R2-1)*4*LIMC+R2)*(LIMC2+6*logLIMC)/(4*LIMC2*LIMC2*logLIMC2);
+}
+
+static long
+primeneeded(long N, long R1, long R2, double LOGD)
+{
+  const double lim = 0.25; /* should be log(2)/2 == 0.34657... */
+  const double al2K =  0.3526*LOGD - 0.8212*N + 4.5007;
+  const double  rKm = -1.0155*LOGD + 2.1041*N - 8.3419;
+  const double  rKM = -0.5   *LOGD + 1.2076*N + 1;
+  const double r1Km = -       LOGD + 1.4150*N;
+  const double r1KM = -       LOGD + 1.9851*N;
+  const double r2Km = -       LOGD + 0.9151*N;
+  const double r2KM = -       LOGD + 1.0800*N;
+  long LIMCmin = 3, LIMCmax = 3, Ntest;
+  while (tailres(R1, R2, al2K, rKm, rKM, r1Km, r1KM, r2Km, r2KM, LIMCmax) > lim)
+  {
+    LIMCmin = LIMCmax;
+    LIMCmax *= 2;
+  }
+  while (LIMCmax - LIMCmin > 1)
+  {
+    Ntest = (LIMCmin + LIMCmax)/2;
+    if (tailres(R1, R2, al2K, rKm, rKM, r1Km, r1KM, r2Km, r2KM, Ntest) > lim)
+      LIMCmin = Ntest;
+    else
+      LIMCmax = Ntest;
+  }
+  return LIMCmax;
+}
+
+/*
   for (; i > 0; pr++, i--)
   {
     GEN dec, a = NULL, b = NULL, fs, ns;
-    long j, k, limp = llimc/pr->logp;
+    long j, k, limp = (long)(llimc/pr->logp);
     ulong p = pr->p;
     dec = pr->dec;
     fs = gel(dec, 1); ns = gel(dec, 2);
@@ -575,7 +620,72 @@ compute_invres(GRHcheck_t *S)
     else
       invres = divru(mulur(p, invres), p-1);
   }
-  return gerepileuptoleaf(av, invres);
+*/
+
+static GEN
+compute_invres(GRHcheck_t *S, long LIMC)
+{
+  pari_sp av = avma;
+  double loginvres = 0.;
+  GRHprime_t *pr;
+  long i;
+  double logLIMC = log(LIMC);
+  double logLIMC2 = logLIMC*logLIMC, denc;
+  double c0, c1, c2;
+  denc = 1/(pow(LIMC, 3) * logLIMC * logLIMC2);
+  c2 = (    logLIMC2 + 3 * logLIMC / 2 + 1) * denc;
+  denc *= LIMC;
+  c1 = (3 * logLIMC2 + 4 * logLIMC     + 2) * denc;
+  denc *= LIMC;
+  c0 = (3 * logLIMC2 + 5 * logLIMC / 2 + 1) * denc;
+  for (pr = S->primes, i = S->nprimes; i > 0; pr++, i--)
+  {
+    GEN dec, fs, ns;
+    long addpsi;
+    double addpsi1, addpsi2;
+    double logp = pr->logp, NPk;
+    long j, k, limp = logLIMC/logp;
+    ulong p = pr->p, p2 = p*p;
+    if (limp < 1) break;
+    dec = pr->dec;
+    fs = gel(dec, 1); ns = gel(dec, 2);
+    loginvres += 1./p;
+    /*
+     * note for optimization: limp == 1 nearly always and limp >= 3 for
+     * only very few primes.
+     */
+    for (k = 2, NPk = p; k <= limp; k++)
+    {
+      NPk *= p;
+      loginvres += 1/(k * NPk);
+    }
+    addpsi = limp;
+    addpsi1 = p *(pow(p , limp)-1)/(p -1);
+    addpsi2 = p2*(pow(p2, limp)-1)/(p2-1);
+    j = lg(fs);
+    while (--j > 0)
+    {
+      long f, nb, kmax;
+      double NP, NP2, addinvres;
+      f = fs[j]; if (f > limp) continue;
+      nb = ns[j];
+      NP = pow(p, f);
+      addinvres = 1/NP;
+      kmax = limp / f;
+      for (k = 2, NPk = NP; k <= kmax; k++)
+      {
+        NPk *= NP;
+        addinvres += 1/(k*NPk);
+      }
+      NP2 = NP*NP;
+      loginvres -= nb * addinvres;
+      addpsi -= nb * f * kmax;
+      addpsi1 -= nb*(f*NP *(pow(NP ,kmax)-1)/(NP -1));
+      addpsi2 -= nb*(f*NP2*(pow(NP2,kmax)-1)/(NP2-1));
+    }
+    loginvres -= (addpsi*c0 - addpsi1*c1 + addpsi2*c2)*logp;
+  }
+  return gerepileuptoleaf(av, mpexp(dbltor(loginvres)));
 }
 
 static long
@@ -644,7 +754,6 @@ FBgen(FB_t *F, GEN nf, long N, ulong C1, ulong C2, GRHcheck_t *S)
   for (;; pr++) /* p <= C2 */
   {
     ulong p = pr->p;
-    pari_sp av = avma;
     long k, l, m;
     GEN LP, nb, f;
 
@@ -658,27 +767,20 @@ FBgen(FB_t *F, GEN nf, long N, ulong C1, ulong C2, GRHcheck_t *S)
     /* compute l such that p^f <= C2  <=> f <= l */
     l = (long)(L/pr->logp);
     for (k=0, m=1; m < lg(f) && f[m]<=l; m++) k += nb[m];
-
-    prim[2] = p; LP = idealprimedec(nf,prim);
-    /* keep non-inert ideals with Norm <= C2 */
-    for (m = 1; m <= k; m++)
+    if (!k) /* p too inert to appear in FB */
     {
-      GEN t = gel(LP,m);
-      gel(t,5) = zk_scalar_or_multable(nf, gel(t,5));
+      if (p == C2) break;
+      continue;
     }
-    if (m == lg(LP))
-      setisclone(LP); /* flag it: all prime divisors in FB */
-    else
-      { setlg(LP,k+1); LP = gerepilecopy(av,LP); }
+    prim[2] = p; LP = idealprimedec_limit_f(nf,prim, l);
+    /* keep non-inert ideals with Norm <= C2 */
+    if (m == lg(f)) setisclone(LP); /* flag it: all prime divisors in FB */
     F->FB[++i]= p;
     F->LV[p]  = LP;
     F->iLP[p] = ip; ip += k;
-    if (p == C2)
-    {
-      if (!F->KC) { F->KCZ = i; F->KC = ip; }
-      break;
-    }
+    if (p == C2) break;
   }
+  if (!F->KC) { F->KCZ = i; F->KC = ip; }
   /* Note F->KC > 0 otherwise GRHchk is false */
   setlg(F->FB, F->KCZ+1); F->KCZ2 = i;
   if (DEBUGLEVEL>1)
@@ -801,15 +903,23 @@ smooth_norm(FB_t *F, GEN *N, GEN *ex)
 {
   GEN FB = F->FB;
   const long KCZ = F->KCZ;
-  const ulong limp = (ulong)FB[KCZ]; /* last p in FB */
+  const ulong limp = uel(FB,KCZ); /* last p in FB */
   long i;
 
   *ex = new_chunk(KCZ+1);
   for (i=1; ; i++)
   {
     int stop;
-    (*ex)[i] = Z_lvalrem_stop(N, (ulong)FB[i], &stop);
-    if (stop) break;
+    ulong p = uel(FB,i);
+    long v = Z_lvalrem_stop(N, p, &stop);
+    (*ex)[i] = v;
+    if (v)
+    {
+      GEN LP = F->LV[p];
+      if(!LP) pari_err_BUG("can_factor");
+      if (lg(LP) == 1) return 0;
+      if (stop) break;
+    }
     if (i == KCZ) return 0;
   }
   (*ex)[0] = i;
@@ -821,11 +931,6 @@ divide_p(FB_t *F, long p, long k, GEN nf, GEN I, GEN m, FACT *fact)
 {
   GEN LP = F->LV[p];
   long ip = F->iLP[p];
-  if (!LP)
-  {
-    if (!I) pari_err_BUG("divide_p");
-    pari_err_TYPE("divide_p [not an ideal]", I);
-  }
   if (!m) return divide_p_id (LP,ip,k,nf,I,fact);
   if (!I) return divide_p_elt(LP,ip,k,nf,m,fact);
   return divide_p_quo(LP,ip,k,nf,I,m,fact);
@@ -1305,7 +1410,7 @@ testprimes(GEN bnf, GEN BOUND)
 {
   pari_sp av0 = avma, av;
   ulong pmax, count = 0;
-  GEN Vbase, fb, p, nf = bnf_get_nf(bnf), dK = nf_get_disc(nf);
+  GEN Vbase, fb, p, nf = bnf_get_nf(bnf);
   forprime_t S;
   FACT *fact;
   FB_t F;
@@ -1344,21 +1449,16 @@ testprimes(GEN bnf, GEN BOUND)
     }
 
     avma = av;
-    vP = idealprimedec(bnf, p);
-    l = lg(vP);
+    vP = idealprimedec_limit_norm(bnf, p, BOUND);
+    l = lg(vP); if (l == 1) continue;
     if (DEBUGLEVEL>1) err_printf("*** p = %Ps\n",p);
-    /* loop through all P | p if ramified, all but one otherwise */
-    if (!dvdii(dK,p)) l--;
-    for (i=1; i<l; i++)
+    /* if vP[1] unramified, skip it */
+    i = (pr_get_e(gel(vP,1))) == 1? 2: 1;
+    for (; i<l; i++)
     {
       GEN P = gel(vP,i);
       long k;
       if (DEBUGLEVEL>1) err_printf("  Testing P = %Ps\n",P);
-      if (cmpii(pr_norm(P), BOUND) >= 0)
-      {
-        if (DEBUGLEVEL>1) err_printf("    Norm(P) > Zimmert bound\n");
-        break;
-      }
       if (cmpiu(p, pmax) <= 0 && (k = tablesearch(fb, P, &cmp_prime_ideal)))
       { if (DEBUGLEVEL>1) err_printf("    #%ld in factor base\n",k); }
       else if (DEBUGLEVEL>1)
@@ -1456,7 +1556,7 @@ scalar_get_arch_real(GEN nf, GEN u, GEN *emb)
 }
 
 static int
-low_prec(GEN x) { return gequal0(x) || (typ(x) == t_REAL && realprec(x) <= LOWDEFAULTPREC); }
+low_prec(GEN x) { return gequal0(x) || (typ(x) == t_REAL && realprec(x) <= DEFAULTPREC); }
 
 /* For internal use. Get archimedean components: [e_i log( | sigma_i(x) | )],
  * with e_i = 1 (resp 2.) for i <= R1 (resp. > R1)
@@ -1547,18 +1647,28 @@ act_arch(GEN A, GEN x)
     return a;
   }
   if (l==1) return cgetg(1, t_VEC);
+  a = NULL;
   if (tA == t_VECSMALL)
   {
-    a = gmulsg(A[1], gel(x,1));
-    for (i=2; i<l; i++)
-      if (A[i]) a = gadd(a, gmulsg(A[i], gel(x,i)));
+    for (i=1; i<l; i++)
+    {
+      long c = A[i];
+      if (!c) continue;
+      if (!a) { a = gmulsg(c, gel(x,i)); continue; }
+      a = gadd(a, gmulsg(c, gel(x,i)));
+    }
   }
   else
   { /* A a t_COL of t_INT. Assume lg(A)==lg(x) */
-    a = gmul(gel(A,1), gel(x,1));
-    for (i=2; i<l; i++)
-      if (signe(gel(A,i))) a = gadd(a, gmul(gel(A,i), gel(x,i)));
+    for (i=1; i<l; i++)
+    {
+      GEN c = gel(A,i);
+      if (!signe(c)) continue;
+      if (!a) { a = gmul(c, gel(x,i)); continue; }
+      a = gadd(a, gmul(gel(A,i), gel(x,i)));
+    }
   }
+  if (!a) return zerovec(lgcols(x)-1);
   settyp(a, t_VEC); return a;
 }
 
@@ -2156,7 +2266,7 @@ set_fact(FB_t *F, FACT *fact, GEN ex, long *pnz)
   long nz;
   GEN c = zero_Flv(F->KC);
   if (!n) /* trivial factorization */
-    *pnz = F->KC;
+    *pnz = F->KC+1;
   else {
     nz = fact[1].pr;
     if (fact[n].pr < nz) /* Possible with jid in rnd_rel */
@@ -2203,6 +2313,7 @@ add_rel_i(RELCACHE_t *cache, GEN R, long nz, GEN m, long orig, long aut, REL_t *
 {
   long i, k, n = lg(R)-1;
 
+  if (nz == n+1) { k = 0; goto ADD_REL; }
   if (already_known(cache, nz, R)) return -1;
   if (cache->last >= cache->base + cache->len) return 0;
   if (DEBUGLEVEL>6)
@@ -2227,7 +2338,7 @@ add_rel_i(RELCACHE_t *cache, GEN R, long nz, GEN m, long orig, long aut, REL_t *
       }
       else
       {
-        ulong invak = Fl_inv((ulong)a[k], mod_p);
+        ulong invak = Fl_inv(uel(a,k), mod_p);
         /* Cleanup a */
         for (i = k; i-- > 1; )
         {
@@ -2264,8 +2375,9 @@ add_rel_i(RELCACHE_t *cache, GEN R, long nz, GEN m, long orig, long aut, REL_t *
   {
     REL_t *rel;
 
+ADD_REL:
     rel = ++cache->last;
-    if (!k && cache->relsup)
+    if (!k && cache->relsup && nz < n+1)
     {
       cache->relsup--;
       k = (rel - cache->base) + cache->missing;
@@ -2417,7 +2529,7 @@ Fincke_Pohst_ideal(RELCACHE_t *cache, FB_t *F, GEN nf, GEN M,
   double BOUND;
   long j, k, skipfirst, nbrelideal=0, dependent=0, try_elt=0,  try_factor=0;
 
-  u = ZM_lll(ZM_mul(F->G0, ideal0), 0.99, LLL_IM);
+  u = ZM_lll(ZM_mul(F->G0, ideal0), 0.99, LLL_IM|LLL_COMPATIBLE);
   ideal = ZM_mul(ideal0,u); /* approximate T2-LLL reduction */
   r = gaussred_from_QR(RgM_mul(G, ideal), prec); /* Cholesky for T2 | ideal */
   if (!r) pari_err_BUG("small_norm (precision too low)");
@@ -2525,15 +2637,15 @@ Fincke_Pohst_ideal(RELCACHE_t *cache, FB_t *F, GEN nf, GEN M,
 }
 
 static void
-small_norm(RELCACHE_t *cache, FB_t *F, GEN nf, long nbrelpid,
-           double LOGD, double LIMC2, FACT *fact, GEN p0)
+small_norm(RELCACHE_t *cache, FB_t *F, GEN nf, long nbrelpid, GEN M,
+           FACT *fact, GEN p0)
 {
   pari_timer T;
-  const long N = nf_get_degree(nf), prec = nf_get_prec(nf);
+  const long prec = nf_get_prec(nf);
   FP_t fp;
   pari_sp av;
-  GEN M = nf_get_M(nf), G = nf_get_G(nf), L_jid = F->L_jid;
-  long nbsmallnorm, nbfact, precbound, noideal = lg(L_jid);
+  GEN G = nf_get_G(nf), L_jid = F->L_jid;
+  long nbsmallnorm, nbfact, noideal = lg(L_jid);
   REL_t *last = cache->last;
 
   if (DEBUGLEVEL)
@@ -2544,16 +2656,7 @@ small_norm(RELCACHE_t *cache, FB_t *F, GEN nf, long nbrelpid,
   }
   nbsmallnorm = nbfact = 0;
 
- /* LLL reduction produces v0 in I such that
-  *     T2(v0) <= (4/3)^((n-1)/2) NI^(2/n) disc(K)^(1/n)
-  * We consider v with T2(v) <= BMULT * T2(v0)
-  * Hence Nv <= ((4/3)^((n-1)/2) * BMULT / n)^(n/2) NI sqrt(disc(K)) */
-  precbound = nbits2prec( BITS_IN_LONG + (long)ceil(
-    (N/2. * ((N-1)/2.* log(4./3) + log(BMULT/(double)N)) + log(LIMC2) + LOGD/2)
-      / LOG2)); /* enough to compute norms */
-  if (precbound < prec) M = gprec_w(M, precbound);
-
-  minim_alloc(N+1, &fp.q, &fp.x, &fp.y, &fp.z, &fp.v);
+  minim_alloc(lg(M), &fp.q, &fp.x, &fp.y, &fp.z, &fp.v);
   for (av = avma; --noideal; avma = av)
   {
     GEN ideal=gel(F->LP,L_jid[noideal]);
@@ -2623,7 +2726,7 @@ rnd_rel(RELCACHE_t *cache, FB_t *F, GEN nf, FACT *fact)
   RNDREL_t rr;
   FP_t fp;
   const long nbG = lg(F->vecG)-1, lgsub = lg(F->subFB), l_jid = lg(L_jid);
-  const long N = nf_get_degree(nf), prec = nf_get_prec(nf);
+  const long prec = nf_get_prec(nf);
   long jlist;
   pari_sp av;
 
@@ -2637,7 +2740,7 @@ rnd_rel(RELCACHE_t *cache, FB_t *F, GEN nf, FACT *fact)
   baseideal = get_random_ideal(F, nf, rr.ex);
   baseideal = red(nf, baseideal, F->G0, &rr.m1);
   baseideal = idealhnf_two(nf, baseideal);
-  minim_alloc(N+1, &fp.q, &fp.x, &fp.y, &fp.z, &fp.v);
+  minim_alloc(lg(M), &fp.q, &fp.x, &fp.y, &fp.z, &fp.v);
   for (av = avma, jlist = 1; jlist < l_jid; jlist++, avma = av)
   {
     long j;
@@ -2650,7 +2753,7 @@ rnd_rel(RELCACHE_t *cache, FB_t *F, GEN nf, FACT *fact)
     if (DEBUGLEVEL>1)
       err_printf("\n*** Ideal no %ld: %Ps\n", rr.jid, vecslice(ideal,1,4));
     else if (DEBUGLEVEL)
-      err_printf("(%ld) ", jlist, rr.jid);
+      err_printf("(%ld) ", rr.jid);
     ideal = idealmul_HNF(nf, baseideal, ideal);
     rr.Nideal = ZM_det_triangular(ideal);
     if (Fincke_Pohst_ideal(cache, F, nf, M, G, ideal, fact,
@@ -3136,22 +3239,18 @@ makecycgen(GEN bnf)
 }
 
 static GEN
-get_y(GEN bnf, GEN pFB, long j)
-{
-  GEN W, B, nf, WB_C, ex, C, Nx, y;
-  long lW, e;
-
-  W   = gel(bnf,1);
-  B   = gel(bnf,2);
-  WB_C= gel(bnf,4);
-  nf  = bnf_get_nf(bnf);
-  lW=lg(W)-1;
-
-  ex = (j<=lW)? gel(W,j): gel(B,j-lW);
-  C = (j<=lW)? NULL: gel(pFB,j);
-  Nx = get_norm_fact_primes(pFB, ex, C);
-  y = isprincipalarch(bnf,gel(WB_C,j), Nx,gen_1, gen_1, &e);
-  if (y && fact_ok(nf,y,C,pFB,ex)) return y;
+get_y(GEN bnf, GEN W, GEN B, GEN WB_C, GEN pFB, long j)
+{
+  GEN y, nf  = bnf_get_nf(bnf);
+  long e, lW = lg(W)-1;
+  GEN ex = (j<=lW)? gel(W,j): gel(B,j-lW);
+  GEN C = (j<=lW)? NULL: gel(pFB,j);
+  if (WB_C)
+  { /* archimedean embeddings known: cheap trial */
+    GEN Nx = get_norm_fact_primes(pFB, ex, C);
+    y = isprincipalarch(bnf,gel(WB_C,j), Nx,gen_1, gen_1, &e);
+    if (y && fact_ok(nf,y,C,pFB,ex)) return y;
+  }
   y = isprincipalfact_or_fail(bnf, C, pFB, ex);
   return typ(y) == t_INT? y: gel(y,2);
 }
@@ -3159,33 +3258,33 @@ get_y(GEN bnf, GEN pFB, long j)
 static GEN
 makematal(GEN bnf)
 {
-  GEN W, B, pFB, ma, retry;
+  GEN W, B, WB_C, pFB, ma, retry;
   long lma, j, prec = 0;
 
   if (DEBUGLEVEL) pari_warn(warner,"completing bnf (building matal)");
-  W   = gel(bnf,1);
-  B   = gel(bnf,2);
+  W = gel(bnf,1);
+  B = gel(bnf,2);
+  WB_C= gel(bnf,4);
   lma=lg(W)+lg(B)-1;
   pFB = get_Vbase(bnf);
   ma = cgetg(lma,t_VEC);
-  retry = vectrunc_init(lma);
+  retry = vecsmalltrunc_init(lma);
   for (j=lma-1; j>0; j--)
   {
-    pari_sp av0 = avma, av;
-    GEN c = getrand(), y;
-    av = avma; y = get_y(bnf, pFB, j);
+    pari_sp av = avma;
+    GEN y = get_y(bnf,W,B,WB_C, pFB, j);
     if (typ(y) == t_INT)
     {
       long E = itos(y);
       if (DEBUGLEVEL>1) err_printf("\n%ld done later at prec %ld\n",j,E);
       avma = av;
-      vectrunc_append(retry, mkvec2(c, (GEN)j));
+      vecsmalltrunc_append(retry, j);
       if (E > prec) prec = E;
     }
     else
     {
       if (DEBUGLEVEL>1) err_printf("%ld ",j);
-      gel(ma,j) = gerepileupto(av0,y);
+      gel(ma,j) = gerepileupto(av,y);
     }
   }
   if (prec)
@@ -3199,10 +3298,8 @@ makematal(GEN bnf)
     for (k=1; k<l; k++)
     {
       pari_sp av = avma;
-      GEN S = gel(retry,k), c = gel(S,1);
-      long j = S[2];
-      setrand(c);
-      y = get_y(bnf, pFB, j);
+      long j = retry[k];
+      y = get_y(bnf,W,B,NULL, pFB, j);
       if (typ(y) == t_INT) pari_err_PREC("makematal");
       if (DEBUGLEVEL>1) err_printf("%ld ",j);
       gel(ma,j) = gerepileupto(av,y);
@@ -3253,6 +3350,7 @@ get_archclean(GEN nf, GEN x, long prec, int units)
       c = cleanarch(c, N, prec);
       if (!c) return NULL;
     }
+    settyp(c,t_COL);
     gel(M,k) = gerepilecopy(av, c);
   }
   return M;
@@ -3559,6 +3657,62 @@ init_rel(RELCACHE_t *cache, FB_t *F, long add_need)
   }
 }
 
+/* Let z = \zeta_n in nf. List of not-obviously-dependent generators for
+ * cyclotomic units modulo torsion in Q(z) [independent when n a prime power]:
+ * - z^a - 1,  n/(a,n) not a prime power, a \nmid n unless a=1,  1 <= a < n/2
+ * - (Z^a - 1)/(Z - 1),  p^k || n, Z = z^{n/p^k}, (p,a) = 1, 1 < a <= (p^k-1)/2
+ */
+static GEN
+cyclotomic_units(GEN nf, GEN zu)
+{
+  long n = itos(gel(zu, 1)), n2, lP, i, a;
+  GEN z, fa, P, E, L, mz, powz;
+  if (n <= 6) return cgetg(1, t_VEC);
+
+  z = algtobasis(nf,gel(zu, 2));
+  if ((n & 3) == 2) { n = n >> 1; z = ZC_neg(z); } /* ensure n != 2 (mod 4) */
+  n2 = n/2;
+  mz = zk_multable(nf, z); /* multiplication by z */
+  powz = cgetg(n2, t_VEC); gel(powz,1) = z;
+  for (i = 2; i < n2; i++) gel(powz,i) = ZM_ZC_mul(mz, gel(powz,i-1));
+  /* powz[i] = z^i */
+
+  L = vectrunc_init(n);
+  fa = factoru(n);
+  P = gel(fa,1); lP = lg(P);
+  E = gel(fa,2);
+  for (i = 1; i < lP; i++)
+  { /* second kind */
+    long p = P[i], k = E[i], pk = upowuu(p,k), pk2 = (pk-1) / 2;
+    GEN u = gen_1;
+    for (a = 2; a <= pk2; a++)
+    {
+      u = nfadd(nf, u, gel(powz, (n/pk) * (a-1))); /* = (Z^a-1)/(Z-1) */
+      if (a % p) vectrunc_append(L, u);
+    }
+  }
+  if (lP > 2) for (a = 1; a < n2; a++)
+  { /* first kind, when n not a prime power */
+    ulong p;
+    if (a > 1 && (n % a == 0 || uisprimepower(n/ugcd(a,n), &p))) continue;
+    vectrunc_append(L, nfadd(nf, gel(powz, a), gen_m1));
+  }
+  return L;
+}
+static void
+add_cyclotomic_units(GEN nf, GEN zu, RELCACHE_t *cache, FB_t *F)
+{
+  pari_sp av = avma;
+  GEN L = cyclotomic_units(nf, zu);
+  long i, l = lg(L);
+  if (l > 1)
+  {
+    GEN R = zero_Flv(F->KC);
+    for(i = 1; i < l; i++) add_rel(cache, F, R, F->KC+1, gel(L,i), 0);
+  }
+  avma = av;
+}
+
 static void
 shift_embed(GEN G, GEN Gtw, long a, long r1)
 {
@@ -3773,11 +3927,12 @@ Buchall_param(GEN P, double cbach, double cbach2, long nbrelpid, long flun, long
   pari_timer T;
   pari_sp av0 = avma, av, av2;
   long PRECREG, N, R1, R2, RU, low, high, LIMC0, LIMC, LIMC2, LIMCMAX, zc, i;
+  long LIMres;
   long MAXDEPSIZESFB, MAXDEPSFB;
   long nreldep, sfb_trials, need, old_need, precdouble = 0, precadd = 0;
-  long done_small, small_fail, fail_limit, squash_index;
+  long done_small, small_fail, fail_limit, squash_index, small_norm_prec;
   double lim, drc, LOGD, LOGD2;
-  GEN computed = NULL, zu, nf, D, A, W, R, h, PERM, fu = NULL /*-Wall*/;
+  GEN computed = NULL, zu, nf, M_sn, D, A, W, R, h, PERM, fu = NULL /*-Wall*/;
   GEN small_multiplier;
   GEN res, L, invhr, B, C, C0, lambda, dep, clg1, clg2, Vbase;
   GEN auts, cyclic;
@@ -3819,7 +3974,7 @@ Buchall_param(GEN P, double cbach, double cbach2, long nbrelpid, long flun, long
   D = absi(nf_get_disc(nf)); drc = gtodouble(D);
   if (DEBUGLEVEL) err_printf("R1 = %ld, R2 = %ld\nD = %Ps\n",R1,R2, D);
   LOGD = log(drc); LOGD2 = LOGD*LOGD;
-  lim = exp(-N + R2 * log(4/PI)) * sqrt(2*PI*N*drc);
+  lim = exp(-N + R2 * log(4/M_PI)) * sqrt(2*M_PI*N*drc);
   if (lim < 3.) lim = 3.;
   if (cbach > 12.) {
     if (cbach2 < cbach) cbach2 = cbach;
@@ -3832,8 +3987,6 @@ Buchall_param(GEN P, double cbach, double cbach2, long nbrelpid, long flun, long
   init_GRHcheck(&GRHcheck, N, R1, LOGD);
   high = low = LIMC0 = maxss((long)(cbach2*LOGD2), 1);
   LIMCMAX = (long)(12.*LOGD2);
-  /* 97/1223 below to ensure a good enough approximation of residue */
-  cache_prime_dec(&GRHcheck, expi(D) < 16 ? 97: 1223, nf);
   while (!GRHchk(nf, &GRHcheck, high))
   {
     low = high;
@@ -3856,9 +4009,17 @@ Buchall_param(GEN P, double cbach, double cbach2, long nbrelpid, long flun, long
   if (LIMC2 < nthideal(&GRHcheck, nf, 1)) class1 = 1;
   if (DEBUGLEVEL && class1) err_printf("Class 1\n", LIMC2);
   LIMC0 = (long)(cbach*LOGD2);
-  av = avma; LIMC = cbach ? LIMC0 : LIMC2;
+  LIMC = cbach ? LIMC0 : LIMC2;
   LIMC = maxss(LIMC, nthideal(&GRHcheck, nf, N));
   if (DEBUGLEVEL) timer_printf(&T, "computing Bach constant");
+  LIMres = primeneeded(N, R1, R2, LOGD);
+  cache_prime_dec(&GRHcheck, LIMres, nf);
+  /* invhr ~ 2^r1 (2pi)^r2 / sqrt(D) w * Res(zeta_K, s=1) = 1 / hR */
+  invhr = gmul(gdiv(gmul2n(powru(mppi(DEFAULTPREC), R2), RU),
+              mulri(gsqrt(D,DEFAULTPREC),gel(zu,1))),
+              compute_invres(&GRHcheck, LIMres));
+  if (DEBUGLEVEL) timer_printf(&T, "computing inverse of hR");
+  av = avma;
 
 START:
   if (DEBUGLEVEL) timer_start(&T);
@@ -3884,6 +4045,25 @@ START:
   FBgen(&F, nf, N, LIMC, LIMC2, &GRHcheck);
   if (!F.KC) goto START;
   av = avma;
+ /* In small_norm, LLL reduction produces v0 in I such that
+  *     T2(v0) <= (4/3)^((n-1)/2) NI^(2/n) disc(K)^(1/n)
+  * We consider v with T2(v) <= BMULT * T2(v0)
+  * Hence Nv <= ((4/3)^((n-1)/2) * BMULT / n)^(n/2) NI sqrt(disc(K)).
+  * NI <= LIMC2^2 */
+  small_norm_prec = nbits2prec( BITS_IN_LONG + (long)ceil(
+    (N/2. * ((N-1)/2.*log(4./3) + log(BMULT/(double)N)) + 2*log(LIMC2) + LOGD/2)
+      / LOG2)); /* enough to compute norms */
+  if (small_norm_prec > PRECREG)
+  {
+    GEN nf0 = nf;
+    PRECREG = small_norm_prec;
+    nf = gclone( nfnewprec_shallow(nf, PRECREG) );
+    if (precdouble) gunclone(nf0);
+    precdouble++;
+  }
+  M_sn = nf_get_M(nf);
+  if (small_norm_prec < PRECREG) M_sn = gprec_w(M_sn, small_norm_prec);
+  else if (precdouble) M_sn = gcopy(M_sn);
   subFBgen(&F,nf,auts,cyclic,mindd(lim,LIMC2) + 0.5,MINSFB);
   if (DEBUGLEVEL)
   {
@@ -3893,9 +4073,6 @@ START:
     else
       timer_printf(&T, "factorbase (no subFB) and ideal permutations");
   }
-  /* invhr ~ 2^r1 (2pi)^r2 / sqrt(D) w = Res(zeta_K, s=1) / hR */
-  invhr = gmul(gdiv(gmul2n(powru(mppi(DEFAULTPREC), R2), RU),
-              mulri(gsqrt(D,DEFAULTPREC),gel(zu,1))),compute_invres(&GRHcheck));
   fact = (FACT*)stack_malloc((F.KC+1)*sizeof(FACT));
   PERM = leafcopy(F.perm); /* to be restored in case of precision increase */
   cache.basis = zero_Flm_copy(F.KC,F.KC);
@@ -3909,6 +4086,8 @@ START:
   av2 = avma;
   init_rel(&cache, &F, RELSUP + RU-1); /* trivial relations */
   old_need = need = cache.end - cache.last;
+  add_cyclotomic_units(nf, zu, &cache, &F);
+  cache.end = cache.last + need;
 
   W = NULL; zc = 0;
   sfb_trials = nreldep = 0;
@@ -3984,7 +4163,7 @@ START:
           }
         }
         if (lg(F.L_jid) > 1)
-          small_norm(&cache, &F, nf, nbrelpid, LOGD, LIMC2, fact, p0);
+          small_norm(&cache, &F, nf, nbrelpid, M_sn, fact, p0);
         avma = av3;
         if (!A && cache.last != last)
           small_fail = 0;
@@ -4043,7 +4222,6 @@ START:
         if (precdouble) gunclone(nf0);
         precdouble++; precpb = NULL;
 
-        F.newarc = 1;
         for (i = 1; i < lg(PERM); i++) F.perm[i] = PERM[i];
         cache.chk = cache.base; W = NULL; /* recompute arch components+reduce */
       }
@@ -4189,7 +4367,7 @@ START:
       }
       /* arch. components of fund. units */
       H = ZM_hnflll(L, &U, 1); U = vecslice(U, lg(U)-(RU-1), lg(U)-1);
-      U = ZM_mul(U, ZM_lll(H, 0.99, LLL_IM));
+      U = ZM_mul(U, ZM_lll(H, 0.99, LLL_IM|LLL_COMPATIBLE));
       AU = RgM_mul(A, U);
       A = cleanarch(AU, N, PRECREG);
       if (DEBUGLEVEL) timer_printf(&T, "cleanarch");
diff --git a/src/basemath/buch3.c b/src/basemath/buch3.c
index 9af8d7d..c83ac28 100644
--- a/src/basemath/buch3.c
+++ b/src/basemath/buch3.c
@@ -757,13 +757,13 @@ is_unit(GEN M, long r1, GEN x)
 }
 
 /* FIXME: should use smallvectors */
-static GEN
+static double
 minimforunits(GEN nf, long BORNE, ulong w)
 {
   const long prec = MEDDEFAULTPREC;
-  long n, r1, i, j, k, s, *x, cnt = 0;
+  long n, r1, i, j, k, *x, cnt = 0;
   pari_sp av = avma;
-  GEN u, r, M;
+  GEN r, M;
   double p, norme, normin, normax;
   double **q,*v,*y,*z;
   double eps=0.000001, BOUND = BORNE * 1.00001;
@@ -783,8 +783,8 @@ minimforunits(GEN nf, long BORNE, ulong w)
     v[j] = gtodouble(gcoeff(r,j,j));
     for (i=1; i<j; i++) q[i][j] = gtodouble(gcoeff(r,i,j));
   }
-  normax = 0.; normin = (double)BOUND;
-  s=0; k=n; y[n]=z[n]=0;
+  normax = 0.; normin = (double)BORNE*(1-eps);
+  k=n; y[n]=z[n]=0;
   x[n] = (long)(sqrt(BOUND/v[n]));
 
   for(;;x[1]--)
@@ -812,25 +812,22 @@ minimforunits(GEN nf, long BORNE, ulong w)
     if (!x[1] && y[1]<=eps) break;
 
     if (DEBUGLEVEL>8){ err_printf("."); err_flush(); }
-    if (++cnt == 5000) return NULL; /* too expensive */
+    if (++cnt == 5000) return -1.; /* too expensive */
 
-    p = (double)x[1] + z[1]; norme = y[1] + p*p*v[1] + eps;
-    if (norme > normax) normax = norme;
+    p = (double)x[1] + z[1]; norme = y[1] + p*p*v[1];
+    if (norme+eps > normax) normax = norme;
     if (is_unit(M, r1, x)
     && (norme > 2*n  /* exclude roots of unity */
         || !ZV_isscalar(nfpow_u(nf, zc_to_ZC(x), w))))
     {
-      if (norme < normin) normin = norme;
+      if (norme < normin) normin = norme*(1-eps);
       if (DEBUGLEVEL>=2) { err_printf("*"); err_flush(); }
     }
 
   }
   if (DEBUGLEVEL>=2){ err_printf("\n"); err_flush(); }
-  avma = av; u = cgetg(4,t_VEC);
-  gel(u,1) = stoi(s<<1);
-  gel(u,2) = dbltor(normax);
-  gel(u,3) = dbltor(normin);
-  return u;
+  avma = av;
+  return normin;
 }
 
 #undef NBMAX
@@ -851,10 +848,10 @@ compute_M0(GEN M_star,long N)
   long bitprec = 24;
 
   if (N == 2) return gmul2n(sqrr(gacosh(gmul2n(M_star,-1),0)), -1);
-  vM = fetch_var(); M = pol_x(vM);
-  vz = fetch_var(); Z = pol_x(vz);
-  vy = fetch_var(); Y = pol_x(vy);
   vx = fetch_var(); X = pol_x(vx);
+  vy = fetch_var(); Y = pol_x(vy);
+  vz = fetch_var(); Z = pol_x(vz);
+  vM = fetch_var(); M = pol_x(vM);
 
   M0 = NULL; m1 = N/3;
   for (n1=1; n1<=m1; n1++) /* 1 <= n1 <= n2 <= n3 < N */
@@ -987,7 +984,8 @@ static GEN
 lowerboundforregulator(GEN bnf, GEN units)
 {
   long i, N, R2, RU = lg(units)-1;
-  GEN nf, M0, M, G, bound, minunit, vecminim;
+  GEN nf, M0, M, G, minunit;
+  double bound;
 
   if (!RU) return gen_1;
   nf = bnf_get_nf(bnf);
@@ -1003,11 +1001,10 @@ lowerboundforregulator(GEN bnf, GEN units)
   }
   if (gexpo(minunit) > 30) return NULL;
 
-  vecminim = minimforunits(nf, itos(gceil(minunit)), bnf_get_tuN(bnf));
-  if (!vecminim) return NULL;
-  bound = gel(vecminim,3);
-  if (DEBUGLEVEL>1) err_printf("M* = %Ps\n", bound);
-  M0 = compute_M0(bound, N);
+  bound = minimforunits(nf, itos(gceil(minunit)), bnf_get_tuN(bnf));
+  if (bound < 0) return NULL;
+  if (DEBUGLEVEL>1) err_printf("M* = %Ps\n", dbltor(bound));
+  M0 = compute_M0(dbltor(bound), N);
   if (DEBUGLEVEL>1) { err_printf("M0 = %.28Pg\n",M0); err_flush(); }
   M = gmul2n(divru(gdiv(powrs(M0,RU),hermiteconstant(RU)),N),R2);
   if (cmprr(M, dbltor(0.04)) < 0) return NULL;
@@ -1046,14 +1043,11 @@ primecertify(GEN bnf, GEN beta, ulong p, GEN bad)
     if (!umodiu(bad,q) || !uisprime(q)) continue;
 
     gq = utoipos(q);
-    LQ = idealprimedec(bnf,gq); nbqq = lg(LQ)-1;
+    LQ = idealprimedec_limit_f(bnf,gq,1); nbqq = lg(LQ)-1;
     g = NULL;
     for (i=1; i<=nbqq; i++)
     {
-      GEN mat1, Q = gel(LQ,i);
-
-      if (pr_get_f(Q) != 1) break;
-      /* Q has degree 1 */
+      GEN mat1, Q = gel(LQ,i); /* degree 1 */
       if (!g)
       {
         g = gener_Flxq(pol_x(0), q, &ord);
@@ -1380,19 +1374,14 @@ bnrisconductor(GEN bnr, GEN H0)
   avma = av; return 1;
 }
 
-static void
-err_rnfnormgroup(GEN T)
-{ pari_err_DOMAIN("rnfnormgroup","rnfisabelian(bnr,pol)","=", gen_0,T); }
-
 /* return the norm group corresponding to the relative extension given by
  * polrel over bnr.bnf, assuming it is abelian and the modulus of bnr is a
  * multiple of the conductor */
-GEN
-rnfnormgroup(GEN bnr, GEN polrel)
+static GEN
+rnfnormgroup_i(GEN bnr, GEN polrel)
 {
   long i, j, reldeg, nfac, k;
-  pari_sp av = avma;
-  GEN bnf, index, discnf, nf, group, detgroup, fa, greldeg;
+  GEN bnf, index, discnf, nf, G, detG, fa, greldeg;
   GEN fac, col, cnd;
   forprime_t S;
   ulong p;
@@ -1406,15 +1395,15 @@ rnfnormgroup(GEN bnr, GEN polrel)
   reldeg = degpol(polrel);
   /* reldeg-th powers are in norm group */
   greldeg = utoipos(reldeg);
-  group = FpC_red(bnr_get_cyc(bnr), greldeg);
-  for (i=1; i<lg(group); i++)
-    if (!signe(gel(group,i))) gel(group,i) = greldeg;
-  detgroup = ZV_prod(group);
-  group = diagonal_shallow(group);
-  k = cmpiu(detgroup,reldeg);
-  if (k < 0) err_rnfnormgroup(polrel);
-  if (!k) return gerepilecopy(av, group);
-
+  G = FpC_red(bnr_get_cyc(bnr), greldeg);
+  for (i=1; i<lg(G); i++)
+    if (!signe(gel(G,i))) gel(G,i) = greldeg;
+  detG = ZV_prod(G);
+  k = cmpiu(detG,reldeg);
+  if (k < 0) return NULL;
+  if (!k) return diagonal(G);
+
+  G = diagonal_shallow(G);
   discnf = nf_get_disc(nf);
   index  = nf_get_index(nf);
   u_forprime_init(&S, 2, ULONG_MAX);
@@ -1427,14 +1416,12 @@ rnfnormgroup(GEN bnr, GEN polrel)
 
     if (!umodiu(index, p)) continue; /* can't be treated efficiently */
 
-    fa = idealprimedec(nf, utoipos(p)); lfa = lg(fa)-1;
+    /* primes of degree 1 are enough, and simpler */
+    fa = idealprimedec_limit_f(nf, utoipos(p), 1); lfa = lg(fa)-1;
     for (i=1; i<=lfa; i++)
     {
       GEN pr = gel(fa,i), pp, T, polr, modpr;
       long f;
-
-      /* primes of degree 1 are enough, and simpler */
-      if (pr_get_f(pr) > 1) break;
       /* if pr (probably) ramified, we have to use all (non-ram) P | pr */
       if (idealval(nf,cnd,pr)) { oldf = 0; continue; }
       modpr = zk_to_Fq_init(nf, &pr, &T, &pp); /* T = NULL, pp ignored */
@@ -1447,7 +1434,7 @@ rnfnormgroup(GEN bnr, GEN polrel)
       nfac = lg(fac)-1;
       /* check decomposition of pr has Galois type */
       for (j=2; j<=nfac; j++)
-        if (degpol(gel(fac,j)) != f) err_rnfnormgroup(polrel);
+        if (degpol(gel(fac,j)) != f) return NULL;
       if (oldf < 0) oldf = f; else if (oldf != f) oldf = 0;
       if (f == reldeg) continue; /* reldeg-th powers already included */
 
@@ -1456,15 +1443,23 @@ rnfnormgroup(GEN bnr, GEN polrel)
       /* pr^f = N P, P | pr, hence is in norm group */
       col = bnrisprincipal(bnr,pr,0);
       if (f > 1) col = ZC_z_mul(col, f);
-      group = ZM_hnf(shallowconcat(group, col));
-      detgroup = ZM_det_triangular(group);
-      k = cmpiu(detgroup,reldeg);
-      if (k < 0) err_rnfnormgroup(polrel);
-      if (!k) { cgiv(detgroup); return gerepileupto(av,group); }
+      G = ZM_hnf(shallowconcat(G, col));
+      detG = ZM_det_triangular(G);
+      k = cmpiu(detG,reldeg);
+      if (k < 0) return NULL;
+      if (!k) { cgiv(detG); return G; }
     }
   }
   return NULL;
 }
+GEN
+rnfnormgroup(GEN bnr, GEN polrel)
+{
+  pari_sp av = avma;
+  GEN G = rnfnormgroup_i(bnr, polrel);
+  if (!G) { avma = av; return cgetg(1,t_MAT); }
+  return gerepileupto(av, G);
+}
 
 GEN
 nf_deg1_prime(GEN nf)
@@ -2108,9 +2103,9 @@ discrayabslistarch(GEN bnf, GEN arch, ulong bound)
 {
   int allarch = (arch==NULL), flbou = 0;
   long degk, j, k, l, nba, nbarch, r1, c;
-  pari_sp av0 = avma,  av,  av1,  lim;
+  pari_sp av0 = avma,  av,  av1;
   GEN nf, p, Z, fa, ideal, bidp, matarchunit, Disc, U, sgnU, EMPTY, empty;
-  GEN res, embunit, h, Ray, discall, idealrel, idealrelinit, fadkabs;
+  GEN res, embunit, h, Ray, discall, idealrel, idealrelinit, fadkabs, BOUND;
   ulong i, ii, sqbou;
   forprime_t S;
 
@@ -2140,9 +2135,10 @@ discrayabslistarch(GEN bnf, GEN arch, ulong bound)
 
   empty = cgetg(1,t_VEC);
   /* what follows was rewritten from Ideallist */
+  BOUND = utoipos(bound);
   p = cgetipos(3);
   u_forprime_init(&S, 2, bound);
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
   sqbou = (ulong)sqrt((double)bound) + 1;
   Z = bigcgetvec(bound);
   for (i=2; i<=bound; i++) bigel(Z,i) = empty;
@@ -2155,7 +2151,7 @@ discrayabslistarch(GEN bnf, GEN arch, ulong bound)
   Ray = Z;
   while ((p[2] = u_forprime_next(&S)))
   {
-    if (!flbou && (ulong)p[2] > sqbou)
+    if (!flbou && uel(p,2) > sqbou)
     {
       GEN z;
       flbou = 1;
@@ -2169,13 +2165,12 @@ discrayabslistarch(GEN bnf, GEN arch, ulong bound)
       for (i=1; i<=sqbou; i++) bigel(z,i) = bigel(Z,i);
       Z = z;
     }
-    fa = idealprimedec(nf,p);
+    fa = idealprimedec_limit_norm(nf,p,BOUND);
     for (j=1; j<lg(fa); j++)
     {
       GEN pr = gel(fa,j);
       long prcode, f = pr_get_f(pr);
       ulong q, Q = upowuu(p[2], f);
-      if (!Q || Q > bound) break;
 
       /* p, f-1, j-1 as a single integer in "base degk" (f,j <= degk)*/
       prcode = (p[2]*degk + f-1)*degk + j-1;
@@ -2213,7 +2208,7 @@ discrayabslistarch(GEN bnf, GEN arch, ulong bound)
         ideal = idealmul(nf,ideal,pr);
       }
     }
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"[1]: discrayabslistarch");
       gerepileall(av, flbou? 2: 1, &Z, &Ray);
@@ -2237,7 +2232,7 @@ discrayabslistarch(GEN bnf, GEN arch, ulong bound)
   }
   EMPTY = mkvec3(gen_0,gen_0,gen_0);
   idealrelinit = trivial_fact();
-  av1 = avma; lim = stack_lim(av1,1);
+  av1 = avma;
   Disc = bigcgetvec(bound);
   for (i=1; i<=bound; i++) bigel(Disc,i) = empty;
   for (ii=1; ii<=bound; ii++)
@@ -2299,7 +2294,7 @@ STORE:  gel(discall,karch+1) = res;
       res = allarch? mkvec2(Fa, discall)
                    : mkvec4(Fa, gel(res,1), gel(res,2), gel(res,3));
       gel(sousdisc,j) = res;
-      if (low_stack(lim, stack_lim(av1,1)))
+      if (gc_needed(av1,1))
       {
         long jj;
         if(DEBUGMEM>1) pari_warn(warnmem,"[2]: discrayabslistarch");
@@ -2404,3 +2399,100 @@ bnrdisclist0(GEN bnf, GEN L, GEN arch)
   if (typ(L)!=t_INT) return discrayabslist(bnf,L);
   return discrayabslistarch(bnf,arch,itos(L));
 }
+
+/****************************************************************************/
+/*                                Galois action on a BNR                    */
+/****************************************************************************/
+
+GEN
+bnrautmatrix(GEN bnr, GEN aut)
+{
+  pari_sp av=avma;
+  GEN gen, mat, nf;
+  long i, l;
+  nf = bnr_get_nf(bnr);
+  gen = bnr_get_gen(bnr); l = lg(gen);
+  aut = algtobasis(nf, aut);
+  mat = cgetg(l,t_MAT);
+  for (i=1; i<l; i++)
+    gel(mat, i) = bnrisprincipal(bnr,galoisapply(nf,aut,gel(gen,i)),0);
+  return gerepilecopy(av, mat);
+}
+
+GEN
+bnrgaloismatrix(GEN bnr, GEN aut)
+{
+  checkbnr(bnr);
+  switch (typ(aut))
+  {
+    case t_POL:
+    case t_COL:
+      return bnrautmatrix(bnr, aut);
+    case t_VEC:
+    {
+      long i, l = lg(aut);
+      GEN V;
+      if (l==9 && typ(gal_get_gen(aut))==t_VEC)
+      {
+        pari_sp av = avma;
+        V = galoispermtopol(aut, gal_get_gen(aut));
+        return gerepileupto(av, bnrgaloismatrix(bnr, V));
+      }
+      V = cgetg(l, t_VEC);
+      for(i=1; i<l; i++)
+        gel(V,i) = bnrautmatrix(bnr, gel(aut,i));
+      return V;
+    }
+    default:
+      pari_err_TYPE("bnrgaloismatrix", aut);
+      return NULL; /*NOT REACHED*/
+  }
+}
+
+GEN
+bnrgaloisapply(GEN bnr, GEN mat, GEN x)
+{
+  pari_sp av=avma;
+  GEN cyc;
+  checkbnr(bnr);
+  cyc = bnr_get_cyc(bnr);
+  if (typ(mat)!=t_MAT || !RgM_is_ZM(mat))
+    pari_err_TYPE("bnrgaloisapply",mat);
+  if (typ(x)!=t_MAT || !RgM_is_ZM(x))
+    pari_err_TYPE("bnrgaloisapply",x);
+  return gerepileupto(av, ZM_hnfmodid(ZM_mul(mat, x), cyc));
+}
+
+static GEN
+check_bnrgal(GEN bnr, GEN M)
+{
+  checkbnr(bnr);
+  if (typ(M)==t_MAT)
+    return mkvec(M);
+  else if (typ(M)==t_VEC && lg(M)==9 && typ(gal_get_gen(M))==t_VEC)
+  {
+    pari_sp av = avma;
+    GEN V = galoispermtopol(M, gal_get_gen(M));
+    return gerepileupto(av, bnrgaloismatrix(bnr, V));
+  }
+  else if (!is_vec_t(typ(M)))
+    pari_err_TYPE("bnrisgalois",M);
+  return M;
+}
+
+long
+bnrisgalois(GEN bnr, GEN M, GEN H)
+{
+  pari_sp av = avma;
+  long i, l;
+  if (typ(H)!=t_MAT || !RgM_is_ZM(H))
+    pari_err_TYPE("bnrisgalois",H);
+  M = check_bnrgal(bnr, M); l = lg(M);
+  for (i=1; i<l; i++)
+  {
+    long res = ZM_equal(bnrgaloisapply(bnr,gel(M,i), H), H);
+    if (!res) { avma = av; return 0; }
+  }
+  avma = av;
+  return 1;
+}
diff --git a/src/basemath/buch4.c b/src/basemath/buch4.c
index 1c2ce11..373dd2e 100644
--- a/src/basemath/buch4.c
+++ b/src/basemath/buch4.c
@@ -597,7 +597,7 @@ make_unit(GEN nf, GEN bnfS, GEN *px)
   }
   if (!is_pm1(N0)) return NULL;
   /* here, x = S v */
-  p1 = vecpermute(v, perm);
+  p1 = vecsmallpermute(v, perm);
   v = ZM_zc_mul(HB, p1);
   for (i=1; i<=cH; i++)
   {
@@ -684,17 +684,6 @@ nfX_eltup(GEN nf, GEN rnfeq, GEN x)
   for (i=2; i<l; i++) gel(y,i) = nfeltup(nf, gel(x,i), zknf, czknf);
   return y;
 }
-/* FIXME: remove this */
-static void
-nfX_fix_var(GEN P, long v)
-{
-  long i, l = lg(P);
-  for (i=2; i<l; i++)
-  {
-    GEN c = gel(P,i);
-    if (typ(c) == t_POL) setvarn(c, v);
-  }
-}
 
 GEN
 rnfisnorminit(GEN T, GEN relpol, int galois)
@@ -729,17 +718,10 @@ rnfisnorminit(GEN T, GEN relpol, int galois)
 
   if (galois == 2)
   {
-    GEN P;
-    long v = varn(T);
-    if (polabs == relpol)
-      P = relpol;
-    else
-    { /* FIXME: don't mess with variables, use proper priorities in nfabs. */
-      P = nfX_eltup(nf, rnfeq, relpol);
-      nfX_fix_var(P, v);
-    }
-    /* FIXME */
-    galois = nfissplit(gsubst(nfabs, nf_get_varn(nfabs), pol_x(v)), P);
+    GEN P = polabs==relpol? leafcopy(relpol): nfX_eltup(nf, rnfeq, relpol);
+    setvarn(P, fetch_var_higher());
+    galois = nfissplit(nfabs, P);
+    (void)delete_var();
   }
 
   prod = gen_1; S1 = S2 = cgetg(1, t_VEC);
@@ -854,6 +836,8 @@ GEN
 bnfisnorm(GEN bnf, GEN x, long flag)
 {
   pari_sp av = avma;
-  GEN T = rnfisnorminit(pol_x(MAXVARN), bnf, flag == 0? 1: 2);
-  return gerepileupto(av, rnfisnorm(T, x, flag == 1? 0: flag));
+  GEN T = rnfisnorminit(pol_x(fetch_var()), bnf, flag == 0? 1: 2);
+  GEN r = rnfisnorm(T, x, flag == 1? 0: flag);
+  (void)delete_var();
+  return gerepileupto(av,r);
 }
diff --git a/src/basemath/concat.c b/src/basemath/concat.c
index 38d285a..d0b9151 100644
--- a/src/basemath/concat.c
+++ b/src/basemath/concat.c
@@ -283,7 +283,7 @@ catmany(GEN y1, GEN y2, long t)
 GEN
 shallowconcat1(GEN x)
 {
-  pari_sp av = avma, lim = stack_lim(av, 3);
+  pari_sp av = avma;
   long lx, t, i;
   GEN z;
   switch(typ(x))
@@ -310,7 +310,7 @@ shallowconcat1(GEN x)
   }
   for (; i<lx; i++) {
     z = shallowconcat(z, gel(x,i));
-    if (low_stack(lim, stack_lim(av,3)))
+    if (gc_needed(av,3))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"concat: i = %ld", i);
       z = gerepilecopy(av, z);
diff --git a/src/basemath/crvwtors.c b/src/basemath/crvwtors.c
new file mode 100644
index 0000000..622d8cd
--- /dev/null
+++ b/src/basemath/crvwtors.c
@@ -0,0 +1,2467 @@
+/* Copyright (C) 2014  The PARI group.
+
+This file is part of the PARI/GP package.
+
+PARI/GP 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. It is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY WHATSOEVER.
+
+Check the License for details. You should have received a copy of it, along
+with the package; see the file 'COPYING'. If not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+#include "pari.h"
+#include "paripriv.h"
+
+/* In the database, the curve X1(N) is given by the bivariate
+ * polynomial X.  The degree of X in its main variable is at least
+ * the degree of its secondary variable, except for N = 6, 7, 8, 9,
+ * 10, 12.  Note that X1(N) is genus 0 for N <= 10 and N = 12, and
+ * genus 1 for N = 11, 14, and 15. */
+
+
+INLINE ulong
+Fl_div4(ulong x, ulong p)
+{
+  return Fl_halve(Fl_halve(x, p), p);
+}
+
+
+INLINE ulong
+Fl_div8(ulong x, ulong p)
+{
+  return Fl_halve(Fl_div4(x, p), p);
+}
+
+/* These tags describe which map to use to convert from (r,s) to (b,c)
+ * coeffs. */
+typedef enum {
+  RS_MAP, T_MAP, QT_MAP, TQ_MAP
+} map_type;
+
+typedef struct {
+  GEN crv;
+  GEN r_num, r_den;
+  long rplus1;
+  GEN s_num, s_den;
+  long splus1;
+  map_type map;
+} X1_info;
+
+#define FIRST_X1_LEVEL 13
+#define LAST_X1_LEVEL 39
+/* The table is defined at the end of the file. */
+INLINE const X1_info *get_X1_info(ulong N);
+
+/* Compute the image of
+ * (x,y) |--> (r_n(x,y)/r_d(x,y), s_n(x,y), s_d(x,y)) */
+static void
+map_X1_points(
+  GEN r, GEN s,
+  const X1_info *X1, long ncurves, ulong p, ulong pi)
+{
+  pari_sp ltop = avma, av;
+  GEN X1_c, rn_pol, rd_pol, sn_pol, sd_pol, rn, sn, rd, sd;
+  long xdeg, ydeg, i;
+
+  X1_c = zxX_to_FlxX(X1->crv, p);
+  xdeg = degpol(X1_c);
+  ydeg = RgXY_degreex(X1_c);
+
+  rn_pol = zxX_to_FlxX(X1->r_num, p);
+  rd_pol = zxX_to_FlxX(X1->r_den, p);
+  sn_pol = zxX_to_FlxX(X1->s_num, p);
+  sd_pol = zxX_to_FlxX(X1->s_den, p);
+
+  xdeg = maxss(xdeg, degpol(rn_pol));
+  xdeg = maxss(xdeg, degpol(rd_pol));
+  xdeg = maxss(xdeg, degpol(sn_pol));
+  xdeg = maxss(xdeg, degpol(sd_pol));
+
+  ydeg = maxss(ydeg, RgXY_degreex(rn_pol));
+  ydeg = maxss(ydeg, RgXY_degreex(rd_pol));
+  ydeg = maxss(ydeg, RgXY_degreex(sn_pol));
+  ydeg = maxss(ydeg, RgXY_degreex(sd_pol));
+
+  rn = cgetg(ncurves + 1, t_VECSMALL);
+  rd = cgetg(ncurves + 1, t_VECSMALL);
+  sn = cgetg(ncurves + 1, t_VECSMALL);
+  sd = cgetg(ncurves + 1, t_VECSMALL);
+
+  av = avma;
+  for (i = 1; i <= ncurves; ) {
+    GEN pol, ypowers, xpowers;
+    ulong y, x;
+    y = random_Fl(p);
+    ypowers = Fl_powers_pre(y, ydeg, p, pi);
+    pol = FlxY_evalx_powers_pre(X1_c, ypowers, p, pi);
+    x = Flx_oneroot(pol, p);
+    if (x != p) {
+      xpowers = Fl_powers_pre(x, xdeg, p, pi);
+      rd[i] = FlxY_eval_powers_pre(rd_pol, ypowers, xpowers, p, pi);
+      sd[i] = FlxY_eval_powers_pre(sd_pol, ypowers, xpowers, p, pi);
+      if (rd[i] != 0 && sd[i] != 0) {
+        rn[i] = FlxY_eval_powers_pre(rn_pol, ypowers, xpowers, p, pi);
+        sn[i] = FlxY_eval_powers_pre(sn_pol, ypowers, xpowers, p, pi);
+        ++i;
+      }
+    }
+    avma = av;
+  }
+
+  Flv_inv_pre_inplace(rd, p, pi);
+  Flv_inv_pre_inplace(sd, p, pi);
+
+  for (i = 1; i <= ncurves; ++i) {
+    r[i] = Fl_add(Fl_mul_pre(rn[i], rd[i], p, pi), X1->rplus1, p);
+    s[i] = Fl_add(Fl_mul_pre(sn[i], sd[i], p, pi), X1->splus1, p);
+  }
+  avma = ltop;
+}
+
+/*
+ * A curve y^2 = x^3 + a2 x^2 + a4 x is isomorphic to the curve
+ *
+ *   y^2 = x^3 + (a4 - 1/3*a2^2) x + (2/27*a2^3 - 1/3*a4*a2)
+ *       = x^3 + (a4 - a2 c) x + (2 c^3 - a4 c)
+ *
+ * (where c = a2/3) which is in short form.
+ */
+INLINE void
+a2a4_to_a4a6(ulong *a4, ulong *a6, ulong A2, ulong A4, ulong inv3, ulong p, ulong pi)
+{
+    ulong c = Fl_mul_pre(A2, inv3, p, pi);
+    *a4 = Fl_sub(A4, Fl_mul_pre(A2, c, p, pi), p);
+    *a6 = Fl_sub(Fl_double(Fl_mul_pre(c, Fl_sqr_pre(c, p, pi), p, pi), p),
+                 Fl_mul_pre(A4, c, p, pi), p);
+}
+
+
+/*
+ * A curve y^2 + a1 xy + a3 y = x^3 is isomorphic to the curve
+ *
+ *   y^2 = x^3 + (1/2*a3*a1 -1/48*a1^4) x + (1/864*a1^6 - 1/24*a3*a1^3 + 1/4*a3^2
+ *       = x^3 + c (a3 - 1/3 * c^3) x + 1/3 * c^3(1/9 c^2 a1 - a3) + 1/4 a3^2
+ *
+ * (where c = a1/2) which is in short form.
+ */
+INLINE void
+a1a3_to_a4a6(
+  ulong *a4, ulong *a6,
+  ulong a1, ulong a3, ulong inv3, ulong inv4, ulong inv9, ulong p, ulong pi)
+{
+  ulong c = Fl_halve(a1, p);
+  ulong c2 = Fl_sqr_pre(c, p, pi);
+  ulong c3_on_3 = Fl_mul_pre(Fl_mul_pre(c, c2, p, pi), inv3, p, pi);
+  /* t1 = c^2 * a1 / 9 */
+  ulong t1 = Fl_mul_pre(c2, Fl_mul_pre(a1, inv9, p, pi), p, pi);
+  /* t1 = c^3/3 (c^2 * a1 / 9 - a3) */
+  t1 = Fl_mul_pre(c3_on_3, Fl_sub(t1, a3, p), p, pi);
+
+  *a4 = Fl_mul_pre(c, Fl_sub(a3, c3_on_3, p), p, pi);
+  *a6 = Fl_add(t1, Fl_mul_pre(inv4, Fl_sqr_pre(a3, p, pi), p, pi), p);
+}
+
+
+/* Assumes m > 3, p > 5 */
+/* FIXME: Where do we assume that p > 5?  Some testing suggests that
+ * this works for p == 5 also. */
+/* Sutherland has a version of this function in tecurve.c
+ * around line 306. */
+/* FIXME: Could precompute some of the constants. */
+INLINE void
+bc_to_a4a6(
+  ulong *a4, ulong *a6, ulong b, ulong c, ulong p, ulong pi)
+{
+  /* E: y^2 + (1 - c)xy - by = x^3 - bx^2, so a1 = 1 - c
+   * and a2 = a3 = -b. */
+  ulong t0, t2, b2, b4, b6, c4, c6;
+
+  b6 = Fl_sub(c, 1, p);
+  t0 = Fl_sqr_pre(b6, p, pi);
+  b4 = Fl_double(Fl_double(b, p), p);
+  b2 = Fl_sub(t0, b4, p);
+  b4 = Fl_mul_pre(b6, b, p, pi);
+  b6 = Fl_sqr_pre(b, p, pi);
+  t2 = Fl_sqr_pre(b2, p, pi);
+  c4 = Fl_mul_pre(24 % p, b4, p, pi);
+  c4 = Fl_sub(c4, t2, p);
+
+  t0 = Fl_mul_pre(36 % p, b4, p, pi);
+  t2 = Fl_sub(t2, t0, p);
+  c6 = Fl_mul_pre(b2, t2, p, pi);
+  t0 = Fl_mul_pre(216 % p, b6, p, pi);
+  c6 = Fl_add(c6, t0, p);
+
+  *a4 = Fl_mul_pre(27 % p, c4, p, pi);
+  *a6 = Fl_mul_pre(54 % p, c6, p, pi);
+}
+
+
+INLINE void
+bc_to_a4a6_and_tors(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  ulong b, ulong c, ulong p, ulong pi)
+{
+  bc_to_a4a6(a4, a6, b, c, p, pi);
+
+  /* tx = 3((c - 1)^2 - 4b) */
+  *tx = Fl_triple(Fl_sub(Fl_sqr(Fl_sub(c, 1, p), p),
+                         Fl_double(Fl_double(b, p), p), p), p);
+  /* ty = -108 b */
+  *ty = Fl_neg(Fl_mul_pre(108 % p, b, p, pi), p);
+}
+
+
+INLINE void
+tq_to_a4a6_and_tors(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  ulong q, ulong t, ulong p, ulong pi, ulong inv3)
+{
+  ulong A2, A4;
+  ulong t2 = Fl_sqr_pre(t, p, pi);
+  ulong qtp1 = Fl_add(Fl_mul_pre(q, t, p, pi), 1L, p);
+  /* a2 = t^2-2*(q*t+1), a4 = (1-t^2)*(q*t+1)^2 */
+  A2 = Fl_sub(t2, Fl_double(qtp1, p), p);
+  A4 = Fl_mul_pre(Fl_sub(1L, t2, p), Fl_sqr_pre(qtp1, p, pi), p, pi);
+  a2a4_to_a4a6(a4, a6, A2, A4, inv3, p, pi);
+
+  /* [tx, ty] = [(t+1)*(q*t+1),t*(q*t+1)*(t+1)] */
+  *tx = Fl_mul_pre(Fl_add(t, 1L, p), qtp1, p, pi);
+  *ty = Fl_mul_pre(t, *tx, p, pi);
+  /* Map to isomorphic curve */
+  *tx = Fl_add(*tx, Fl_mul_pre(A2, inv3, p, pi), p);
+}
+
+
+INLINE void
+qt_to_a4a6_and_tors(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  ulong q, ulong t, ulong p, ulong pi, ulong c_12, ulong c_108)
+{
+  /* z = (q+1)*(t^2-1)/8 */
+  ulong z = Fl_div8(Fl_mul_pre(Fl_add(q, 1L, p),
+                               Fl_sub(Fl_sqr_pre(t, p, pi),
+                                      1L, p), p, pi), p);
+  ulong bb = Fl_mul_pre(Fl_sub(q, 1L, p), z, p, pi);
+  ulong b = Fl_halve(bb, p);
+  /* E=[1,(q^2-1)*(t^2-1)/16,(q^2-1)*(t^2-1)/16,0,0];
+   *  = [1, (q-1)*(q+1)*(t^2-1)/16, idem]
+   *  = [1, b, b, 0, 0] */
+  bc_to_a4a6(a4, a6, Fl_neg(b, p), 0L, p, pi);
+
+  /* [tx,ty]= [(q+1)*(t^2-1)/8,(q+1)^2*(t^2-1)*(t-1)/32];
+   *        = [z, (q+1)*(t-1)*z*1/4] */
+  *tx = z;
+  *ty = Fl_mul_pre(Fl_add(q, 1L, p),
+                   Fl_mul_pre(Fl_div4(z, p),
+                              Fl_sub(t, 1L, p), p, pi), p, pi);
+  /* Map to isomorphic curve:
+   * (x, y) |--> (3(12x + 4b + 1), 108(2y + x + b)) */
+  *ty = Fl_mul_pre(c_108, Fl_add(Fl_double(*ty, p),
+                                 Fl_add(b, *tx, p), p), p, pi);
+  *tx = Fl_triple(Fl_add(Fl_mul_pre(c_12, *tx, p, pi),
+                         Fl_add(Fl_double(bb, p), 1L, p), p), p);
+}
+
+
+INLINE void
+t_to_a4a6_and_tors(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  ulong q, ulong t, ulong p, ulong pi,
+  ulong inv3, ulong inv4, ulong inv9)
+{
+  ulong a1, a3, qt = Fl_mul_pre(q, t, p, pi), t1;
+  /* a1 = q*t+t+(2-q), a3 = (q*t)*(t-1)+t */
+  a1 = Fl_add(Fl_add(qt, t, p), Fl_sub(2L, q, p), p);
+  a3 = Fl_add(Fl_mul_pre(qt, Fl_sub(t, 1L, p), p, pi), t, p);
+  a1a3_to_a4a6(a4, a6, a1, a3, inv3, inv4, inv9, p, pi);
+  *tx = Fl_neg(t, p);
+  *ty = Fl_sqr_pre(t, p, pi);
+  /* Map to isomorphic curve:
+   * (x, y) |--> (x + 1/12*a1^2, 1/2*a1*x + (y + 1/2*a3))  */
+  t1 = Fl_halve(a1, p);
+  *ty = Fl_add(Fl_mul_pre(*tx, t1, p, pi),
+               Fl_add(*ty, Fl_halve(a3, p), p), p);
+  *tx = Fl_add(*tx, Fl_mul_pre(inv3, Fl_sqr_pre(t1, p, pi), p, pi), p);
+}
+
+
+INLINE void
+rs_to_a4a6_and_tors(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  ulong r, ulong s, ulong p, ulong pi)
+{
+  /* c = s (r - 1) */
+  ulong c = Fl_mul_pre(s, Fl_sub(r, 1, p), p, pi);
+  /* b = rc */
+  ulong b = Fl_mul_pre(r, c, p, pi);
+  bc_to_a4a6_and_tors(a4, a6, tx, ty, b, c, p, pi);
+}
+
+
+INLINE void
+random_curves_with_general_X1(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  long ncurves, long m, ulong p, ulong pi)
+{
+  pari_sp av = avma;
+  const X1_info *X1 = get_X1_info(m);
+  GEN r, r_, s, s_;
+
+  r_ = cgetg(ncurves + 1, t_VECSMALL); r = r_ + 1;
+  s_ = cgetg(ncurves + 1, t_VECSMALL); s = s_ + 1;
+  map_X1_points(r_, s_, X1, ncurves, p, pi);
+
+  switch (X1->map) {
+  case RS_MAP:
+    while (ncurves--)
+      rs_to_a4a6_and_tors(a4++, a6++, tx++, ty++, *r++, *s++, p, pi);
+    break;
+  case T_MAP:
+  {
+    ulong inv3 = Fl_inv(3L, p), inv4 = Fl_div4(1L, p);
+    ulong inv9 = Fl_sqr_pre(inv3, p, pi);
+    while (ncurves--) {
+      t_to_a4a6_and_tors(a4++, a6++, tx++, ty++, *r++, *s++,
+                         p, pi, inv3, inv4, inv9);
+    }
+    break;
+  }
+  case TQ_MAP:
+  {
+    ulong inv3 = Fl_inv(3L, p);
+    while (ncurves--) {
+      tq_to_a4a6_and_tors(a4++, a6++, tx++, ty++, *r++, *s++,
+                          p, pi, inv3);
+    }
+    break;
+  }
+  case QT_MAP:
+  {
+    ulong c_12 = 12 % p, c_108 = 108 % p;
+    while (ncurves--) {
+      qt_to_a4a6_and_tors(a4++, a6++, tx++, ty++, *r++, *s++,
+                          p, pi, c_12, c_108);
+    }
+    break;
+  }
+  }
+  avma = av;
+}
+
+
+INLINE void
+random_curves_with_11_torsion(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  long ncurves, ulong p, ulong pi)
+{
+  pari_sp ltop = avma, av;
+  const ulong A4 = Fl_neg(432 % p, p), A6 = 8208 % p;
+  const ulong c_6 = 6 % p, c_72 = 72 % p, c_108 = 108 % p;
+  const ulong inv216 = Fl_inv(216 % p, p);
+
+  av = avma;
+  while (ncurves) {
+    GEN Q;
+    ulong r, s, den;
+
+    /* FIXME: Curve arithmetic in Pari is slow enough that it's faster
+     * to generate random points on the curve than it is to compute
+     * random multiples of a point. I don't know if this is to be
+     * expected or not.  Should check if this is still true when using
+     * the fast jac_{add,mul} routines in 'classpoly.c'. Anyway,
+     * disabled for now. */
+#if 0
+    /* Must guard against the possibility that [n]Q = 0 */
+    do {
+      /* FIXME: should perhaps use p + 1 + 2\sqrt{p} instead of p - 1 */
+      n = random_Fl(m1) + 1;  /* m1 = p - 1; */
+      Q = Fle_mulu(P, n, A4, p);
+    } while (ell_is_inf(Q));
+#endif
+    /* FIXME: Thing is, if I'm going to do it this way *anyway*, I
+     * might as well use the non-elliptic version of X1(11), since the
+     * formulae are much nicer. */
+    Q = random_Fle_pre(A4, A6, p, pi);
+
+    /* den = 6x + 72 */
+    den = Fl_add(Fl_mul_pre(c_6, Q[1], p, pi), c_72, p);
+    if (den == 0)
+      continue;
+
+    /* r = (y + 108)/216, s = 1 + (y - 108)/(6x + 72) */
+    r = Fl_mul_pre(Fl_add(Q[2], c_108, p), inv216, p, pi);
+    s = Fl_add(1, Fl_div(Fl_sub(Q[2], c_108, p), den, p), p);
+    rs_to_a4a6_and_tors(a4++, a6++, tx++, ty++, r, s, p, pi);
+    avma = av;
+    --ncurves;
+  }
+  avma = ltop;
+}
+
+
+INLINE void
+random_curves_with_elliptic_X1(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  long ncurves, long m, ulong p, ulong pi)
+{
+  switch (m) {
+  case 11:
+    random_curves_with_11_torsion(a4, a6, tx, ty, ncurves, p, pi);
+    break;
+  /* cases 12 and 13 are not missing, it is handled by
+   * random_curves_with_rational_X1() and
+   * random_curves_with_general_X1() respectively. */
+  case 14:
+    /*random_curves_with_14_torsion(a4, a6, tx, ty, ncurves, p, pi);
+      break;*/
+  case 15:
+    /*random_curves_with_14_torsion(a4, a6, tx, ty, ncurves, p, pi);
+      break;*/
+    /* FIXME: random_curves_with_elliptic_X1() currently uses the
+     * alternative (but nevertheless very efficient) non-elliptic
+     * implementation for levels 14 and 15. */
+    random_curves_with_general_X1(a4, a6, tx, ty, ncurves, m, p, pi);
+    break;
+  default:
+    pari_err_BUG("random_curves_with_elliptic_X1");
+  }
+}
+
+
+INLINE void
+random_curves_with_2_torsion(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  long ncurves, ulong p, ulong pi)
+{
+  const ulong m1 = p - 1, inv3 = Fl_inv(3L, p);
+  while (ncurves--) {
+    ulong A2 = random_Fl(m1) + 1;  /* non-zero */
+    ulong A4 = random_Fl(m1) + 1;  /* non-zero */
+
+    a2a4_to_a4a6(a4++, a6++, A2, A4, inv3, p, pi);
+
+    /* [0,0] is a 2-torsion point on y^2 = x(x^2 + a2x + a4) which
+     * is mapped to [(1/3)a2, 0] on y^2 = x^3 + A4x + A6. */
+    *tx++ = Fl_mul_pre(inv3, A2, p, pi);
+    *ty++ = 0L;
+  };
+}
+
+
+INLINE void
+random_curves_with_3_torsion(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  long ncurves, ulong p, ulong pi)
+{
+  const ulong m1 = p - 1;
+  const ulong inv3 = Fl_inv(3, p), inv4 = Fl_inv(4, p);
+  const ulong inv9 = Fl_sqr_pre(inv3, p, pi);
+
+  while (ncurves--) {
+    ulong a1 = random_Fl(m1) + 1;  /* non-zero */
+    ulong a3 = random_Fl(m1) + 1;  /* non-zero */
+
+    a1a3_to_a4a6(a4++, a6++, a1, a3, inv3, inv4, inv9, p, pi);
+
+    /* [0,0] is a 3-torsion point on y^2 + a1xy + a3y = x^3 which
+     * is mapped to [a1^2/12, a3/2] on y^2 = x^3 + a4x + a6. */
+    *tx++ = Fl_mul_pre(Fl_sqr_pre(Fl_halve(a1, p), p, pi), inv3, p, pi);
+    *ty++ = Fl_halve(a3, p);
+  }
+}
+
+
+INLINE void
+random_curves_with_4_torsion(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  long ncurves, ulong p, ulong pi)
+{
+  const ulong m1 = p - 1;
+  while (ncurves--) {
+    ulong b = random_Fl(m1) + 1;  /* non-zero */
+    bc_to_a4a6_and_tors(a4++, a6++, tx++, ty++, b, 0L, p, pi);
+  }
+}
+
+
+INLINE void
+random_curves_with_5_torsion(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  long ncurves, ulong p, ulong pi)
+{
+  const ulong m1 = p - 1;
+  while (ncurves--) {
+    ulong b = random_Fl(m1) + 1;  /* non-zero */
+    bc_to_a4a6_and_tors(a4++, a6++, tx++, ty++, b, b, p, pi);
+  }
+}
+
+
+INLINE void
+random_curves_with_6_torsion(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  long ncurves, ulong p, ulong pi)
+{
+  const ulong m2 = p - 2;
+  while (ncurves--) {
+    ulong c = random_Fl(m2) + 1; /* in [1, p - 2] */
+    ulong b = Fl_add(c, Fl_sqr_pre(c, p, pi), p); /* b = c + c^2 */
+    bc_to_a4a6_and_tors(a4++, a6++, tx++, ty++, b, c, p, pi);
+  }
+}
+
+
+INLINE void
+random_curves_with_7_torsion(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  long ncurves, ulong p, ulong pi)
+{
+  const ulong m2 = p - 2;
+  while (ncurves--) {
+    ulong d = random_Fl(m2) + 2; /* in [2, p - 2] */
+    ulong c = Fl_sub(Fl_sqr_pre(d, p, pi), d, p); /* c = d^2 - d */
+    ulong b = Fl_mul_pre(c, d, p, pi); /* b = d^3 - d^2 */
+    bc_to_a4a6_and_tors(a4++, a6++, tx++, ty++, b, c, p, pi);
+  }
+}
+
+
+INLINE void
+random_curves_with_8_torsion(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  long ncurves, ulong p, ulong pi)
+{
+  const ulong m1 = p - 1;
+  while (ncurves--) {
+    ulong d = random_Fl(m1) + 1;  /* non-zero */
+    /* b = (2d - 1)(d - 1) */
+    ulong b = Fl_mul_pre(Fl_sub(Fl_double(d, p), 1, p),
+                         Fl_sub(d, 1, p), p, pi);
+    /* c = (2d - 1)(d - 1)/d */
+    ulong c = Fl_div(b, d, p);
+    bc_to_a4a6_and_tors(a4++, a6++, tx++, ty++, b, c, p, pi);
+  }
+}
+
+
+INLINE void
+random_curves_with_9_torsion(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  long ncurves, ulong p, ulong pi)
+{
+  while (ncurves--) {
+    ulong f = random_Fl(p);
+    /* d = f(f - 1) + 1 = f^2 - f + 1 = f^2 - (f - 1) */
+    ulong d = Fl_sub(Fl_sqr_pre(f, p, pi), Fl_sub(f, 1, p), p);
+    /* c = fd - f */
+    ulong c = Fl_mul_pre(f, Fl_sub(d, 1, p), p, pi);
+    /* b = cd */
+    ulong b = Fl_mul_pre(c, d, p, pi);
+    bc_to_a4a6_and_tors(a4++, a6++, tx++, ty++, b, c, p, pi);
+  }
+}
+
+INLINE void
+random_curves_with_10_torsion(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  long ncurves, ulong p, ulong pi)
+{
+  while (ncurves) {
+    ulong f, f2, d, c, b, t;
+
+    f = random_Fl(p);
+    /* t = f - (f - 1)^2 = (3f - 1) - f^2 */
+    f2 = Fl_sqr_pre(f, p, pi);
+    t = Fl_sub(Fl_sub(Fl_triple(f, p), 1, p), f2, p);
+    if (t == 0)
+      continue;
+
+    /* d = f^2 / (f - (f - 1)^2) */
+    d = Fl_div(f2, t, p);
+    /* c = fd - f */
+    c = Fl_mul_pre(f, Fl_sub(d, 1, p), p, pi);
+    /* b = cd */
+    b = Fl_mul_pre(c, d, p, pi);
+    bc_to_a4a6_and_tors(a4++, a6++, tx++, ty++, b, c, p, pi);
+    --ncurves;
+  }
+}
+
+INLINE void
+random_curves_with_12_torsion(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  long ncurves, ulong p, ulong pi)
+{
+  while (ncurves--) {
+    ulong tau, t1, t2, M, f, d, c, b;
+    tau = random_Fl(p);
+    /* tau mustn't be = 1.  If it is, just set tau = 2. */
+    tau += tau == 1;
+
+    /* t1 = tau - 1 */
+    t1 = Fl_sub(tau, 1, p);
+    /* M = (3 tau - 3 tau^2 - 1)/(tau - 1) = -(3 tau + 1/(tau - 1)) */
+    t2 = Fl_inv(t1, p);
+    M = Fl_neg(Fl_add(Fl_mul_pre(tau, 3, p, pi), t2, p), p);
+    /* f = M/(1 - tau) = -M / (tau - 1) */
+    f = Fl_neg(Fl_mul_pre(M, t2, p, pi), p);
+    /* d = M + tau */
+    d = Fl_add(M, tau, p);
+    /* c = fd - f */
+    c = Fl_mul_pre(f, Fl_sub(d, 1, p), p, pi);
+    /* b = cd */
+    b = Fl_mul_pre(c, d, p, pi);
+    bc_to_a4a6_and_tors(a4++, a6++, tx++, ty++, b, c, p, pi);
+  }
+}
+
+
+INLINE void
+random_curves_with_rational_X1(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  long ncurves, long m, ulong p, ulong pi)
+{
+  switch (m) {
+  case 2:
+    random_curves_with_2_torsion(a4, a6, tx, ty, ncurves, p, pi);
+    break;
+  case 3:
+    random_curves_with_3_torsion(a4, a6, tx, ty, ncurves, p, pi);
+    break;
+  case 4:
+    random_curves_with_4_torsion(a4, a6, tx, ty, ncurves, p, pi);
+    break;
+  case 5:
+    random_curves_with_5_torsion(a4, a6, tx, ty, ncurves, p, pi);
+    break;
+  case 6:
+    random_curves_with_6_torsion(a4, a6, tx, ty, ncurves, p, pi);
+    break;
+  case 7:
+    random_curves_with_7_torsion(a4, a6, tx, ty, ncurves, p, pi);
+    break;
+  case 8:
+    random_curves_with_8_torsion(a4, a6, tx, ty, ncurves, p, pi);
+    break;
+  case 9:
+    random_curves_with_9_torsion(a4, a6, tx, ty, ncurves, p, pi);
+    break;
+  case 10:
+    random_curves_with_10_torsion(a4, a6, tx, ty, ncurves, p, pi);
+    break;
+  /* case 11 is not missing, it is handled by random_curves_with_elliptic_X1() */
+  case 12:
+    random_curves_with_12_torsion(a4, a6, tx, ty, ncurves, p, pi);
+    break;
+  default:
+    pari_err_BUG("random_curves_with_rational_X1");
+  }
+}
+
+
+static void
+random_curves_with_any_torsion(
+  ulong *a4, ulong *a6, ulong *px, ulong *py,
+  long ncurves, ulong p, ulong pi)
+{
+  pari_sp av = avma;
+  ulong c_1728 = 1728 % p;
+  long i;
+  for (i = 0; i < ncurves; ++i) {
+    GEN P;
+    ulong j;
+    do
+      j = random_Fl(p);
+    while (j == 0 || j == c_1728);
+
+    Fl_ellj_to_a4a6(j, p, &a4[i], &a6[i]);
+
+    P = random_Fle_pre(a4[i], a6[i], p, pi);
+    px[i] = P[1];
+    py[i] = P[2];
+    avma = av;
+  }
+}
+
+/* Assumes p < 2^62 or thereabouts. */
+INLINE long
+torsion_compatible_with_characteristic(long m, ulong p)
+{
+  ulong two_sqrt_p = usqrt(4*p);
+  ulong lo = p + 1 - two_sqrt_p;
+  ulong hi = p + 1 + two_sqrt_p;
+
+  /* If ceil(lo/m) <= floor(hi/m) then there is a positive
+   * integer n such that lo <= mn <= hi. */
+  /* NB: Ceil(a/b) = (a + b - 1)/b, Floor(a/b) = a/b (using integer
+   * truncation). */
+  return (lo + m - 1)/m <= hi/m;
+}
+
+
+/*
+ * Input: pointers a4, a6, t{x,y} where t{x,y} is allowed to be
+ * zero, each (non-zero one) pointing to space for at least ncurves
+ * elements; an integer m <= 50; a prime p > 3; a flag in {0, 1}.
+ *
+ * The flag indicates that we should generate curves faster at the
+ * expense of not guaranteeing uniform randomness.  This only makes a
+ * difference when m = 11, 14 and 15.
+ *
+ * Output: Put the coefficients of ncurves elliptic curves with
+ * m-torsion into a4 and a6.  The actual number of *unique* curves
+ * generated is *not* guaranteed to be ncurves, but will be close
+ * whenever p is big relative to ncurves.  When non-zero, (torx[i],
+ * tory[i]) will contain the m-torsion point on [a4[i], a6[i]].
+ */
+void
+random_curves_with_m_torsion(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  long ncurves, long m, ulong p)
+{
+  ulong pi = get_Fl_red(p);
+
+  if (ncurves == 0)
+    return;
+
+  if (m < 1 || m > LAST_X1_LEVEL
+      || ! torsion_compatible_with_characteristic(m, p))
+    pari_err_BUG("random_curves_with_m_torsion");
+  else if (m == 1)
+    random_curves_with_any_torsion(a4, a6, tx, ty, ncurves, p, pi);
+  else if (m <= 10 || m == 12)
+    random_curves_with_rational_X1(a4, a6, tx, ty, ncurves, m, p, pi);
+  else if (m == 11 || m == 14 || m == 15)
+    random_curves_with_elliptic_X1(a4, a6, tx, ty, ncurves, m, p, pi);
+  else
+    random_curves_with_general_X1(a4, a6, tx, ty, ncurves, m, p, pi);
+
+  /* The likelihood of getting *any* zero discriminants is small
+   * enough that we can check using this slightly roundabout and
+   * expensive manner. */
+  while (ncurves--) {
+    ulong d = Fl_elldisc_pre(*a4, *a6, p, pi);
+    if (d == 0)  /* should almost never be true */
+      random_curves_with_m_torsion(a4, a6, tx, ty, 1L, m, p);
+    ++a4; ++a6; ++tx; ++ty;
+  }
+}
+
+#define vZ evalvarn(1) /* variable number for secondary variable */
+static const long FLX_0[3] = { evaltyp(t_VECSMALL) | _evallg(2), vZ };
+static const long FLX_1[3] = { evaltyp(t_VECSMALL) | _evallg(3), vZ, 1 };
+static const long FLX_m1[3] = { evaltyp(t_VECSMALL) | _evallg(3), vZ, -1 };
+static const long FLX_Z[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, 1 };
+static const long FLX_mZ[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, -1 };
+
+/*
+ * X1 Curves database follows!
+ */
+
+/* x^2 + (z^3 + z^2 + 1)*x + (-z^2 - z) */
+static const long X1_13_crv_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, -1, -1 }; /* -z^2 - z */
+static const long X1_13_crv_1[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 1, 0, 1, 1 }; /* z^3 + z^2 + 1 */
+static const long *X1_13_crv[5] = {
+  (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_13_crv_0, X1_13_crv_1, FLX_1
+};
+/* -z*x + 1 */
+static const long *X1_13_r_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_1, FLX_mZ
+};
+/* 1 */
+static const long *X1_13_r_d[3] = {
+  (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_1
+};
+/* -z*x */
+static const long *X1_13_s_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_0, FLX_mZ
+};
+/* x + 1 */
+static const long *X1_13_s_d[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_1, FLX_1
+};
+/* x^2 + (z^2 + z)*x + z */
+static const long X1_14_crv_1[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 1, 1 }; /* z^2 + z */
+static const long *X1_14_crv[5] = {
+  (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_Z, X1_14_crv_1, FLX_1
+};
+/* -x - z */
+static const long *X1_14_r_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_mZ, FLX_m1
+};
+/* x^2 + (z + 2)*x + (z + 1) */
+static const long X1_14_r_d_0[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */
+static const long X1_14_r_d_1[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 2, 1 }; /* z + 2 */
+static const long *X1_14_r_d[5] = {
+  (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_14_r_d_0, X1_14_r_d_1, FLX_1
+};
+/* (-z + 1) */
+static const long X1_14_s_n_0[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, -1 }; /* -z + 1 */
+static const long *X1_14_s_n[3] = {
+  (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_14_s_n_0
+};
+/* x + 1 */
+static const long *X1_14_s_d[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_1, FLX_1
+};
+/* x^2 + (z^2 + z + 1)*x + z^2 */
+static const long X1_15_crv_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, 1 }; /* z^2 */
+static const long X1_15_crv_1[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 1, 1, 1 }; /* z^2 + z + 1 */
+static const long *X1_15_crv[5] = {
+  (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_15_crv_0, X1_15_crv_1, FLX_1
+};
+/* x^2 + z*x */
+static const long *X1_15_r_n[5] = {
+  (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_0, FLX_Z, FLX_1
+};
+/* z^2*x + (z^3 + z^2) */
+static const long X1_15_r_d_0[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 1, 1 }; /* z^3 + z^2 */
+static const long X1_15_r_d_1[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, 1 }; /* z^2 */
+static const long *X1_15_r_d[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_15_r_d_0, X1_15_r_d_1
+};
+/* x */
+static const long *X1_15_s_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_0, FLX_1
+};
+/* (z^2 + z) */
+static const long X1_15_s_d_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 1, 1 }; /* z^2 + z */
+static const long *X1_15_s_d[3] = {
+  (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_15_s_d_0
+};
+/* x^2 + (z^3 + z^2 - z + 1)*x + z^2 */
+static const long X1_16_crv_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, 1 }; /* z^2 */
+static const long X1_16_crv_1[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 1, -1, 1, 1 }; /* z^3 + z^2 - z + 1 */
+static const long *X1_16_crv[5] = {
+  (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_16_crv_0, X1_16_crv_1, FLX_1
+};
+/* x^2 + (-z + 1)*x + z^2 */
+static const long X1_16_r_n_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, 1 }; /* z^2 */
+static const long X1_16_r_n_1[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, -1 }; /* -z + 1 */
+static const long *X1_16_r_n[5] = {
+  (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_16_r_n_0, X1_16_r_n_1, FLX_1
+};
+/* -x + (z^2 + z - 1) */
+static const long X1_16_r_d_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, -1, 1, 1 }; /* z^2 + z - 1 */
+static const long *X1_16_r_d[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_16_r_d_0, FLX_m1
+};
+/* -x + z */
+static const long *X1_16_s_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_Z, FLX_m1
+};
+/* (z + 1) */
+static const long X1_16_s_d_0[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */
+static const long *X1_16_s_d[3] = {
+  (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_16_s_d_0
+};
+/* x^4 + (z^3 + z^2 - z + 2)*x^3 + (z^3 - 3*z + 1)*x^2 + (-z^4 - 2*z)*x + (z^3 + z^2) */
+static const long X1_17_crv_0[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 1, 1 }; /* z^3 + z^2 */
+static const long X1_17_crv_1[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, -2, 0, 0, -1 }; /* -z^4 - 2*z */
+static const long X1_17_crv_2[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 1, -3, 0, 1 }; /* z^3 - 3*z + 1 */
+static const long X1_17_crv_3[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 2, -1, 1, 1 }; /* z^3 + z^2 - z + 2 */
+static const long *X1_17_crv[7] = {
+  (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_17_crv_0, X1_17_crv_1, X1_17_crv_2, X1_17_crv_3, FLX_1
+};
+/* -x + (z^2 + z) */
+static const long X1_17_r_n_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 1, 1 }; /* z^2 + z */
+static const long *X1_17_r_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_17_r_n_0, FLX_m1
+};
+/* -x^2 + (z - 1)*x + (z^2 + z) */
+static const long X1_17_r_d_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 1, 1 }; /* z^2 + z */
+static const long X1_17_r_d_1[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, -1, 1 }; /* z - 1 */
+static const long *X1_17_r_d[5] = {
+  (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_17_r_d_0, X1_17_r_d_1, FLX_m1
+};
+/* (z + 1) */
+static const long X1_17_s_n_0[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */
+static const long *X1_17_s_n[3] = {
+  (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_17_s_n_0
+};
+/* x + (z + 1) */
+static const long X1_17_s_d_0[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */
+static const long *X1_17_s_d[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_17_s_d_0, FLX_1
+};
+/* x^2 + (z^3 - 2*z^2 + 3*z + 1)*x + 2*z */
+static const long X1_18_crv_0[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, 2 }; /* 2*z */
+static const long X1_18_crv_1[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 1, 3, -2, 1 }; /* z^3 - 2*z^2 + 3*z + 1 */
+static const long *X1_18_crv[5] = {
+  (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_18_crv_0, X1_18_crv_1, FLX_1
+};
+/* -z*x + (z^2 - 3*z + 1) */
+static const long X1_18_r_n_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 1, -3, 1 }; /* z^2 - 3*z + 1 */
+static const long *X1_18_r_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_18_r_n_0, FLX_mZ
+};
+/* (z^3 - 2*z^2 + z)*x + (z^2 - 2*z + 1) */
+static const long X1_18_r_d_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 1, -2, 1 }; /* z^2 - 2*z + 1 */
+static const long X1_18_r_d_1[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 1, -2, 1 }; /* z^3 - 2*z^2 + z */
+static const long *X1_18_r_d[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_18_r_d_0, X1_18_r_d_1
+};
+/* -x + (z^2 - 2*z) */
+static const long X1_18_s_n_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, -2, 1 }; /* z^2 - 2*z */
+static const long *X1_18_s_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_18_s_n_0, FLX_m1
+};
+/* -x^2 + (-z - 2)*x + (z^2 - 3*z) */
+static const long X1_18_s_d_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, -3, 1 }; /* z^2 - 3*z */
+static const long X1_18_s_d_1[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, -2, -1 }; /* -z - 2 */
+static const long *X1_18_s_d[5] = {
+  (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_18_s_d_0, X1_18_s_d_1, FLX_m1
+};
+/* x^5 + (-z^2 - 2)*x^4 + (-2*z^3 - 2*z^2 - 2*z + 1)*x^3 + (z^5 + 3*z^4 + 7*z^3 + 6*z^2 + 2*z)*x^2 + (-z^5 - 2*z^4 - 4*z^3 - 3*z^2)*x + (z^3 + z^2) */
+static const long X1_19_crv_0[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 1, 1 }; /* z^3 + z^2 */
+static const long X1_19_crv_1[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, -3, -4, -2, -1 }; /* -z^5 - 2*z^4 - 4*z^3 - 3*z^2 */
+static const long X1_19_crv_2[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 2, 6, 7, 3, 1 }; /* z^5 + 3*z^4 + 7*z^3 + 6*z^2 + 2*z */
+static const long X1_19_crv_3[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 1, -2, -2, -2 }; /* -2*z^3 - 2*z^2 - 2*z + 1 */
+static const long X1_19_crv_4[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, -2, 0, -1 }; /* -z^2 - 2 */
+static const long *X1_19_crv[8] = {
+  (long *)(evaltyp(t_POL) | _evallg(8)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_19_crv_0, X1_19_crv_1, X1_19_crv_2, X1_19_crv_3, X1_19_crv_4, FLX_1
+};
+/* z*x^2 + (z^2 - z)*x - z^2 */
+static const long X1_19_r_n_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, -1 }; /* -z^2 */
+static const long X1_19_r_n_1[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, -1, 1 }; /* z^2 - z */
+static const long *X1_19_r_n[5] = {
+  (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_19_r_n_0, X1_19_r_n_1, FLX_Z
+};
+/* (-z - 1)*x^2 + (-z^2 + 1)*x + (z^3 + 3*z^2 + 2*z) */
+static const long X1_19_r_d_0[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 2, 3, 1 }; /* z^3 + 3*z^2 + 2*z */
+static const long X1_19_r_d_1[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 1, 0, -1 }; /* -z^2 + 1 */
+static const long X1_19_r_d_2[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, -1, -1 }; /* -z - 1 */
+static const long *X1_19_r_d[5] = {
+  (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_19_r_d_0, X1_19_r_d_1, X1_19_r_d_2
+};
+/* z*x - z */
+static const long *X1_19_s_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_mZ, FLX_Z
+};
+/* (-z - 1)*x + (z^2 + 2*z + 1) */
+static const long X1_19_s_d_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 1, 2, 1 }; /* z^2 + 2*z + 1 */
+static const long X1_19_s_d_1[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, -1, -1 }; /* -z - 1 */
+static const long *X1_19_s_d[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_19_s_d_0, X1_19_s_d_1
+};
+/* x^3 - z^3*x^2 - z^2*x + z */
+static const long X1_20_crv_1[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, -1 }; /* -z^2 */
+static const long X1_20_crv_2[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 0, -1 }; /* -z^3 */
+static const long *X1_20_crv[6] = {
+  (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_Z, X1_20_crv_1, X1_20_crv_2, FLX_1
+};
+/* -x + z */
+static const long *X1_20_r_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_Z, FLX_m1
+};
+/* z*x - 1 */
+static const long *X1_20_r_d[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_m1, FLX_Z
+};
+/* 4*z^3*x^3 + (-4*z^4 - 8*z^2)*x^2 + (8*z^3 + 4*z)*x - 4*z^2 */
+static const long X1_20_s_n_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, -4 }; /* -4*z^2 */
+static const long X1_20_s_n_1[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 4, 0, 8 }; /* 8*z^3 + 4*z */
+static const long X1_20_s_n_2[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, -8, 0, -4 }; /* -4*z^4 - 8*z^2 */
+static const long X1_20_s_n_3[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 0, 4 }; /* 4*z^3 */
+static const long *X1_20_s_n[6] = {
+  (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_20_s_n_0, X1_20_s_n_1, X1_20_s_n_2, X1_20_s_n_3
+};
+/* (z^4 + 4*z^2 - 1)*x^3 + (-10*z^3 - 2*z)*x^2 + (3*z^4 + 8*z^2 + 1)*x + (-2*z^3 - 2*z) */
+static const long X1_20_s_d_0[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, -2, 0, -2 }; /* -2*z^3 - 2*z */
+static const long X1_20_s_d_1[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, 0, 8, 0, 3 }; /* 3*z^4 + 8*z^2 + 1 */
+static const long X1_20_s_d_2[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, -2, 0, -10 }; /* -10*z^3 - 2*z */
+static const long X1_20_s_d_3[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, -1, 0, 4, 0, 1 }; /* z^4 + 4*z^2 - 1 */
+static const long *X1_20_s_d[6] = {
+  (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_20_s_d_0, X1_20_s_d_1, X1_20_s_d_2, X1_20_s_d_3
+};
+/* x^4 + (3*z^2 + 1)*x^3 + (z^5 + z^4 + 2*z^2 + 2*z)*x^2 + (2*z^4 + z^3 + z)*x + z^3 */
+static const long X1_21_crv_0[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 0, 1 }; /* z^3 */
+static const long X1_21_crv_1[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 1, 0, 1, 2 }; /* 2*z^4 + z^3 + z */
+static const long X1_21_crv_2[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 2, 2, 0, 1, 1 }; /* z^5 + z^4 + 2*z^2 + 2*z */
+static const long X1_21_crv_3[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 1, 0, 3 }; /* 3*z^2 + 1 */
+static const long *X1_21_crv[7] = {
+  (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_21_crv_0, X1_21_crv_1, X1_21_crv_2, X1_21_crv_3, FLX_1
+};
+/* (z + 1)*x^3 + (z + 2)*x^2 + x */
+static const long X1_21_r_n_2[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 2, 1 }; /* z + 2 */
+static const long X1_21_r_n_3[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */
+static const long *X1_21_r_n[6] = {
+  (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_0, FLX_1, X1_21_r_n_2, X1_21_r_n_3
+};
+/* -z*x^3 + (z^2 - 1)*x^2 + 2*z*x + 1 */
+static const long X1_21_r_d_1[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, 2 }; /* 2*z */
+static const long X1_21_r_d_2[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, -1, 0, 1 }; /* z^2 - 1 */
+static const long *X1_21_r_d[6] = {
+  (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_1, X1_21_r_d_1, X1_21_r_d_2, FLX_mZ
+};
+/* x^2 + x */
+static const long *X1_21_s_n[5] = {
+  (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_0, FLX_1, FLX_1
+};
+/* z*x + 1 */
+static const long *X1_21_s_d[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_1, FLX_Z
+};
+/* x^4 + (z^3 + 2*z^2 + z + 2)*x^3 + (z^5 + z^4 + 2*z^3 + 2*z^2 + 1)*x^2 + (z^5 - z^4 - 2*z^3 - z^2 - z)*x + (-z^4 - z^3) */
+static const long X1_22_crv_0[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, 0, -1, -1 }; /* -z^4 - z^3 */
+static const long X1_22_crv_1[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, -1, -1, -2, -1, 1 }; /* z^5 - z^4 - 2*z^3 - z^2 - z */
+static const long X1_22_crv_2[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 1, 0, 2, 2, 1, 1 }; /* z^5 + z^4 + 2*z^3 + 2*z^2 + 1 */
+static const long X1_22_crv_3[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 2, 1, 2, 1 }; /* z^3 + 2*z^2 + z + 2 */
+static const long *X1_22_crv[7] = {
+  (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_22_crv_0, X1_22_crv_1, X1_22_crv_2, X1_22_crv_3, FLX_1
+};
+/* (z^2 + z + 1)*x + z^2 */
+static const long X1_22_r_n_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, 1 }; /* z^2 */
+static const long X1_22_r_n_1[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 1, 1, 1 }; /* z^2 + z + 1 */
+static const long *X1_22_r_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_22_r_n_0, X1_22_r_n_1
+};
+/* x + (z^3 + 2*z^2) */
+static const long X1_22_r_d_0[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 2, 1 }; /* z^3 + 2*z^2 */
+static const long *X1_22_r_d[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_22_r_d_0, FLX_1
+};
+/* (z + 1)*x */
+static const long X1_22_s_n_1[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */
+static const long *X1_22_s_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_0, X1_22_s_n_1
+};
+/* x + z^2 */
+static const long X1_22_s_d_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, 1 }; /* z^2 */
+static const long *X1_22_s_d[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_22_s_d_0, FLX_1
+};
+/* x^7 + (z^5 - z^4 + z^3 + 4*z^2 + 3)*x^6 + (z^7 + 3*z^5 + z^4 + 5*z^3 + 7*z^2 - 4*z + 3)*x^5 + (2*z^7 + 3*z^5 - z^4 - 2*z^3 - z^2 - 8*z + 1)*x^4 + (z^7 - 4*z^6 - 5*z^5 - 6*z^4 - 6*z^3 - 2*z^2 - 3*z)*x^3 + (-3*z^6 + 5*z^4 + 3*z^3 + 3*z^2 + 2*z)*x^2 + (3*z^5 + 4*z^4 + z)*x + (-z^4 - 2*z^3 - z^2) */
+static const long X1_23_crv_0[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, -1, -2, -1 }; /* -z^4 - 2*z^3 - z^2 */
+static const long X1_23_crv_1[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 1, 0, 0, 4, 3 }; /* 3*z^5 + 4*z^4 + z */
+static const long X1_23_crv_2[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 2, 3, 3, 5, 0, -3 }; /* -3*z^6 + 5*z^4 + 3*z^3 + 3*z^2 + 2*z */
+static const long X1_23_crv_3[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, -3, -2, -6, -6, -5, -4, 1 }; /* z^7 - 4*z^6 - 5*z^5 - 6*z^4 - 6*z^3 - 2*z^2 - 3*z */
+static const long X1_23_crv_4[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, 1, -8, -1, -2, -1, 3, 0, 2 }; /* 2*z^7 + 3*z^5 - z^4 - 2*z^3 - z^2 - 8*z + 1 */
+static const long X1_23_crv_5[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, 3, -4, 7, 5, 1, 3, 0, 1 }; /* z^7 + 3*z^5 + z^4 + 5*z^3 + 7*z^2 - 4*z + 3 */
+static const long X1_23_crv_6[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 3, 0, 4, 1, -1, 1 }; /* z^5 - z^4 + z^3 + 4*z^2 + 3 */
+static const long *X1_23_crv[10] = {
+  (long *)(evaltyp(t_POL) | _evallg(10)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_23_crv_0, X1_23_crv_1, X1_23_crv_2, X1_23_crv_3, X1_23_crv_4, X1_23_crv_5, X1_23_crv_6, FLX_1
+};
+/* x + (z^2 + z + 1) */
+static const long X1_23_r_n_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 1, 1, 1 }; /* z^2 + z + 1 */
+static const long *X1_23_r_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_23_r_n_0, FLX_1
+};
+/* -z*x + z^2 */
+static const long X1_23_r_d_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, 1 }; /* z^2 */
+static const long *X1_23_r_d[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_23_r_d_0, FLX_mZ
+};
+/* x + (z + 1) */
+static const long X1_23_s_n_0[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */
+static const long *X1_23_s_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_23_s_n_0, FLX_1
+};
+/* z */
+static const long *X1_23_s_d[3] = {
+  (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_Z
+};
+/* (z^2 - 3)*x^4 + (z^5 + 2*z^4 + 2*z^3 + 2*z^2 - 3*z)*x^2 + (-z^4 - z^2) */
+static const long X1_24_crv_0[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, -1, 0, -1 }; /* -z^4 - z^2 */
+static const long X1_24_crv_2[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, -3, 2, 2, 2, 1 }; /* z^5 + 2*z^4 + 2*z^3 + 2*z^2 - 3*z */
+static const long X1_24_crv_4[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, -3, 0, 1 }; /* z^2 - 3 */
+static const long *X1_24_crv[7] = {
+  (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_24_crv_0, FLX_0, X1_24_crv_2, FLX_0, X1_24_crv_4
+};
+/* x */
+static const long *X1_24_r_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_0, FLX_1
+};
+/* 1 */
+static const long *X1_24_r_d[3] = {
+  (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_1
+};
+/* 4*x^3 + 4*z*x */
+static const long X1_24_s_n_1[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, 4 }; /* 4*z */
+static const long X1_24_s_n_3[3] = {
+  evaltyp(t_VECSMALL) | _evallg(3), vZ, 4 }; /* 4 */
+static const long *X1_24_s_n[6] = {
+  (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_0, X1_24_s_n_1, FLX_0, X1_24_s_n_3
+};
+/* (z - 2)*x^4 + (-4*z - 2)*x^2 - z */
+static const long X1_24_s_d_2[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, -2, -4 }; /* -4*z - 2 */
+static const long X1_24_s_d_4[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, -2, 1 }; /* z - 2 */
+static const long *X1_24_s_d[7] = {
+  (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_mZ, FLX_0, X1_24_s_d_2, FLX_0, X1_24_s_d_4
+};
+/* z*u^5 + (z^4 - 2*z^3 - z^2 + 2*z + 1)*u^4 + (-2*z^6 + 2*z^4 - 4*z^3 - 2*z^2 + 2)*u^3 + (z^8 + z^7 - 2*z^6 + z^5 - z^4 - z^3 - 2*z^2 - z + 1)*u^2 + (z^8 + z^7 + 2*z^6 + z^5 - 2*z^4 + z^3 - z^2)*u + z^6 */
+static const long X1_25_crv_0[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 0, 0, 0, 0, 1 }; /* z^6 */
+static const long X1_25_crv_1[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, -1, 1, -2, 1, 2, 1, 1 }; /* z^8 + z^7 + 2*z^6 + z^5 - 2*z^4 + z^3 - z^2 */
+static const long X1_25_crv_2[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, 1, -1, -2, -1, -1, 1, -2, 1, 1 }; /* z^8 + z^7 - 2*z^6 + z^5 - z^4 - z^3 - 2*z^2 - z + 1 */
+static const long X1_25_crv_3[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 2, 0, -2, -4, 2, 0, -2 }; /* -2*z^6 + 2*z^4 - 4*z^3 - 2*z^2 + 2 */
+static const long X1_25_crv_4[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, 2, -1, -2, 1 }; /* z^4 - 2*z^3 - z^2 + 2*z + 1 */
+static const long *X1_25_crv[8] = {
+  (long *)(evaltyp(t_POL) | _evallg(8)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_25_crv_0, X1_25_crv_1, X1_25_crv_2, X1_25_crv_3, X1_25_crv_4, FLX_Z
+};
+/* -z^2*u^6 + (2*z^4 - 2*z^2 - 2*z)*u^5 + (-z^6 + 2*z^5 + 5*z^4 + z^3 - 4*z - 1)*u^4 + (-2*z^7 - 3*z^6 + 4*z^5 + 4*z^4 + 5*z^3 - z - 2)*u^3 + (-z^8 - 4*z^7 - 2*z^6 - z^5 + 3*z^4 + 5*z^3 - z^2 + z - 1)*u^2 + (-z^8 - z^7 - 2*z^6 - 3*z^5 + 2*z^4 + z^3)*u - z^6 */
+static const long X1_25_r_n_0[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 0, 0, 0, 0, -1 }; /* -z^6 */
+static const long X1_25_r_n_1[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, 0, 1, 2, -3, -2, -1, -1 }; /* -z^8 - z^7 - 2*z^6 - 3*z^5 + 2*z^4 + z^3 */
+static const long X1_25_r_n_2[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, -1, 1, -1, 5, 3, -1, -2, -4, -1 }; /* -z^8 - 4*z^7 - 2*z^6 - z^5 + 3*z^4 + 5*z^3 - z^2 + z - 1 */
+static const long X1_25_r_n_3[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, -2, -1, 0, 5, 4, 4, -3, -2 }; /* -2*z^7 - 3*z^6 + 4*z^5 + 4*z^4 + 5*z^3 - z - 2 */
+static const long X1_25_r_n_4[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, -1, -4, 0, 1, 5, 2, -1 }; /* -z^6 + 2*z^5 + 5*z^4 + z^3 - 4*z - 1 */
+static const long X1_25_r_n_5[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, -2, -2, 0, 2 }; /* 2*z^4 - 2*z^2 - 2*z */
+static const long X1_25_r_n_6[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, -1 }; /* -z^2 */
+static const long *X1_25_r_n[9] = {
+  (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_25_r_n_0, X1_25_r_n_1, X1_25_r_n_2, X1_25_r_n_3, X1_25_r_n_4, X1_25_r_n_5, X1_25_r_n_6
+};
+/* -z^2*u^6 + (2*z^4 + z^3 - 2*z^2 - 2*z)*u^5 + (-z^6 + 7*z^4 + 3*z^3 + z^2 - 4*z - 1)*u^4 + (-z^7 - 8*z^6 + z^5 + 7*z^4 + 7*z^3 + 2*z^2 - z - 2)*u^3 + (2*z^8 - 6*z^7 - 11*z^6 - 2*z^5 + 3*z^4 + 7*z^3 + z - 1)*u^2 + (3*z^9 + 3*z^8 - 6*z^7 - 6*z^6 - 3*z^5 + z^4 + 2*z^3)*u + (z^10 + 3*z^9 + z^8 - 2*z^7 - z^6) */
+static const long X1_25_r_d_0[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, 0, 0, 0, 0, -1, -2, 1, 3, 1 }; /* z^10 + 3*z^9 + z^8 - 2*z^7 - z^6 */
+static const long X1_25_r_d_1[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, 2, 1, -3, -6, -6, 3, 3 }; /* 3*z^9 + 3*z^8 - 6*z^7 - 6*z^6 - 3*z^5 + z^4 + 2*z^3 */
+static const long X1_25_r_d_2[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, -1, 1, 0, 7, 3, -2, -11, -6, 2 }; /* 2*z^8 - 6*z^7 - 11*z^6 - 2*z^5 + 3*z^4 + 7*z^3 + z - 1 */
+static const long X1_25_r_d_3[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, -2, -1, 2, 7, 7, 1, -8, -1 }; /* -z^7 - 8*z^6 + z^5 + 7*z^4 + 7*z^3 + 2*z^2 - z - 2 */
+static const long X1_25_r_d_4[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, -1, -4, 1, 3, 7, 0, -1 }; /* -z^6 + 7*z^4 + 3*z^3 + z^2 - 4*z - 1 */
+static const long X1_25_r_d_5[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, -2, -2, 1, 2 }; /* 2*z^4 + z^3 - 2*z^2 - 2*z */
+static const long X1_25_r_d_6[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, -1 }; /* -z^2 */
+static const long *X1_25_r_d[9] = {
+  (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_25_r_d_0, X1_25_r_d_1, X1_25_r_d_2, X1_25_r_d_3, X1_25_r_d_4, X1_25_r_d_5, X1_25_r_d_6
+};
+/* -z*u^3 + (z^3 - z - 1)*u^2 + (z^4 + z^3 - z^2 + z - 1)*u + z^4 */
+static const long X1_25_s_n_0[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, 0, 0, 1 }; /* z^4 */
+static const long X1_25_s_n_1[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, -1, 1, -1, 1, 1 }; /* z^4 + z^3 - z^2 + z - 1 */
+static const long X1_25_s_n_2[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, -1, -1, 0, 1 }; /* z^3 - z - 1 */
+static const long *X1_25_s_n[6] = {
+  (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_25_s_n_0, X1_25_s_n_1, X1_25_s_n_2, FLX_mZ
+};
+/* -z*u^3 + (z^3 + z^2 - z - 1)*u^2 + (2*z^3 + z - 1)*u + (-z^5 + z^3) */
+static const long X1_25_s_d_0[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 0, 1, 0, -1 }; /* -z^5 + z^3 */
+static const long X1_25_s_d_1[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, -1, 1, 0, 2 }; /* 2*z^3 + z - 1 */
+static const long X1_25_s_d_2[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, -1, -1, 1, 1 }; /* z^3 + z^2 - z - 1 */
+static const long *X1_25_s_d[6] = {
+  (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_25_s_d_0, X1_25_s_d_1, X1_25_s_d_2, FLX_mZ
+};
+/* x^6 + (3*z^2 + 4*z - 2)*x^5 + (3*z^4 + 10*z^3 - 9*z + 1)*x^4 + (z^6 + 7*z^5 + 8*z^4 - 14*z^3 - 11*z^2 + 6*z)*x^3 + (z^7 + 4*z^6 - z^5 - 13*z^4 + 2*z^3 + 10*z^2 - z)*x^2 + (-z^6 + 7*z^4 + 4*z^3 - 2*z^2)*x + (-z^4 - z^3) */
+static const long X1_26_crv_0[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, 0, -1, -1 }; /* -z^4 - z^3 */
+static const long X1_26_crv_1[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, -2, 4, 7, 0, -1 }; /* -z^6 + 7*z^4 + 4*z^3 - 2*z^2 */
+static const long X1_26_crv_2[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, -1, 10, 2, -13, -1, 4, 1 }; /* z^7 + 4*z^6 - z^5 - 13*z^4 + 2*z^3 + 10*z^2 - z */
+static const long X1_26_crv_3[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 6, -11, -14, 8, 7, 1 }; /* z^6 + 7*z^5 + 8*z^4 - 14*z^3 - 11*z^2 + 6*z */
+static const long X1_26_crv_4[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, -9, 0, 10, 3 }; /* 3*z^4 + 10*z^3 - 9*z + 1 */
+static const long X1_26_crv_5[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, -2, 4, 3 }; /* 3*z^2 + 4*z - 2 */
+static const long *X1_26_crv[9] = {
+  (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_26_crv_0, X1_26_crv_1, X1_26_crv_2, X1_26_crv_3, X1_26_crv_4, X1_26_crv_5, FLX_1
+};
+/* z*x^2 + (z^3 + 3*z^2)*x - z^2 */
+static const long X1_26_r_n_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, -1 }; /* -z^2 */
+static const long X1_26_r_n_1[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 3, 1 }; /* z^3 + 3*z^2 */
+static const long *X1_26_r_n[5] = {
+  (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_26_r_n_0, X1_26_r_n_1, FLX_Z
+};
+/* (z + 1)*x^2 + (z^3 + 4*z^2 + 3*z)*x + (z^3 + z^2) */
+static const long X1_26_r_d_0[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 1, 1 }; /* z^3 + z^2 */
+static const long X1_26_r_d_1[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 3, 4, 1 }; /* z^3 + 4*z^2 + 3*z */
+static const long X1_26_r_d_2[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */
+static const long *X1_26_r_d[5] = {
+  (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_26_r_d_0, X1_26_r_d_1, X1_26_r_d_2
+};
+/* z*x - z */
+static const long *X1_26_s_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_mZ, FLX_Z
+};
+/* (z + 1)*x */
+static const long X1_26_s_d_1[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */
+static const long *X1_26_s_d[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_0, X1_26_s_d_1
+};
+/* (z^2 - 2*z + 1)*u^6 + (z^5 - 2*z^4 + z^3 + 2*z^2 - 4*z + 2)*u^5 + (-z^7 + 5*z^5 - 5*z^4 + 2*z^3 - 2*z^2 + 1)*u^4 + (z^8 - 4*z^7 - z^6 + 5*z^5 + 2*z^3 - 5*z^2 + 2*z)*u^3 + (3*z^8 - 4*z^7 - 2*z^6 - 2*z^5 + 3*z^4 + 2*z^3 - z^2 + z)*u^2 + (3*z^8 - 3*z^5)*u + (z^8 + z^7 + z^6) */
+static const long X1_27_crv_0[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, 0, 0, 0, 0, 1, 1, 1 }; /* z^8 + z^7 + z^6 */
+static const long X1_27_crv_1[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, 0, 0, 0, -3, 0, 0, 3 }; /* 3*z^8 - 3*z^5 */
+static const long X1_27_crv_2[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 1, -1, 2, 3, -2, -2, -4, 3 }; /* 3*z^8 - 4*z^7 - 2*z^6 - 2*z^5 + 3*z^4 + 2*z^3 - z^2 + z */
+static const long X1_27_crv_3[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 2, -5, 2, 0, 5, -1, -4, 1 }; /* z^8 - 4*z^7 - z^6 + 5*z^5 + 2*z^3 - 5*z^2 + 2*z */
+static const long X1_27_crv_4[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, 1, 0, -2, 2, -5, 5, 0, -1 }; /* -z^7 + 5*z^5 - 5*z^4 + 2*z^3 - 2*z^2 + 1 */
+static const long X1_27_crv_5[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 2, -4, 2, 1, -2, 1 }; /* z^5 - 2*z^4 + z^3 + 2*z^2 - 4*z + 2 */
+static const long X1_27_crv_6[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 1, -2, 1 }; /* z^2 - 2*z + 1 */
+static const long *X1_27_crv[9] = {
+  (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_27_crv_0, X1_27_crv_1, X1_27_crv_2, X1_27_crv_3, X1_27_crv_4, X1_27_crv_5, X1_27_crv_6
+};
+/* (-z^4 + 2*z^2 - 2*z + 1)*u^4 + (z^5 - 4*z^4 - z^3 + 6*z^2 - 4*z + 2)*u^3 + (3*z^5 - 5*z^4 - 2*z^3 + 5*z^2 - z + 1)*u^2 + (3*z^5 - 2*z^4 - z^3 + z^2)*u + z^5 */
+static const long X1_27_r_n_0[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 0, 0, 0, 1 }; /* z^5 */
+static const long X1_27_r_n_1[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 1, -1, -2, 3 }; /* 3*z^5 - 2*z^4 - z^3 + z^2 */
+static const long X1_27_r_n_2[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 1, -1, 5, -2, -5, 3 }; /* 3*z^5 - 5*z^4 - 2*z^3 + 5*z^2 - z + 1 */
+static const long X1_27_r_n_3[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 2, -4, 6, -1, -4, 1 }; /* z^5 - 4*z^4 - z^3 + 6*z^2 - 4*z + 2 */
+static const long X1_27_r_n_4[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, -2, 2, 0, -1 }; /* -z^4 + 2*z^2 - 2*z + 1 */
+static const long *X1_27_r_n[7] = {
+  (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_27_r_n_0, X1_27_r_n_1, X1_27_r_n_2, X1_27_r_n_3, X1_27_r_n_4
+};
+/* (-z^3 + z^2 - z + 1)*u^4 + (z^5 - z^4 - 2*z^3 + z^2 - z + 2)*u^3 + (3*z^5 - 2*z^4 - z^3 - 2*z^2 + 2*z + 1)*u^2 + (3*z^5 - z^4 - 3*z^2 + z)*u + (z^5 - z^2) */
+static const long X1_27_r_d_0[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, -1, 0, 0, 1 }; /* z^5 - z^2 */
+static const long X1_27_r_d_1[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 1, -3, 0, -1, 3 }; /* 3*z^5 - z^4 - 3*z^2 + z */
+static const long X1_27_r_d_2[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 1, 2, -2, -1, -2, 3 }; /* 3*z^5 - 2*z^4 - z^3 - 2*z^2 + 2*z + 1 */
+static const long X1_27_r_d_3[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 2, -1, 1, -2, -1, 1 }; /* z^5 - z^4 - 2*z^3 + z^2 - z + 2 */
+static const long X1_27_r_d_4[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 1, -1, 1, -1 }; /* -z^3 + z^2 - z + 1 */
+static const long *X1_27_r_d[7] = {
+  (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_27_r_d_0, X1_27_r_d_1, X1_27_r_d_2, X1_27_r_d_3, X1_27_r_d_4
+};
+/* (z^3 - 2*z + 1)*u^3 + (-z^4 + 2*z^3 + z^2 - 4*z + 2)*u^2 + (-2*z^4 + z^3 + z^2 - z + 1)*u - z^4 */
+static const long X1_27_s_n_0[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, 0, 0, -1 }; /* -z^4 */
+static const long X1_27_s_n_1[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, -1, 1, 1, -2 }; /* -2*z^4 + z^3 + z^2 - z + 1 */
+static const long X1_27_s_n_2[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 2, -4, 1, 2, -1 }; /* -z^4 + 2*z^3 + z^2 - 4*z + 2 */
+static const long X1_27_s_n_3[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 1, -2, 0, 1 }; /* z^3 - 2*z + 1 */
+static const long *X1_27_s_n[6] = {
+  (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_27_s_n_0, X1_27_s_n_1, X1_27_s_n_2, X1_27_s_n_3
+};
+/* (-z + 1)*u^3 + (-z^4 - z + 2)*u^2 + (-2*z^4 + 2*z + 1)*u + (-z^4 + z) */
+static const long X1_27_s_d_0[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 1, 0, 0, -1 }; /* -z^4 + z */
+static const long X1_27_s_d_1[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, 2, 0, 0, -2 }; /* -2*z^4 + 2*z + 1 */
+static const long X1_27_s_d_2[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 2, -1, 0, 0, -1 }; /* -z^4 - z + 2 */
+static const long X1_27_s_d_3[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, -1 }; /* -z + 1 */
+static const long *X1_27_s_d[6] = {
+  (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_27_s_d_0, X1_27_s_d_1, X1_27_s_d_2, X1_27_s_d_3
+};
+/* (z^5 + 3*z^4 + 3*z^3 + z^2)*x^6 + (z^8 + 2*z^7 + z^6 + 11*z^4 + 22*z^3 + 11*z^2)*x^5 + (9*z^7 + 9*z^6 - 6*z^5 - 6*z^4 + 45*z^3 + 45*z^2)*x^4 + (-5*z^8 + 28*z^6 - 42*z^4 + 84*z^2 - 1)*x^3 + (-25*z^7 + 25*z^6 + 23*z^5 - 23*z^4 - 67*z^3 + 67*z^2 + 5*z - 5)*x^2 + (6*z^8 - 12*z^7 - 12*z^6 + 36*z^5 - 36*z^3 + 12*z^2 + 12*z - 6)*x + (-z^9 + 3*z^8 - 8*z^6 + 6*z^5 + 6*z^4 - 8*z^3 + 3*z - 1) */
+static const long X1_28_crv_0[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, -1, 3, 0, -8, 6, 6, -8, 0, 3, -1 }; /* -z^9 + 3*z^8 - 8*z^6 + 6*z^5 + 6*z^4 - 8*z^3 + 3*z - 1 */
+static const long X1_28_crv_1[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, -6, 12, 12, -36, 0, 36, -12, -12, 6 }; /* 6*z^8 - 12*z^7 - 12*z^6 + 36*z^5 - 36*z^3 + 12*z^2 + 12*z - 6 */
+static const long X1_28_crv_2[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, -5, 5, 67, -67, -23, 23, 25, -25 }; /* -25*z^7 + 25*z^6 + 23*z^5 - 23*z^4 - 67*z^3 + 67*z^2 + 5*z - 5 */
+static const long X1_28_crv_3[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, -1, 0, 84, 0, -42, 0, 28, 0, -5 }; /* -5*z^8 + 28*z^6 - 42*z^4 + 84*z^2 - 1 */
+static const long X1_28_crv_4[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, 0, 45, 45, -6, -6, 9, 9 }; /* 9*z^7 + 9*z^6 - 6*z^5 - 6*z^4 + 45*z^3 + 45*z^2 */
+static const long X1_28_crv_5[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, 11, 22, 11, 0, 1, 2, 1 }; /* z^8 + 2*z^7 + z^6 + 11*z^4 + 22*z^3 + 11*z^2 */
+static const long X1_28_crv_6[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 1, 3, 3, 1 }; /* z^5 + 3*z^4 + 3*z^3 + z^2 */
+static const long *X1_28_crv[9] = {
+  (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_28_crv_0, X1_28_crv_1, X1_28_crv_2, X1_28_crv_3, X1_28_crv_4, X1_28_crv_5, X1_28_crv_6
+};
+/* (z + 1)*x + 2 */
+static const long X1_28_r_n_0[3] = {
+  evaltyp(t_VECSMALL) | _evallg(3), vZ, 2 }; /* 2 */
+static const long X1_28_r_n_1[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */
+static const long *X1_28_r_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_28_r_n_0, X1_28_r_n_1
+};
+/* 2*z */
+static const long X1_28_r_d_0[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, 2 }; /* 2*z */
+static const long *X1_28_r_d[3] = {
+  (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_28_r_d_0
+};
+/* (-z - 1)*x - 2 */
+static const long X1_28_s_n_0[3] = {
+  evaltyp(t_VECSMALL) | _evallg(3), vZ, -2 }; /* -2 */
+static const long X1_28_s_n_1[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, -1, -1 }; /* -z - 1 */
+static const long *X1_28_s_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_28_s_n_0, X1_28_s_n_1
+};
+/* 2 */
+static const long X1_28_s_d_0[3] = {
+  evaltyp(t_VECSMALL) | _evallg(3), vZ, 2 }; /* 2 */
+static const long *X1_28_s_d[3] = {
+  (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_28_s_d_0
+};
+/* x^11 + (2*z^3 + 5*z^2 + 5*z - 3)*x^10 + (z^6 + 8*z^5 + 18*z^4 + 11*z^3 - 5*z^2 - 12*z + 3)*x^9 + (3*z^8 + 15*z^7 + 29*z^6 + 6*z^5 - 39*z^4 - 19*z^3 + 5*z^2 + 5*z - 1)*x^8 + (3*z^10 + 14*z^9 + 18*z^8 - 26*z^7 - 99*z^6 - 45*z^5 + 95*z^4 + 25*z^3 - 37*z^2 + 7*z)*x^7 + (z^12 + 5*z^11 - 44*z^9 - 106*z^8 - 40*z^7 + 197*z^6 + 190*z^5 - 140*z^4 - 93*z^3 + 59*z^2 - 6*z)*x^6 + (-2*z^12 - 16*z^11 - 37*z^10 + 9*z^9 + 184*z^8 + 256*z^7 - 99*z^6 - 346*z^5 + 20*z^4 + 130*z^3 - 32*z^2 + z)*x^5 + (z^1 [...]
+static const long X1_29_crv_0[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, 0, 0, 0, 0, 1, 2, 1 }; /* z^8 + 2*z^7 + z^6 */
+static const long X1_29_crv_1[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, 0, 0, 5, 0, -18, -17, -4 }; /* -4*z^9 - 17*z^8 - 18*z^7 + 5*z^5 */
+static const long X1_29_crv_2[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, 0, 0, 10, -26, -55, 25, 76, 38, 6 }; /* 6*z^10 + 38*z^9 + 76*z^8 + 25*z^7 - 55*z^6 - 26*z^5 + 10*z^4 */
+static const long X1_29_crv_3[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 10, -64, -15, 191, 110, -98, -108, -36, -4 }; /* -4*z^11 - 36*z^10 - 108*z^9 - 98*z^8 + 110*z^7 + 191*z^6 - 15*z^5 - 64*z^4 + 10*z^3 */
+static const long X1_29_crv_4[15] = {
+  evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 0, 5, -66, 100, 223, -165, -320, -55, 99, 65, 15, 1 }; /* z^12 + 15*z^11 + 65*z^10 + 99*z^9 - 55*z^8 - 320*z^7 - 165*z^6 + 223*z^5 + 100*z^4 - 66*z^3 + 5*z^2 */
+static const long X1_29_crv_5[15] = {
+  evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 1, -32, 130, 20, -346, -99, 256, 184, 9, -37, -16, -2 }; /* -2*z^12 - 16*z^11 - 37*z^10 + 9*z^9 + 184*z^8 + 256*z^7 - 99*z^6 - 346*z^5 + 20*z^4 + 130*z^3 - 32*z^2 + z */
+static const long X1_29_crv_6[15] = {
+  evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, -6, 59, -93, -140, 190, 197, -40, -106, -44, 0, 5, 1 }; /* z^12 + 5*z^11 - 44*z^9 - 106*z^8 - 40*z^7 + 197*z^6 + 190*z^5 - 140*z^4 - 93*z^3 + 59*z^2 - 6*z */
+static const long X1_29_crv_7[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 7, -37, 25, 95, -45, -99, -26, 18, 14, 3 }; /* 3*z^10 + 14*z^9 + 18*z^8 - 26*z^7 - 99*z^6 - 45*z^5 + 95*z^4 + 25*z^3 - 37*z^2 + 7*z */
+static const long X1_29_crv_8[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, -1, 5, 5, -19, -39, 6, 29, 15, 3 }; /* 3*z^8 + 15*z^7 + 29*z^6 + 6*z^5 - 39*z^4 - 19*z^3 + 5*z^2 + 5*z - 1 */
+static const long X1_29_crv_9[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 3, -12, -5, 11, 18, 8, 1 }; /* z^6 + 8*z^5 + 18*z^4 + 11*z^3 - 5*z^2 - 12*z + 3 */
+static const long X1_29_crv_10[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, -3, 5, 5, 2 }; /* 2*z^3 + 5*z^2 + 5*z - 3 */
+static const long *X1_29_crv[14] = {
+  (long *)(evaltyp(t_POL) | _evallg(14)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_29_crv_0, X1_29_crv_1, X1_29_crv_2, X1_29_crv_3, X1_29_crv_4, X1_29_crv_5, X1_29_crv_6, X1_29_crv_7, X1_29_crv_8, X1_29_crv_9, X1_29_crv_10, FLX_1
+};
+/* -x + (-z^3 - z^2 - z) */
+static const long X1_29_r_n_0[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, -1, -1, -1 }; /* -z^3 - z^2 - z */
+static const long *X1_29_r_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_29_r_n_0, FLX_m1
+};
+/* (z^2 + z - 1)*x - z */
+static const long X1_29_r_d_1[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, -1, 1, 1 }; /* z^2 + z - 1 */
+static const long *X1_29_r_d[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_mZ, X1_29_r_d_1
+};
+/* -z*x - z^2 */
+static const long X1_29_s_n_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, -1 }; /* -z^2 */
+static const long *X1_29_s_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_29_s_n_0, FLX_mZ
+};
+/* (z - 1)*x - z */
+static const long X1_29_s_d_1[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, -1, 1 }; /* z - 1 */
+static const long *X1_29_s_d[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_mZ, X1_29_s_d_1
+};
+/* x^6 + (z^6 - 5*z^5 + 6*z^4 + 3*z^3 - 6*z^2 + 7*z + 3)*x^5 + (z^7 - 3*z^6 - 13*z^5 + 44*z^4 - 18*z^3 + z^2 + 18*z + 3)*x^4 + (z^8 - 3*z^7 - 13*z^6 + 27*z^5 + 46*z^4 - 32*z^3 + 21*z^2 + 15*z + 1)*x^3 + (2*z^8 - 16*z^7 + 18*z^6 + 40*z^5 + 12*z^4 - 12*z^3 + 18*z^2 + 4*z)*x^2 + (-8*z^7 + 28*z^6 + 12*z^5 + 4*z^2)*x + 8*z^6 */
+static const long X1_30_crv_0[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 0, 0, 0, 0, 8 }; /* 8*z^6 */
+static const long X1_30_crv_1[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, 0, 4, 0, 0, 12, 28, -8 }; /* -8*z^7 + 28*z^6 + 12*z^5 + 4*z^2 */
+static const long X1_30_crv_2[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 4, 18, -12, 12, 40, 18, -16, 2 }; /* 2*z^8 - 16*z^7 + 18*z^6 + 40*z^5 + 12*z^4 - 12*z^3 + 18*z^2 + 4*z */
+static const long X1_30_crv_3[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, 1, 15, 21, -32, 46, 27, -13, -3, 1 }; /* z^8 - 3*z^7 - 13*z^6 + 27*z^5 + 46*z^4 - 32*z^3 + 21*z^2 + 15*z + 1 */
+static const long X1_30_crv_4[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, 3, 18, 1, -18, 44, -13, -3, 1 }; /* z^7 - 3*z^6 - 13*z^5 + 44*z^4 - 18*z^3 + z^2 + 18*z + 3 */
+static const long X1_30_crv_5[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 3, 7, -6, 3, 6, -5, 1 }; /* z^6 - 5*z^5 + 6*z^4 + 3*z^3 - 6*z^2 + 7*z + 3 */
+static const long *X1_30_crv[9] = {
+  (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_30_crv_0, X1_30_crv_1, X1_30_crv_2, X1_30_crv_3, X1_30_crv_4, X1_30_crv_5, FLX_1
+};
+/* x + 1 */
+static const long *X1_30_r_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_1, FLX_1
+};
+/* 1 */
+static const long *X1_30_r_d[3] = {
+  (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_1
+};
+/* 4*x^2 + (4*z + 4)*x + 4*z */
+static const long X1_30_s_n_0[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, 4 }; /* 4*z */
+static const long X1_30_s_n_1[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 4, 4 }; /* 4*z + 4 */
+static const long X1_30_s_n_2[3] = {
+  evaltyp(t_VECSMALL) | _evallg(3), vZ, 4 }; /* 4 */
+static const long *X1_30_s_n[5] = {
+  (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_30_s_n_0, X1_30_s_n_1, X1_30_s_n_2
+};
+/* (z - 3)*x^3 - 6*x^2 + (-4*z - 4)*x - 4*z */
+static const long X1_30_s_d_0[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, -4 }; /* -4*z */
+static const long X1_30_s_d_1[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, -4, -4 }; /* -4*z - 4 */
+static const long X1_30_s_d_2[3] = {
+  evaltyp(t_VECSMALL) | _evallg(3), vZ, -6 }; /* -6 */
+static const long X1_30_s_d_3[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, -3, 1 }; /* z - 3 */
+static const long *X1_30_s_d[6] = {
+  (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_30_s_d_0, X1_30_s_d_1, X1_30_s_d_2, X1_30_s_d_3
+};
+/* u^12 + (z^10 - z^9 - 8*z^8 + 6*z^7 + 23*z^6 - 12*z^5 - 26*z^4 + 8*z^3 + 10*z^2 + 7*z - 3)*u^11 + (z^11 - 8*z^10 - 11*z^9 + 61*z^8 + 45*z^7 - 152*z^6 - 70*z^5 + 129*z^4 + 37*z^3 - 24*z + 3)*u^10 + (-8*z^11 + 17*z^10 + 105*z^9 - 93*z^8 - 387*z^7 + 145*z^6 + 453*z^5 - 57*z^4 - 91*z^3 - 73*z^2 + 31*z - 1)*u^9 + (-z^12 + 25*z^11 + 27*z^10 - 273*z^9 - 260*z^8 + 745*z^7 + 569*z^6 - 572*z^5 - 266*z^4 - 36*z^3 + 131*z^2 - 19*z)*u^8 + (5*z^12 - 32*z^11 - 162*z^10 + 193*z^9 + 911*z^8 - 147*z^7 - [...]
+static const long X1_31_crv_0[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, 0, 0, 0, 0, -1, -2, -1 }; /* -z^9 - 2*z^8 - z^7 */
+static const long X1_31_crv_1[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, 0, 0, 0, 0, -6, -5, 11, 14, 3 }; /* 3*z^10 + 14*z^9 + 11*z^8 - 5*z^7 - 6*z^6 */
+static const long X1_31_crv_2[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 0, 0, -15, 13, 67, 25, -49, -27, -3 }; /* -3*z^11 - 27*z^10 - 49*z^9 + 25*z^8 + 67*z^7 + 13*z^6 - 15*z^5 */
+static const long X1_31_crv_3[15] = {
+  evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 0, 0, 0, -20, 68, 103, -119, -247, -1, 76, 20, 1 }; /* z^12 + 20*z^11 + 76*z^10 - z^9 - 247*z^8 - 119*z^7 + 103*z^6 + 68*z^5 - 20*z^4 */
+static const long X1_31_crv_4[15] = {
+  evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 0, 0, -15, 112, -17, -390, -266, 448, 293, -52, -47, -5 }; /* -5*z^12 - 47*z^11 - 52*z^10 + 293*z^9 + 448*z^8 - 266*z^7 - 390*z^6 - 17*z^5 + 112*z^4 - 15*z^3 */
+static const long X1_31_crv_5[15] = {
+  evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 0, -6, 91, -200, -351, 242, 1033, 19, -537, -115, 44, 10 }; /* 10*z^12 + 44*z^11 - 115*z^10 - 537*z^9 + 19*z^8 + 1033*z^7 + 242*z^6 - 351*z^5 - 200*z^4 + 91*z^3 - 6*z^2 */
+static const long X1_31_crv_6[15] = {
+  evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, -1, 37, -216, 28, 598, 713, -967, -864, 268, 240, 0, -10 }; /* -10*z^12 + 240*z^10 + 268*z^9 - 864*z^8 - 967*z^7 + 713*z^6 + 598*z^5 + 28*z^4 - 216*z^3 + 37*z^2 - z */
+static const long X1_31_crv_7[15] = {
+  evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 6, -99, 222, 301, -78, -1254, -147, 911, 193, -162, -32, 5 }; /* 5*z^12 - 32*z^11 - 162*z^10 + 193*z^9 + 911*z^8 - 147*z^7 - 1254*z^6 - 78*z^5 + 301*z^4 + 222*z^3 - 99*z^2 + 6*z */
+static const long X1_31_crv_8[15] = {
+  evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, -19, 131, -36, -266, -572, 569, 745, -260, -273, 27, 25, -1 }; /* -z^12 + 25*z^11 + 27*z^10 - 273*z^9 - 260*z^8 + 745*z^7 + 569*z^6 - 572*z^5 - 266*z^4 - 36*z^3 + 131*z^2 - 19*z */
+static const long X1_31_crv_9[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, -1, 31, -73, -91, -57, 453, 145, -387, -93, 105, 17, -8 }; /* -8*z^11 + 17*z^10 + 105*z^9 - 93*z^8 - 387*z^7 + 145*z^6 + 453*z^5 - 57*z^4 - 91*z^3 - 73*z^2 + 31*z - 1 */
+static const long X1_31_crv_10[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 3, -24, 0, 37, 129, -70, -152, 45, 61, -11, -8, 1 }; /* z^11 - 8*z^10 - 11*z^9 + 61*z^8 + 45*z^7 - 152*z^6 - 70*z^5 + 129*z^4 + 37*z^3 - 24*z + 3 */
+static const long X1_31_crv_11[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, -3, 7, 10, 8, -26, -12, 23, 6, -8, -1, 1 }; /* z^10 - z^9 - 8*z^8 + 6*z^7 + 23*z^6 - 12*z^5 - 26*z^4 + 8*z^3 + 10*z^2 + 7*z - 3 */
+static const long *X1_31_crv[15] = {
+  (long *)(evaltyp(t_POL) | _evallg(15)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_31_crv_0, X1_31_crv_1, X1_31_crv_2, X1_31_crv_3, X1_31_crv_4, X1_31_crv_5, X1_31_crv_6, X1_31_crv_7, X1_31_crv_8, X1_31_crv_9, X1_31_crv_10, X1_31_crv_11, FLX_1
+};
+/* (-z^4 + 3*z^3 - 2*z^2 - z + 1)*u^7 + (-z^5 + 7*z^4 - 11*z^3 + 2*z^2 + 3*z)*u^6 + (5*z^5 - 18*z^4 + 12*z^3 + 3*z^2 - 1)*u^5 + (z^6 - 11*z^5 + 22*z^4 + z^3 - 6*z^2 - 4*z + 1)*u^4 + (-2*z^6 + 15*z^5 - 9*z^4 - 15*z^3 - 3*z^2 + 4*z)*u^3 + (3*z^6 - 11*z^5 - 10*z^4 + 4*z^3 + 6*z^2)*u^2 + (-3*z^6 + 6*z^4 + 4*z^3)*u + (z^6 + 2*z^5 + z^4) */
+static const long X1_31_r_n_0[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 0, 0, 1, 2, 1 }; /* z^6 + 2*z^5 + z^4 */
+static const long X1_31_r_n_1[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 0, 4, 6, 0, -3 }; /* -3*z^6 + 6*z^4 + 4*z^3 */
+static const long X1_31_r_n_2[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 6, 4, -10, -11, 3 }; /* 3*z^6 - 11*z^5 - 10*z^4 + 4*z^3 + 6*z^2 */
+static const long X1_31_r_n_3[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 4, -3, -15, -9, 15, -2 }; /* -2*z^6 + 15*z^5 - 9*z^4 - 15*z^3 - 3*z^2 + 4*z */
+static const long X1_31_r_n_4[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 1, -4, -6, 1, 22, -11, 1 }; /* z^6 - 11*z^5 + 22*z^4 + z^3 - 6*z^2 - 4*z + 1 */
+static const long X1_31_r_n_5[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, -1, 0, 3, 12, -18, 5 }; /* 5*z^5 - 18*z^4 + 12*z^3 + 3*z^2 - 1 */
+static const long X1_31_r_n_6[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 3, 2, -11, 7, -1 }; /* -z^5 + 7*z^4 - 11*z^3 + 2*z^2 + 3*z */
+static const long X1_31_r_n_7[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, -1, -2, 3, -1 }; /* -z^4 + 3*z^3 - 2*z^2 - z + 1 */
+static const long *X1_31_r_n[10] = {
+  (long *)(evaltyp(t_POL) | _evallg(10)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_31_r_n_0, X1_31_r_n_1, X1_31_r_n_2, X1_31_r_n_3, X1_31_r_n_4, X1_31_r_n_5, X1_31_r_n_6, X1_31_r_n_7
+};
+/* (-z + 1)*u^6 + (-4*z^2 + 5*z - 1)*u^5 + (-z^6 - z^5 + 5*z^4 - z^3 + 6*z^2 - 7*z + 1)*u^4 + (3*z^6 + 10*z^5 - 6*z^4 - 8*z^3 - 10*z^2 + 5*z)*u^3 + (-z^6 - 14*z^5 - 10*z^4 + z^3 + 8*z^2)*u^2 + (-2*z^6 + 2*z^5 + 7*z^4 + 5*z^3)*u + (z^6 + 2*z^5 + z^4) */
+static const long X1_31_r_d_0[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 0, 0, 1, 2, 1 }; /* z^6 + 2*z^5 + z^4 */
+static const long X1_31_r_d_1[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 0, 5, 7, 2, -2 }; /* -2*z^6 + 2*z^5 + 7*z^4 + 5*z^3 */
+static const long X1_31_r_d_2[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 8, 1, -10, -14, -1 }; /* -z^6 - 14*z^5 - 10*z^4 + z^3 + 8*z^2 */
+static const long X1_31_r_d_3[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 5, -10, -8, -6, 10, 3 }; /* 3*z^6 + 10*z^5 - 6*z^4 - 8*z^3 - 10*z^2 + 5*z */
+static const long X1_31_r_d_4[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 1, -7, 6, -1, 5, -1, -1 }; /* -z^6 - z^5 + 5*z^4 - z^3 + 6*z^2 - 7*z + 1 */
+static const long X1_31_r_d_5[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, -1, 5, -4 }; /* -4*z^2 + 5*z - 1 */
+static const long X1_31_r_d_6[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, -1 }; /* -z + 1 */
+static const long *X1_31_r_d[9] = {
+  (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_31_r_d_0, X1_31_r_d_1, X1_31_r_d_2, X1_31_r_d_3, X1_31_r_d_4, X1_31_r_d_5, X1_31_r_d_6
+};
+/* (-z^3 + 3*z^2 - z - 2)*u^6 + (-z^4 + 7*z^3 - 8*z^2 - 3*z + 1)*u^5 + (5*z^4 - 15*z^3 + 2*z^2 + 5*z + 1)*u^4 + (z^5 - 11*z^4 + 9*z^3 + 9*z^2 - z - 1)*u^3 + (-3*z^5 + 8*z^4 + 6*z^3 - 4*z^2 - 2*z)*u^2 + (3*z^5 + z^4 - 4*z^3 - 2*z^2)*u + (-z^5 - 2*z^4 - z^3) */
+static const long X1_31_s_n_0[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 0, -1, -2, -1 }; /* -z^5 - 2*z^4 - z^3 */
+static const long X1_31_s_n_1[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, -2, -4, 1, 3 }; /* 3*z^5 + z^4 - 4*z^3 - 2*z^2 */
+static const long X1_31_s_n_2[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, -2, -4, 6, 8, -3 }; /* -3*z^5 + 8*z^4 + 6*z^3 - 4*z^2 - 2*z */
+static const long X1_31_s_n_3[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, -1, -1, 9, 9, -11, 1 }; /* z^5 - 11*z^4 + 9*z^3 + 9*z^2 - z - 1 */
+static const long X1_31_s_n_4[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, 5, 2, -15, 5 }; /* 5*z^4 - 15*z^3 + 2*z^2 + 5*z + 1 */
+static const long X1_31_s_n_5[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, -3, -8, 7, -1 }; /* -z^4 + 7*z^3 - 8*z^2 - 3*z + 1 */
+static const long X1_31_s_n_6[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, -2, -1, 3, -1 }; /* -z^3 + 3*z^2 - z - 2 */
+static const long *X1_31_s_n[9] = {
+  (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_31_s_n_0, X1_31_s_n_1, X1_31_s_n_2, X1_31_s_n_3, X1_31_s_n_4, X1_31_s_n_5, X1_31_s_n_6
+};
+/* (z^2 - z - 1)*u^6 + (2*z^3 - 4*z^2 - z)*u^5 + (z^4 - 6*z^3 + 3*z^2 + z + 1)*u^4 + (-z^5 - 7*z^4 + 5*z^3 + 4*z^2 + 2*z - 1)*u^3 + (10*z^4 + 7*z^3 - z^2 - 3*z)*u^2 + (2*z^5 - z^4 - 5*z^3 - 3*z^2)*u + (-z^5 - 2*z^4 - z^3) */
+static const long X1_31_s_d_0[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 0, -1, -2, -1 }; /* -z^5 - 2*z^4 - z^3 */
+static const long X1_31_s_d_1[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, -3, -5, -1, 2 }; /* 2*z^5 - z^4 - 5*z^3 - 3*z^2 */
+static const long X1_31_s_d_2[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, -3, -1, 7, 10 }; /* 10*z^4 + 7*z^3 - z^2 - 3*z */
+static const long X1_31_s_d_3[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, -1, 2, 4, 5, -7, -1 }; /* -z^5 - 7*z^4 + 5*z^3 + 4*z^2 + 2*z - 1 */
+static const long X1_31_s_d_4[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, 1, 3, -6, 1 }; /* z^4 - 6*z^3 + 3*z^2 + z + 1 */
+static const long X1_31_s_d_5[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, -1, -4, 2 }; /* 2*z^3 - 4*z^2 - z */
+static const long X1_31_s_d_6[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, -1, -1, 1 }; /* z^2 - z - 1 */
+static const long *X1_31_s_d[9] = {
+  (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_31_s_d_0, X1_31_s_d_1, X1_31_s_d_2, X1_31_s_d_3, X1_31_s_d_4, X1_31_s_d_5, X1_31_s_d_6
+};
+/* (z^8 - 4*z^7 + 6*z^6 - 4*z^5 + z^4)*x^8 + (16*z^8 - 48*z^7 + 48*z^6 - 16*z^5)*x^7 + (z^11 - 2*z^10 + z^9 + 104*z^8 - 208*z^7 + 96*z^6 + 16*z^5 - 8*z^4 - z^3 + 2*z^2 - z)*x^6 + (12*z^11 - 12*z^10 + 352*z^8 - 352*z^7 - 96*z^6 + 96*z^5 - 12*z^3 + 12*z^2)*x^5 + (54*z^11 - 6*z^9 + 664*z^8 - 432*z^6 + 24*z^4 - 54*z^3 + 6*z)*x^4 + (112*z^11 + 112*z^10 + 64*z^9 + 768*z^8 + 768*z^7 - 128*z^6 - 128*z^5 + 64*z^4 - 48*z^3 - 48*z^2)*x^3 + (106*z^11 + 212*z^10 + 198*z^9 + 600*z^8 + 1020*z^7 + 576*z [...]
+static const long X1_32_crv_0[15] = {
+  evaltyp(t_VECSMALL) | _evallg(15), vZ, -1, 0, 6, 0, -15, 0, 20, 0, -15, 0, 6, 0, -1 }; /* -z^12 + 6*z^10 - 15*z^8 + 20*z^6 - 15*z^4 + 6*z^2 - 1 */
+static const long X1_32_crv_1[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 40, 120, 144, 240, 480, 480, 240, 144, 120, 40 }; /* 40*z^11 + 120*z^10 + 144*z^9 + 240*z^8 + 480*z^7 + 480*z^6 + 240*z^5 + 144*z^4 + 120*z^3 + 40*z^2 */
+static const long X1_32_crv_2[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, -10, -20, 90, 168, 132, 576, 1020, 600, 198, 212, 106 }; /* 106*z^11 + 212*z^10 + 198*z^9 + 600*z^8 + 1020*z^7 + 576*z^6 + 132*z^5 + 168*z^4 + 90*z^3 - 20*z^2 - 10*z */
+static const long X1_32_crv_3[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, -48, -48, 64, -128, -128, 768, 768, 64, 112, 112 }; /* 112*z^11 + 112*z^10 + 64*z^9 + 768*z^8 + 768*z^7 - 128*z^6 - 128*z^5 + 64*z^4 - 48*z^3 - 48*z^2 */
+static const long X1_32_crv_4[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 6, 0, -54, 24, 0, -432, 0, 664, -6, 0, 54 }; /* 54*z^11 - 6*z^9 + 664*z^8 - 432*z^6 + 24*z^4 - 54*z^3 + 6*z */
+static const long X1_32_crv_5[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 12, -12, 0, 96, -96, -352, 352, 0, -12, 12 }; /* 12*z^11 - 12*z^10 + 352*z^8 - 352*z^7 - 96*z^6 + 96*z^5 - 12*z^3 + 12*z^2 */
+static const long X1_32_crv_6[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, -1, 2, -1, -8, 16, 96, -208, 104, 1, -2, 1 }; /* z^11 - 2*z^10 + z^9 + 104*z^8 - 208*z^7 + 96*z^6 + 16*z^5 - 8*z^4 - z^3 + 2*z^2 - z */
+static const long X1_32_crv_7[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, 0, 0, 0, -16, 48, -48, 16 }; /* 16*z^8 - 48*z^7 + 48*z^6 - 16*z^5 */
+static const long X1_32_crv_8[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, 0, 0, 1, -4, 6, -4, 1 }; /* z^8 - 4*z^7 + 6*z^6 - 4*z^5 + z^4 */
+static const long *X1_32_crv[11] = {
+  (long *)(evaltyp(t_POL) | _evallg(11)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_32_crv_0, X1_32_crv_1, X1_32_crv_2, X1_32_crv_3, X1_32_crv_4, X1_32_crv_5, X1_32_crv_6, X1_32_crv_7, X1_32_crv_8
+};
+/* (z - 1)*x + 2*z */
+static const long X1_32_r_n_0[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, 2 }; /* 2*z */
+static const long X1_32_r_n_1[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, -1, 1 }; /* z - 1 */
+static const long *X1_32_r_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_32_r_n_0, X1_32_r_n_1
+};
+/* 2 */
+static const long X1_32_r_d_0[3] = {
+  evaltyp(t_VECSMALL) | _evallg(3), vZ, 2 }; /* 2 */
+static const long *X1_32_r_d[3] = {
+  (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_32_r_d_0
+};
+/* (-z + 1)*x - 2*z */
+static const long X1_32_s_n_0[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, -2 }; /* -2*z */
+static const long X1_32_s_n_1[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, -1 }; /* -z + 1 */
+static const long *X1_32_s_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_32_s_n_0, X1_32_s_n_1
+};
+/* 2*z */
+static const long X1_32_s_d_0[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, 2 }; /* 2*z */
+static const long *X1_32_s_d[3] = {
+  (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_32_s_d_0
+};
+/* z^8*x^10 + (-z^17 - 2*z^16 - 4*z^15 - 6*z^14 - 9*z^13 - 12*z^12 - 16*z^11 - 20*z^10 - 25*z^9 - 18*z^8)*x^9 + (-3*z^17 - 15*z^16 - 24*z^15 - 28*z^14 - 16*z^13 + 6*z^12 + 32*z^11 + 32*z^10 - 33*z^9 - 155*z^8 - 188*z^7 - 108*z^6 - 58*z^5 - 28*z^4 - 12*z^3 - 4*z^2 - z)*x^8 + (-6*z^17 - 48*z^16 - 144*z^15 - 226*z^14 - 225*z^13 - 39*z^12 + 402*z^11 + 1116*z^10 + 1854*z^9 + 2071*z^8 + 1536*z^7 + 852*z^6 + 476*z^5 + 249*z^4 + 114*z^3 + 40*z^2 + 9*z)*x^7 + (-10*z^17 - 110*z^16 - 520*z^15 - 146 [...]
+static const long X1_33_crv_0[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, 1, 8, 28, 56, 70, 56, 28, 8, 1 }; /* z^8 + 8*z^7 + 28*z^6 + 56*z^5 + 70*z^4 + 56*z^3 + 28*z^2 + 8*z + 1 */
+static const long X1_33_crv_1[20] = {
+  evaltyp(t_VECSMALL) | _evallg(20), vZ, -3, -9, 56, 462, 1659, 4025, 7506, 11292, 13882, 13938, 11376, 7490, 3927, 1605, 494, 108, 15, 1 }; /* z^17 + 15*z^16 + 108*z^15 + 494*z^14 + 1605*z^13 + 3927*z^12 + 7490*z^11 + 11376*z^10 + 13938*z^9 + 13882*z^8 + 11292*z^7 + 7506*z^6 + 4025*z^5 + 1659*z^4 + 462*z^3 + 56*z^2 - 9*z - 3 */
+static const long X1_33_crv_2[20] = {
+  evaltyp(t_VECSMALL) | _evallg(20), vZ, 3, -41, -476, -2184, -6328, -13480, -22380, -29288, -29900, -23253, -13080, -4536, -150, 884, 572, 192, 36, 3 }; /* 3*z^17 + 36*z^16 + 192*z^15 + 572*z^14 + 884*z^13 - 150*z^12 - 4536*z^11 - 13080*z^10 - 23253*z^9 - 29900*z^8 - 29288*z^7 - 22380*z^6 - 13480*z^5 - 6328*z^4 - 2184*z^3 - 476*z^2 - 41*z + 3 */
+static const long X1_33_crv_3[20] = {
+  evaltyp(t_VECSMALL) | _evallg(20), vZ, -1, 112, 896, 3458, 8779, 16391, 22966, 23336, 15607, 4499, -3020, -4432, -2392, -419, 254, 192, 54, 6 }; /* 6*z^17 + 54*z^16 + 192*z^15 + 254*z^14 - 419*z^13 - 2392*z^12 - 4432*z^11 - 3020*z^10 + 4499*z^9 + 15607*z^8 + 23336*z^7 + 22966*z^6 + 16391*z^5 + 8779*z^4 + 3458*z^3 + 896*z^2 + 112*z - 1 */
+static const long X1_33_crv_4[20] = {
+  evaltyp(t_VECSMALL) | _evallg(20), vZ, 0, -126, -840, -2808, -6174, -9630, -10032, -5292, 1576, 4980, 3456, 392, -1026, -690, -64, 120, 60, 10 }; /* 10*z^17 + 60*z^16 + 120*z^15 - 64*z^14 - 690*z^13 - 1026*z^12 + 392*z^11 + 3456*z^10 + 4980*z^9 + 1576*z^8 - 5292*z^7 - 10032*z^6 - 9630*z^5 - 6174*z^4 - 2808*z^3 - 840*z^2 - 126*z */
+static const long X1_33_crv_5[23] = {
+  evaltyp(t_VECSMALL) | _evallg(23), vZ, 0, 84, 480, 1422, 2801, 3917, 3762, 3188, 4847, 8886, 12028, 11872, 9198, 6042, 3576, 1872, 795, 255, 60, 10, 1 }; /* z^20 + 10*z^19 + 60*z^18 + 255*z^17 + 795*z^16 + 1872*z^15 + 3576*z^14 + 6042*z^13 + 9198*z^12 + 11872*z^11 + 12028*z^10 + 8886*z^9 + 4847*z^8 + 3188*z^7 + 3762*z^6 + 3917*z^5 + 2801*z^4 + 1422*z^3 + 480*z^2 + 84*z */
+static const long X1_33_crv_6[20] = {
+  evaltyp(t_VECSMALL) | _evallg(20), vZ, 0, -36, -180, -508, -1028, -1696, -2580, -4500, -7536, -9778, -9656, -7660, -5160, -3006, -1464, -520, -110, -10 }; /* -10*z^17 - 110*z^16 - 520*z^15 - 1464*z^14 - 3006*z^13 - 5160*z^12 - 7660*z^11 - 9656*z^10 - 9778*z^9 - 7536*z^8 - 4500*z^7 - 2580*z^6 - 1696*z^5 - 1028*z^4 - 508*z^3 - 180*z^2 - 36*z */
+static const long X1_33_crv_7[20] = {
+  evaltyp(t_VECSMALL) | _evallg(20), vZ, 0, 9, 40, 114, 249, 476, 852, 1536, 2071, 1854, 1116, 402, -39, -225, -226, -144, -48, -6 }; /* -6*z^17 - 48*z^16 - 144*z^15 - 226*z^14 - 225*z^13 - 39*z^12 + 402*z^11 + 1116*z^10 + 1854*z^9 + 2071*z^8 + 1536*z^7 + 852*z^6 + 476*z^5 + 249*z^4 + 114*z^3 + 40*z^2 + 9*z */
+static const long X1_33_crv_8[20] = {
+  evaltyp(t_VECSMALL) | _evallg(20), vZ, 0, -1, -4, -12, -28, -58, -108, -188, -155, -33, 32, 32, 6, -16, -28, -24, -15, -3 }; /* -3*z^17 - 15*z^16 - 24*z^15 - 28*z^14 - 16*z^13 + 6*z^12 + 32*z^11 + 32*z^10 - 33*z^9 - 155*z^8 - 188*z^7 - 108*z^6 - 58*z^5 - 28*z^4 - 12*z^3 - 4*z^2 - z */
+static const long X1_33_crv_9[20] = {
+  evaltyp(t_VECSMALL) | _evallg(20), vZ, 0, 0, 0, 0, 0, 0, 0, 0, -18, -25, -20, -16, -12, -9, -6, -4, -2, -1 }; /* -z^17 - 2*z^16 - 4*z^15 - 6*z^14 - 9*z^13 - 12*z^12 - 16*z^11 - 20*z^10 - 25*z^9 - 18*z^8 */
+static const long X1_33_crv_10[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; /* z^8 */
+static const long *X1_33_crv[13] = {
+  (long *)(evaltyp(t_POL) | _evallg(13)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_33_crv_0, X1_33_crv_1, X1_33_crv_2, X1_33_crv_3, X1_33_crv_4, X1_33_crv_5, X1_33_crv_6, X1_33_crv_7, X1_33_crv_8, X1_33_crv_9, X1_33_crv_10
+};
+/* (z + 1) */
+static const long X1_33_r_n_0[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */
+static const long *X1_33_r_n[3] = {
+  (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_33_r_n_0
+};
+/* z */
+static const long *X1_33_r_d[3] = {
+  (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_Z
+};
+/* 1 */
+static const long *X1_33_s_n[3] = {
+  (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_1
+};
+/* (-z - 1)*x + (z + 1) */
+static const long X1_33_s_d_0[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */
+static const long X1_33_s_d_1[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, -1, -1 }; /* -z - 1 */
+static const long *X1_33_s_d[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_33_s_d_0, X1_33_s_d_1
+};
+/* u^10 + (z^5 - z^2 - 4*z + 4)*u^9 + (8*z^5 - z^4 - 5*z^3 + z^2 - 12*z + 6)*u^8 + (5*z^7 - 2*z^6 + 16*z^5 - z^4 - 20*z^3 + 9*z^2 - 11*z + 4)*u^7 + (-z^8 + 24*z^7 + 2*z^6 + 7*z^5 - 36*z^3 + 8*z^2 + 1)*u^6 + (z^10 + z^9 - 7*z^8 + 40*z^7 + 26*z^6 + 2*z^5 + 8*z^4 - 29*z^3 - 3*z^2 + 5*z)*u^5 + (2*z^10 + 4*z^9 - 5*z^8 + 35*z^7 + 37*z^6 + 5*z^5 + 12*z^4 - 6*z^3 - 5*z^2 + 2*z)*u^4 + (z^10 + 4*z^9 + 7*z^8 + 28*z^7 + 29*z^6 + 7*z^5 + 5*z^4 + 3*z^3)*u^3 + (2*z^9 + 10*z^8 + 16*z^7 + 10*z^6 + 2*z^5  [...]
+static const long X1_34_crv_0[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, 0, 0, 0, 0, -1, -2, -1 }; /* -z^7 - 2*z^6 - z^5 */
+static const long X1_34_crv_1[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, -1, -1, -1, 0, 5, 5, 1 }; /* z^9 + 5*z^8 + 5*z^7 - z^5 - z^4 - z^3 */
+static const long X1_34_crv_2[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 1, 0, -1, 2, 10, 16, 10, 2 }; /* 2*z^9 + 10*z^8 + 16*z^7 + 10*z^6 + 2*z^5 - z^4 + z^2 */
+static const long X1_34_crv_3[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, 0, 3, 5, 7, 29, 28, 7, 4, 1 }; /* z^10 + 4*z^9 + 7*z^8 + 28*z^7 + 29*z^6 + 7*z^5 + 5*z^4 + 3*z^3 */
+static const long X1_34_crv_4[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 2, -5, -6, 12, 5, 37, 35, -5, 4, 2 }; /* 2*z^10 + 4*z^9 - 5*z^8 + 35*z^7 + 37*z^6 + 5*z^5 + 12*z^4 - 6*z^3 - 5*z^2 + 2*z */
+static const long X1_34_crv_5[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 5, -3, -29, 8, 2, 26, 40, -7, 1, 1 }; /* z^10 + z^9 - 7*z^8 + 40*z^7 + 26*z^6 + 2*z^5 + 8*z^4 - 29*z^3 - 3*z^2 + 5*z */
+static const long X1_34_crv_6[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, 1, 0, 8, -36, 0, 7, 2, 24, -1 }; /* -z^8 + 24*z^7 + 2*z^6 + 7*z^5 - 36*z^3 + 8*z^2 + 1 */
+static const long X1_34_crv_7[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, 4, -11, 9, -20, -1, 16, -2, 5 }; /* 5*z^7 - 2*z^6 + 16*z^5 - z^4 - 20*z^3 + 9*z^2 - 11*z + 4 */
+static const long X1_34_crv_8[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 6, -12, 1, -5, -1, 8 }; /* 8*z^5 - z^4 - 5*z^3 + z^2 - 12*z + 6 */
+static const long X1_34_crv_9[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 4, -4, -1, 0, 0, 1 }; /* z^5 - z^2 - 4*z + 4 */
+static const long *X1_34_crv[13] = {
+  (long *)(evaltyp(t_POL) | _evallg(13)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_34_crv_0, X1_34_crv_1, X1_34_crv_2, X1_34_crv_3, X1_34_crv_4, X1_34_crv_5, X1_34_crv_6, X1_34_crv_7, X1_34_crv_8, X1_34_crv_9, FLX_1
+};
+/* u^8 + (-z^2 - 3*z + 3)*u^7 + (-z^3 + 3*z^2 - 5*z + 3)*u^6 + (-3*z^4 - 11*z^3 + 7*z^2 - 2*z + 1)*u^5 + (2*z^5 + 2*z^4 - 15*z^3 + z^2 - z)*u^4 + (-2*z^6 + 5*z^4 - 7*z^3 - 3*z^2 - 2*z)*u^3 + (z^7 + 2*z^4 - z)*u^2 + (z^5 + z^4 + z^3 + z^2)*u + (z^6 + 2*z^5 + z^4) */
+static const long X1_34_r_n_0[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 0, 0, 1, 2, 1 }; /* z^6 + 2*z^5 + z^4 */
+static const long X1_34_r_n_1[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 1, 1, 1, 1 }; /* z^5 + z^4 + z^3 + z^2 */
+static const long X1_34_r_n_2[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, -1, 0, 0, 2, 0, 0, 1 }; /* z^7 + 2*z^4 - z */
+static const long X1_34_r_n_3[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, -2, -3, -7, 5, 0, -2 }; /* -2*z^6 + 5*z^4 - 7*z^3 - 3*z^2 - 2*z */
+static const long X1_34_r_n_4[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, -1, 1, -15, 2, 2 }; /* 2*z^5 + 2*z^4 - 15*z^3 + z^2 - z */
+static const long X1_34_r_n_5[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, -2, 7, -11, -3 }; /* -3*z^4 - 11*z^3 + 7*z^2 - 2*z + 1 */
+static const long X1_34_r_n_6[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 3, -5, 3, -1 }; /* -z^3 + 3*z^2 - 5*z + 3 */
+static const long X1_34_r_n_7[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 3, -3, -1 }; /* -z^2 - 3*z + 3 */
+static const long *X1_34_r_n[11] = {
+  (long *)(evaltyp(t_POL) | _evallg(11)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_34_r_n_0, X1_34_r_n_1, X1_34_r_n_2, X1_34_r_n_3, X1_34_r_n_4, X1_34_r_n_5, X1_34_r_n_6, X1_34_r_n_7, FLX_1
+};
+/* (-z^3 + 1)*u^6 + (-z^4 - 4*z^3 + 2*z^2 + 3)*u^5 + (-2*z^5 - 2*z^4 - 4*z^3 + 2*z^2 - 3*z + 3)*u^4 + (-z^6 - 2*z^5 - 2*z^4 - 5*z^3 - 3*z^2 - 6*z + 1)*u^3 + (z^7 - z^5 - 2*z^4 - 2*z^3 - z^2 - 3*z)*u^2 + (2*z^5 + 3*z^4 + 3*z^3 + 2*z^2)*u + (z^6 + 2*z^5 + z^4) */
+static const long X1_34_r_d_0[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 0, 0, 1, 2, 1 }; /* z^6 + 2*z^5 + z^4 */
+static const long X1_34_r_d_1[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 2, 3, 3, 2 }; /* 2*z^5 + 3*z^4 + 3*z^3 + 2*z^2 */
+static const long X1_34_r_d_2[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, -3, -1, -2, -2, -1, 0, 1 }; /* z^7 - z^5 - 2*z^4 - 2*z^3 - z^2 - 3*z */
+static const long X1_34_r_d_3[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 1, -6, -3, -5, -2, -2, -1 }; /* -z^6 - 2*z^5 - 2*z^4 - 5*z^3 - 3*z^2 - 6*z + 1 */
+static const long X1_34_r_d_4[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 3, -3, 2, -4, -2, -2 }; /* -2*z^5 - 2*z^4 - 4*z^3 + 2*z^2 - 3*z + 3 */
+static const long X1_34_r_d_5[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 3, 0, 2, -4, -1 }; /* -z^4 - 4*z^3 + 2*z^2 + 3 */
+static const long X1_34_r_d_6[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 1, 0, 0, -1 }; /* -z^3 + 1 */
+static const long *X1_34_r_d[9] = {
+  (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_34_r_d_0, X1_34_r_d_1, X1_34_r_d_2, X1_34_r_d_3, X1_34_r_d_4, X1_34_r_d_5, X1_34_r_d_6
+};
+/* -u^7 + (z^2 + 3*z - 3)*u^6 + (z^3 - 2*z^2 + 5*z - 3)*u^5 + (3*z^4 + 10*z^3 - 4*z^2 + z - 1)*u^4 + (-2*z^5 + 2*z^4 + 14*z^3 - 2*z)*u^3 + (z^6 + z^4 + 6*z^3 + z^2 - z)*u^2 + (z^4 + z^3)*u + (z^5 + 2*z^4 + z^3) */
+static const long X1_34_s_n_0[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 0, 1, 2, 1 }; /* z^5 + 2*z^4 + z^3 */
+static const long X1_34_s_n_1[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, 0, 1, 1 }; /* z^4 + z^3 */
+static const long X1_34_s_n_2[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, -1, 1, 6, 1, 0, 1 }; /* z^6 + z^4 + 6*z^3 + z^2 - z */
+static const long X1_34_s_n_3[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, -2, 0, 14, 2, -2 }; /* -2*z^5 + 2*z^4 + 14*z^3 - 2*z */
+static const long X1_34_s_n_4[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, -1, 1, -4, 10, 3 }; /* 3*z^4 + 10*z^3 - 4*z^2 + z - 1 */
+static const long X1_34_s_n_5[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, -3, 5, -2, 1 }; /* z^3 - 2*z^2 + 5*z - 3 */
+static const long X1_34_s_n_6[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, -3, 3, 1 }; /* z^2 + 3*z - 3 */
+static const long *X1_34_s_n[10] = {
+  (long *)(evaltyp(t_POL) | _evallg(10)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_34_s_n_0, X1_34_s_n_1, X1_34_s_n_2, X1_34_s_n_3, X1_34_s_n_4, X1_34_s_n_5, X1_34_s_n_6, FLX_m1
+};
+/* z*u^6 + (-z^2 + 3*z - 1)*u^5 + (4*z^3 - z^2 + z - 3)*u^4 + (-z^5 + 6*z^3 - z^2 - 2*z - 3)*u^3 + (z^6 + 3*z^3 + z^2 - 1)*u^2 + (2*z^4 + 3*z^3 + 2*z^2 + z)*u + (z^5 + 2*z^4 + z^3) */
+static const long X1_34_s_d_0[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 0, 1, 2, 1 }; /* z^5 + 2*z^4 + z^3 */
+static const long X1_34_s_d_1[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 1, 2, 3, 2 }; /* 2*z^4 + 3*z^3 + 2*z^2 + z */
+static const long X1_34_s_d_2[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, -1, 0, 1, 3, 0, 0, 1 }; /* z^6 + 3*z^3 + z^2 - 1 */
+static const long X1_34_s_d_3[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, -3, -2, -1, 6, 0, -1 }; /* -z^5 + 6*z^3 - z^2 - 2*z - 3 */
+static const long X1_34_s_d_4[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, -3, 1, -1, 4 }; /* 4*z^3 - z^2 + z - 3 */
+static const long X1_34_s_d_5[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, -1, 3, -1 }; /* -z^2 + 3*z - 1 */
+static const long *X1_34_s_d[9] = {
+  (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_34_s_d_0, X1_34_s_d_1, X1_34_s_d_2, X1_34_s_d_3, X1_34_s_d_4, X1_34_s_d_5, FLX_Z
+};
+/* z^3*u^12 + (-z^7 - 8*z^4 - 6*z^3 - z)*u^11 + (7*z^8 + 5*z^7 + 25*z^5 + 44*z^4 + 12*z^3 + 7*z^2 + 5*z)*u^10 + (-18*z^9 - 32*z^8 - 7*z^7 - 34*z^6 - 122*z^5 - 80*z^4 - 27*z^3 - 32*z^2 - 8*z + 1)*u^9 + (-z^11 + 19*z^10 + 72*z^9 + 41*z^8 + 3*z^7 + 141*z^6 + 193*z^5 + 71*z^4 + 75*z^3 + 47*z^2 - 2*z - 3)*u^8 + (4*z^12 + 4*z^11 - 59*z^10 - 79*z^9 + 44*z^8 + 5*z^7 - 178*z^6 - 100*z^5 - 72*z^4 - 99*z^3 - 9*z^2 + 17*z + 3)*u^7 + (-6*z^13 - 32*z^12 - 24*z^11 + 45*z^10 - 43*z^9 - 174*z^8 - 37*z^7  [...]
+static const long X1_35_crv_0[15] = {
+  evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 0, 0, 0, -1, -3, -3, -1, 0, -1, -3, -3, -1 }; /* -z^12 - 3*z^11 - 3*z^10 - z^9 - z^7 - 3*z^6 - 3*z^5 - z^4 */
+static const long X1_35_crv_1[16] = {
+  evaltyp(t_VECSMALL) | _evallg(16), vZ, 0, 0, -1, -3, 1, 7, 1, -7, -6, 1, 7, 1, -6, -3 }; /* -3*z^13 - 6*z^12 + z^11 + 7*z^10 + z^9 - 6*z^8 - 7*z^7 + z^6 + 7*z^5 + z^4 - 3*z^3 - z^2 */
+static const long X1_35_crv_2[18] = {
+  evaltyp(t_VECSMALL) | _evallg(18), vZ, 0, 0, 4, 7, -7, -8, 16, 20, 9, -3, 1, 26, 21, -3, -6, -1 }; /* -z^15 - 6*z^14 - 3*z^13 + 21*z^12 + 26*z^11 + z^10 - 3*z^9 + 9*z^8 + 20*z^7 + 16*z^6 - 8*z^5 - 7*z^4 + 7*z^3 + 4*z^2 */
+static const long X1_35_crv_3[18] = {
+  evaltyp(t_VECSMALL) | _evallg(18), vZ, 0, -1, -8, 0, 19, -15, -36, -7, 11, 25, -13, -45, 6, 36, 16, 2 }; /* 2*z^15 + 16*z^14 + 36*z^13 + 6*z^12 - 45*z^11 - 13*z^10 + 25*z^9 + 11*z^8 - 7*z^7 - 36*z^6 - 15*z^5 + 19*z^4 - 8*z^2 - z */
+static const long X1_35_crv_4[18] = {
+  evaltyp(t_VECSMALL) | _evallg(18), vZ, 0, 2, 0, -27, -6, 50, -3, -47, -84, -100, -6, 0, -72, -57, -14, -1 }; /* -z^15 - 14*z^14 - 57*z^13 - 72*z^12 - 6*z^10 - 100*z^9 - 84*z^8 - 47*z^7 - 3*z^6 + 50*z^5 - 6*z^4 - 27*z^3 + 2*z */
+static const long X1_35_crv_5[17] = {
+  evaltyp(t_VECSMALL) | _evallg(17), vZ, 0, 3, 27, 32, -52, -27, 60, 73, 183, 145, 9, 42, 80, 33, 4 }; /* 4*z^14 + 33*z^13 + 80*z^12 + 42*z^11 + 9*z^10 + 145*z^9 + 183*z^8 + 73*z^7 + 60*z^6 - 27*z^5 - 52*z^4 + 32*z^3 + 27*z^2 + 3*z */
+static const long X1_35_crv_6[16] = {
+  evaltyp(t_VECSMALL) | _evallg(16), vZ, -1, -15, -35, 34, 90, -1, 35, -37, -174, -43, 45, -24, -32, -6 }; /* -6*z^13 - 32*z^12 - 24*z^11 + 45*z^10 - 43*z^9 - 174*z^8 - 37*z^7 + 35*z^6 - z^5 + 90*z^4 + 34*z^3 - 35*z^2 - 15*z - 1 */
+static const long X1_35_crv_7[15] = {
+  evaltyp(t_VECSMALL) | _evallg(15), vZ, 3, 17, -9, -99, -72, -100, -178, 5, 44, -79, -59, 4, 4 }; /* 4*z^12 + 4*z^11 - 59*z^10 - 79*z^9 + 44*z^8 + 5*z^7 - 178*z^6 - 100*z^5 - 72*z^4 - 99*z^3 - 9*z^2 + 17*z + 3 */
+static const long X1_35_crv_8[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, -3, -2, 47, 75, 71, 193, 141, 3, 41, 72, 19, -1 }; /* -z^11 + 19*z^10 + 72*z^9 + 41*z^8 + 3*z^7 + 141*z^6 + 193*z^5 + 71*z^4 + 75*z^3 + 47*z^2 - 2*z - 3 */
+static const long X1_35_crv_9[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, 1, -8, -32, -27, -80, -122, -34, -7, -32, -18 }; /* -18*z^9 - 32*z^8 - 7*z^7 - 34*z^6 - 122*z^5 - 80*z^4 - 27*z^3 - 32*z^2 - 8*z + 1 */
+static const long X1_35_crv_10[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 5, 7, 12, 44, 25, 0, 5, 7 }; /* 7*z^8 + 5*z^7 + 25*z^5 + 44*z^4 + 12*z^3 + 7*z^2 + 5*z */
+static const long X1_35_crv_11[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, -1, 0, -6, -8, 0, 0, -1 }; /* -z^7 - 8*z^4 - 6*z^3 - z */
+static const long X1_35_crv_12[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 0, 1 }; /* z^3 */
+static const long *X1_35_crv[15] = {
+  (long *)(evaltyp(t_POL) | _evallg(15)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_35_crv_0, X1_35_crv_1, X1_35_crv_2, X1_35_crv_3, X1_35_crv_4, X1_35_crv_5, X1_35_crv_6, X1_35_crv_7, X1_35_crv_8, X1_35_crv_9, X1_35_crv_10, X1_35_crv_11, X1_35_crv_12
+};
+/* -z^8*u^19 + (11*z^9 + 8*z^8 + 2*z^6)*u^18 + (-51*z^10 - 83*z^9 - 24*z^8 - 20*z^7 - 13*z^6 - z^4)*u^17 + (125*z^11 + 359*z^10 + 234*z^9 + 118*z^8 + 124*z^7 + 30*z^6 + 7*z^5 + 4*z^4)*u^16 + (-156*z^12 - 804*z^11 - 940*z^10 - 498*z^9 - 527*z^8 - 273*z^7 - 46*z^6 - 25*z^5 - 4*z^4 + 2*z^3 + z^2)*u^15 + (35*z^13 + 861*z^12 + 1909*z^11 + 1379*z^10 + 1322*z^9 + 1091*z^8 + 261*z^7 + 70*z^6 + 19*z^5 - 16*z^4 - 15*z^3 - 2*z^2)*u^14 + (174*z^14 + 19*z^13 - 1703*z^12 - 2223*z^11 - 2147*z^10 - 2523 [...]
+static const long X1_35_r_n_0[20] = {
+  evaltyp(t_VECSMALL) | _evallg(20), vZ, 0, 0, 0, 0, 0, 0, 0, -1, -2, -1, 1, 2, 0, -2, -1, 1, 2, 1 }; /* z^17 + 2*z^16 + z^15 - z^14 - 2*z^13 + 2*z^11 + z^10 - z^9 - 2*z^8 - z^7 */
+static const long X1_35_r_n_1[21] = {
+  evaltyp(t_VECSMALL) | _evallg(21), vZ, 0, 0, 0, 0, 0, -2, -5, -1, -1, -4, -10, -5, 6, 4, -4, -8, 0, 7, 5 }; /* 5*z^18 + 7*z^17 - 8*z^15 - 4*z^14 + 4*z^13 + 6*z^12 - 5*z^11 - 10*z^10 - 4*z^9 - z^8 - z^7 - 5*z^6 - 2*z^5 */
+static const long X1_35_r_n_2[23] = {
+  evaltyp(t_VECSMALL) | _evallg(23), vZ, 0, 0, 0, 0, -1, 8, 1, -11, -19, -5, 9, -17, -25, -6, 0, -5, -44, -30, -4, 9, 1 }; /* z^20 + 9*z^19 - 4*z^18 - 30*z^17 - 44*z^16 - 5*z^15 - 6*z^13 - 25*z^12 - 17*z^11 + 9*z^10 - 5*z^9 - 19*z^8 - 11*z^7 + z^6 + 8*z^5 - z^4 */
+static const long X1_35_r_n_3[24] = {
+  evaltyp(t_VECSMALL) | _evallg(24), vZ, 0, 0, -1, 1, -4, -2, 31, 40, 35, -82, -54, 24, 49, 28, -29, -13, 43, -24, -43, -26, 7, 3 }; /* 3*z^21 + 7*z^20 - 26*z^19 - 43*z^18 - 24*z^17 + 43*z^16 - 13*z^15 - 29*z^14 + 28*z^13 + 49*z^12 + 24*z^11 - 54*z^10 - 82*z^9 + 35*z^8 + 40*z^7 + 31*z^6 - 2*z^5 - 4*z^4 + z^3 - z^2 */
+static const long X1_35_r_n_4[24] = {
+  evaltyp(t_VECSMALL) | _evallg(24), vZ, 0, 0, 0, -1, 4, -50, -42, -57, 172, 289, 29, -168, -137, 109, 385, 178, 86, 103, 79, 0, -37, -9 }; /* -9*z^21 - 37*z^20 + 79*z^18 + 103*z^17 + 86*z^16 + 178*z^15 + 385*z^14 + 109*z^13 - 137*z^12 - 168*z^11 + 29*z^10 + 289*z^9 + 172*z^8 - 57*z^7 - 42*z^6 - 50*z^5 + 4*z^4 - z^3 */
+static const long X1_35_r_n_5[24] = {
+  evaltyp(t_VECSMALL) | _evallg(24), vZ, 0, 0, 0, -13, 32, 34, 20, -125, -525, -71, 429, 449, -104, -802, -730, 74, 100, -10, -101, 40, 56, 9 }; /* 9*z^21 + 56*z^20 + 40*z^19 - 101*z^18 - 10*z^17 + 100*z^16 + 74*z^15 - 730*z^14 - 802*z^13 - 104*z^12 + 449*z^11 + 429*z^10 - 71*z^9 - 525*z^8 - 125*z^7 + 20*z^6 + 34*z^5 + 32*z^4 - 13*z^3 */
+static const long X1_35_r_n_6[24] = {
+  evaltyp(t_VECSMALL) | _evallg(24), vZ, 0, 0, 11, 2, -27, 39, -23, 463, 43, -905, -980, -67, 767, 1090, -515, -1148, -523, 201, 314, -2, -34, -3 }; /* -3*z^21 - 34*z^20 - 2*z^19 + 314*z^18 + 201*z^17 - 523*z^16 - 1148*z^15 - 515*z^14 + 1090*z^13 + 767*z^12 - 67*z^11 - 980*z^10 - 905*z^9 + 43*z^8 + 463*z^7 - 23*z^6 + 39*z^5 - 27*z^4 + 2*z^3 + 11*z^2 */
+static const long X1_35_r_n_7[23] = {
+  evaltyp(t_VECSMALL) | _evallg(23), vZ, 0, -2, -9, 12, -73, 53, -187, -100, 1264, 1491, 188, -708, -950, 396, 2413, 1590, 184, -898, -522, -40, 7 }; /* 7*z^20 - 40*z^19 - 522*z^18 - 898*z^17 + 184*z^16 + 1590*z^15 + 2413*z^14 + 396*z^13 - 950*z^12 - 708*z^11 + 188*z^10 + 1491*z^9 + 1264*z^8 - 100*z^7 - 187*z^6 + 53*z^5 - 73*z^4 + 12*z^3 - 9*z^2 - 2*z */
+static const long X1_35_r_n_8[22] = {
+  evaltyp(t_VECSMALL) | _evallg(22), vZ, 0, 2, -1, 75, 65, 36, 278, -952, -1589, -131, 1263, 1000, 870, -1704, -2243, -1194, 381, 1085, 357, 19 }; /* 19*z^19 + 357*z^18 + 1085*z^17 + 381*z^16 - 1194*z^15 - 2243*z^14 - 1704*z^13 + 870*z^12 + 1000*z^11 + 1263*z^10 - 131*z^9 - 1589*z^8 - 952*z^7 + 278*z^6 + 36*z^5 + 65*z^4 + 75*z^3 - z^2 + 2*z */
+static const long X1_35_r_n_9[21] = {
+  evaltyp(t_VECSMALL) | _evallg(21), vZ, 0, 0, -43, -132, -62, -319, 249, 1172, 163, -1685, -1471, -2155, -1299, 1203, 1797, 1678, -149, -520, -85 }; /* -85*z^18 - 520*z^17 - 149*z^16 + 1678*z^15 + 1797*z^14 + 1203*z^13 - 1299*z^12 - 2155*z^11 - 1471*z^10 - 1685*z^9 + 163*z^8 + 1172*z^7 + 249*z^6 - 319*z^5 - 62*z^4 - 132*z^3 - 43*z^2 */
+static const long X1_35_r_n_10[20] = {
+  evaltyp(t_VECSMALL) | _evallg(20), vZ, 0, 11, 81, 84, 181, 111, -614, -339, 1142, 1495, 2152, 3806, 1269, -902, -2809, -2096, -152, 85 }; /* 85*z^17 - 152*z^16 - 2096*z^15 - 2809*z^14 - 902*z^13 + 1269*z^12 + 3806*z^11 + 2152*z^10 + 1495*z^9 + 1142*z^8 - 339*z^7 - 614*z^6 + 111*z^5 + 181*z^4 + 84*z^3 + 81*z^2 + 11*z */
+static const long X1_35_r_n_11[19] = {
+  evaltyp(t_VECSMALL) | _evallg(19), vZ, -1, -21, -46, -57, -90, 253, 373, -294, -855, -1239, -3864, -3365, -944, 1080, 2713, 1175, 72 }; /* 72*z^16 + 1175*z^15 + 2713*z^14 + 1080*z^13 - 944*z^12 - 3365*z^11 - 3864*z^10 - 1239*z^9 - 855*z^8 - 294*z^7 + 373*z^6 + 253*z^5 - 90*z^4 - 57*z^3 - 46*z^2 - 21*z - 1 */
+static const long X1_35_r_n_12[18] = {
+  evaltyp(t_VECSMALL) | _evallg(18), vZ, 2, 11, 11, 21, -88, -225, -65, 272, 472, 2378, 3700, 2193, 1490, -552, -1155, -232 }; /* -232*z^15 - 1155*z^14 - 552*z^13 + 1490*z^12 + 2193*z^11 + 3700*z^10 + 2378*z^9 + 472*z^8 + 272*z^7 - 65*z^6 - 225*z^5 - 88*z^4 + 21*z^3 + 11*z^2 + 11*z + 2 */
+static const long X1_35_r_n_13[17] = {
+  evaltyp(t_VECSMALL) | _evallg(17), vZ, -1, -1, -2, 21, 79, 61, -62, -162, -972, -2523, -2147, -2223, -1703, 19, 174 }; /* 174*z^14 + 19*z^13 - 1703*z^12 - 2223*z^11 - 2147*z^10 - 2523*z^9 - 972*z^8 - 162*z^7 - 62*z^6 + 61*z^5 + 79*z^4 + 21*z^3 - 2*z^2 - z - 1 */
+static const long X1_35_r_n_14[16] = {
+  evaltyp(t_VECSMALL) | _evallg(16), vZ, 0, 0, -2, -15, -16, 19, 70, 261, 1091, 1322, 1379, 1909, 861, 35 }; /* 35*z^13 + 861*z^12 + 1909*z^11 + 1379*z^10 + 1322*z^9 + 1091*z^8 + 261*z^7 + 70*z^6 + 19*z^5 - 16*z^4 - 15*z^3 - 2*z^2 */
+static const long X1_35_r_n_15[15] = {
+  evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 0, 1, 2, -4, -25, -46, -273, -527, -498, -940, -804, -156 }; /* -156*z^12 - 804*z^11 - 940*z^10 - 498*z^9 - 527*z^8 - 273*z^7 - 46*z^6 - 25*z^5 - 4*z^4 + 2*z^3 + z^2 */
+static const long X1_35_r_n_16[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 0, 4, 7, 30, 124, 118, 234, 359, 125 }; /* 125*z^11 + 359*z^10 + 234*z^9 + 118*z^8 + 124*z^7 + 30*z^6 + 7*z^5 + 4*z^4 */
+static const long X1_35_r_n_17[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, 0, 0, -1, 0, -13, -20, -24, -83, -51 }; /* -51*z^10 - 83*z^9 - 24*z^8 - 20*z^7 - 13*z^6 - z^4 */
+static const long X1_35_r_n_18[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, 0, 0, 0, 2, 0, 8, 11 }; /* 11*z^9 + 8*z^8 + 2*z^6 */
+static const long X1_35_r_n_19[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, 0, 0, 0, 0, 0, 0, -1 }; /* -z^8 */
+static const long *X1_35_r_n[22] = {
+  (long *)(evaltyp(t_POL) | _evallg(22)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_35_r_n_0, X1_35_r_n_1, X1_35_r_n_2, X1_35_r_n_3, X1_35_r_n_4, X1_35_r_n_5, X1_35_r_n_6, X1_35_r_n_7, X1_35_r_n_8, X1_35_r_n_9, X1_35_r_n_10, X1_35_r_n_11, X1_35_r_n_12, X1_35_r_n_13, X1_35_r_n_14, X1_35_r_n_15, X1_35_r_n_16, X1_35_r_n_17, X1_35_r_n_18, X1_35_r_n_19
+};
+/* (-z^10 + z^7)*u^16 + (10*z^11 + 5*z^10 - 9*z^8 - 4*z^7 - 2*z^5 - z^4)*u^15 + (-40*z^12 - 47*z^11 - 8*z^10 + 32*z^9 + 35*z^8 + 4*z^7 + 19*z^6 + 17*z^5 + 4*z^4 + z^3 + 2*z^2)*u^14 + (-z^14 + 77*z^13 + 175*z^12 + 71*z^11 - 48*z^10 - 122*z^9 - 33*z^8 - 75*z^7 - 107*z^6 - 48*z^5 - 12*z^4 - 22*z^3 - 6*z^2 - 1)*u^13 + (7*z^15 - 50*z^14 - 307*z^13 - 248*z^12 - 21*z^11 + 193*z^10 + 109*z^9 + 149*z^8 + 348*z^7 + 235*z^6 + 71*z^5 + 95*z^4 + 63*z^3 + 3*z^2 + 9*z + 2)*u^12 + (-19*z^16 - 79*z^15 +  [...]
+static const long X1_35_r_d_0[20] = {
+  evaltyp(t_VECSMALL) | _evallg(20), vZ, 0, 0, 0, 0, 0, 0, 0, -1, -2, -1, 1, 2, 0, -2, -1, 1, 2, 1 }; /* z^17 + 2*z^16 + z^15 - z^14 - 2*z^13 + 2*z^11 + z^10 - z^9 - 2*z^8 - z^7 */
+static const long X1_35_r_d_1[21] = {
+  evaltyp(t_VECSMALL) | _evallg(21), vZ, 0, 0, 0, 0, 1, 2, 2, 3, -7, -17, -19, -3, 14, 9, -4, -10, -1, 7, 5 }; /* 5*z^18 + 7*z^17 - z^16 - 10*z^15 - 4*z^14 + 9*z^13 + 14*z^12 - 3*z^11 - 19*z^10 - 17*z^9 - 7*z^8 + 3*z^7 + 2*z^6 + 2*z^5 + z^4 */
+static const long X1_35_r_d_2[23] = {
+  evaltyp(t_VECSMALL) | _evallg(23), vZ, 0, 0, 0, 1, -1, 4, 0, 19, 38, 28, -24, -85, -60, 8, 26, 2, -51, -36, -4, 9, 1 }; /* z^20 + 9*z^19 - 4*z^18 - 36*z^17 - 51*z^16 + 2*z^15 + 26*z^14 + 8*z^13 - 60*z^12 - 85*z^11 - 24*z^10 + 28*z^9 + 38*z^8 + 19*z^7 + 4*z^5 - z^4 + z^3 */
+static const long X1_35_r_d_3[24] = {
+  evaltyp(t_VECSMALL) | _evallg(24), vZ, 0, 0, -1, 0, -3, 6, 18, -18, 36, 80, 186, 88, -115, -162, -67, 68, 104, -16, -58, -27, 7, 3 }; /* 3*z^21 + 7*z^20 - 27*z^19 - 58*z^18 - 16*z^17 + 104*z^16 + 68*z^15 - 67*z^14 - 162*z^13 - 115*z^12 + 88*z^11 + 186*z^10 + 80*z^9 + 36*z^8 - 18*z^7 + 18*z^6 + 6*z^5 - 3*z^4 - z^2 */
+static const long X1_35_r_d_4[24] = {
+  evaltyp(t_VECSMALL) | _evallg(24), vZ, 0, 0, 0, 0, 4, -48, 12, -56, -62, -81, 43, 451, 509, 219, 7, -130, 70, 208, 130, -16, -40, -9 }; /* -9*z^21 - 40*z^20 - 16*z^19 + 130*z^18 + 208*z^17 + 70*z^16 - 130*z^15 + 7*z^14 + 219*z^13 + 509*z^12 + 451*z^11 + 43*z^10 - 81*z^9 - 62*z^8 - 56*z^7 + 12*z^6 - 48*z^5 + 4*z^4 */
+static const long X1_35_r_d_5[24] = {
+  evaltyp(t_VECSMALL) | _evallg(24), vZ, 0, 0, 0, -19, 19, -22, -19, 91, -108, -58, -532, -610, -122, 189, 143, -4, -367, -304, -49, 128, 66, 9 }; /* 9*z^21 + 66*z^20 + 128*z^19 - 49*z^18 - 304*z^17 - 367*z^16 - 4*z^15 + 143*z^14 + 189*z^13 - 122*z^12 - 610*z^11 - 532*z^10 - 58*z^9 - 108*z^8 + 91*z^7 - 19*z^6 - 22*z^5 + 19*z^4 - 19*z^3 */
+static const long X1_35_r_d_6[24] = {
+  evaltyp(t_VECSMALL) | _evallg(24), vZ, 0, 0, 12, 11, 11, 86, -218, 43, -109, -60, 132, -341, -810, -385, -237, 171, 363, 231, -94, -158, -45, -3 }; /* -3*z^21 - 45*z^20 - 158*z^19 - 94*z^18 + 231*z^17 + 363*z^16 + 171*z^15 - 237*z^14 - 385*z^13 - 810*z^12 - 341*z^11 + 132*z^10 - 60*z^9 - 109*z^8 + 43*z^7 - 218*z^6 + 86*z^5 + 11*z^4 + 11*z^3 + 12*z^2 */
+static const long X1_35_r_d_7[23] = {
+  evaltyp(t_VECSMALL) | _evallg(23), vZ, 0, -2, -10, -1, -109, 191, 163, 9, 589, 413, 575, 1094, 840, 459, 466, -33, -307, -240, 84, 75, 11 }; /* 11*z^20 + 75*z^19 + 84*z^18 - 240*z^17 - 307*z^16 - 33*z^15 + 466*z^14 + 459*z^13 + 840*z^12 + 1094*z^11 + 575*z^10 + 413*z^9 + 589*z^8 + 9*z^7 + 163*z^6 + 191*z^5 - 109*z^4 - z^3 - 10*z^2 - 2*z */
+static const long X1_35_r_d_8[22] = {
+  evaltyp(t_VECSMALL) | _evallg(22), vZ, 0, 2, 0, 91, 2, -201, 295, -282, -456, -196, -445, -885, -517, -883, -548, 53, 539, 271, -6, -11 }; /* -11*z^19 - 6*z^18 + 271*z^17 + 539*z^16 + 53*z^15 - 548*z^14 - 883*z^13 - 517*z^12 - 885*z^11 - 445*z^10 - 196*z^9 - 456*z^8 - 282*z^7 + 295*z^6 - 201*z^5 + 2*z^4 + 91*z^3 + 2*z */
+static const long X1_35_r_d_9[21] = {
+  evaltyp(t_VECSMALL) | _evallg(21), vZ, 0, 0, -45, -108, 75, -348, -343, 106, -317, -520, 204, 382, 598, 779, 307, -311, -520, -142, -7 }; /* -7*z^18 - 142*z^17 - 520*z^16 - 311*z^15 + 307*z^14 + 779*z^13 + 598*z^12 + 382*z^11 + 204*z^10 - 520*z^9 - 317*z^8 + 106*z^7 - 343*z^6 - 348*z^5 + 75*z^4 - 108*z^3 - 45*z^2 */
+static const long X1_35_r_d_10[20] = {
+  evaltyp(t_VECSMALL) | _evallg(20), vZ, 0, 11, 73, 21, 171, 492, 180, 427, 884, 512, -106, -70, -436, -400, -206, 271, 192, 23 }; /* 23*z^17 + 192*z^16 + 271*z^15 - 206*z^14 - 400*z^13 - 436*z^12 - 70*z^11 - 106*z^10 + 512*z^9 + 884*z^8 + 427*z^7 + 180*z^6 + 492*z^5 + 171*z^4 + 21*z^3 + 73*z^2 + 11*z */
+static const long X1_35_r_d_11[19] = {
+  evaltyp(t_VECSMALL) | _evallg(19), vZ, -1, -20, -28, -38, -257, -201, -237, -612, -627, -117, -153, -27, 219, 406, 169, -79, -19 }; /* -19*z^16 - 79*z^15 + 169*z^14 + 406*z^13 + 219*z^12 - 27*z^11 - 153*z^10 - 117*z^9 - 627*z^8 - 612*z^7 - 237*z^6 - 201*z^5 - 257*z^4 - 38*z^3 - 28*z^2 - 20*z - 1 */
+static const long X1_35_r_d_12[18] = {
+  evaltyp(t_VECSMALL) | _evallg(18), vZ, 2, 9, 3, 63, 95, 71, 235, 348, 149, 109, 193, -21, -248, -307, -50, 7 }; /* 7*z^15 - 50*z^14 - 307*z^13 - 248*z^12 - 21*z^11 + 193*z^10 + 109*z^9 + 149*z^8 + 348*z^7 + 235*z^6 + 71*z^5 + 95*z^4 + 63*z^3 + 3*z^2 + 9*z + 2 */
+static const long X1_35_r_d_13[17] = {
+  evaltyp(t_VECSMALL) | _evallg(17), vZ, -1, 0, -6, -22, -12, -48, -107, -75, -33, -122, -48, 71, 175, 77, -1 }; /* -z^14 + 77*z^13 + 175*z^12 + 71*z^11 - 48*z^10 - 122*z^9 - 33*z^8 - 75*z^7 - 107*z^6 - 48*z^5 - 12*z^4 - 22*z^3 - 6*z^2 - 1 */
+static const long X1_35_r_d_14[15] = {
+  evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 0, 2, 1, 4, 17, 19, 4, 35, 32, -8, -47, -40 }; /* -40*z^12 - 47*z^11 - 8*z^10 + 32*z^9 + 35*z^8 + 4*z^7 + 19*z^6 + 17*z^5 + 4*z^4 + z^3 + 2*z^2 */
+static const long X1_35_r_d_15[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 0, -1, -2, 0, -4, -9, 0, 5, 10 }; /* 10*z^11 + 5*z^10 - 9*z^8 - 4*z^7 - 2*z^5 - z^4 */
+static const long X1_35_r_d_16[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1 }; /* -z^10 + z^7 */
+static const long *X1_35_r_d[19] = {
+  (long *)(evaltyp(t_POL) | _evallg(19)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_35_r_d_0, X1_35_r_d_1, X1_35_r_d_2, X1_35_r_d_3, X1_35_r_d_4, X1_35_r_d_5, X1_35_r_d_6, X1_35_r_d_7, X1_35_r_d_8, X1_35_r_d_9, X1_35_r_d_10, X1_35_r_d_11, X1_35_r_d_12, X1_35_r_d_13, X1_35_r_d_14, X1_35_r_d_15, X1_35_r_d_16
+};
+/* z^4*u^10 + (-5*z^5 - 4*z^4 - z^2)*u^9 + (7*z^6 + 18*z^5 + 4*z^4 + 4*z^3 + 2*z^2)*u^8 + (3*z^7 - 22*z^6 - 16*z^5 - 5*z^4 - 6*z^3 + z + 1)*u^7 + (-14*z^8 - 10*z^7 + 17*z^6 + z^5 + 5*z^4 - 3*z^3 - 3*z^2 - 6*z - 1)*u^6 + (7*z^9 + 36*z^8 + 8*z^7 + 2*z^6 - z^5 + 5*z^4 + 3*z^3 + 10*z^2 + 6*z)*u^5 + (4*z^10 - 15*z^9 - 23*z^8 + 2*z^6 + 3*z^5 + z^4 - 3*z^3 - 9*z^2)*u^4 + (-3*z^11 - 9*z^10 + 8*z^9 - 2*z^8 - 4*z^7 - 9*z^6 - 5*z^5 - 6*z^4 + 6*z^3 - z^2)*u^3 + (6*z^11 + 5*z^10 + 3*z^8 + 4*z^7 + 3*z [...]
+static const long X1_35_s_n_0[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1 }; /* -z^10 - z^5 */
+static const long X1_35_s_n_1[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, -2, 1, 0, -2, -1, -1, 0, 1, -3 }; /* -3*z^11 + z^10 - z^8 - z^7 - 2*z^6 + z^4 - 2*z^3 */
+static const long X1_35_s_n_2[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, -1, 1, 0, -3, 5, 3, 4, 3, 0, 5, 6 }; /* 6*z^11 + 5*z^10 + 3*z^8 + 4*z^7 + 3*z^6 + 5*z^5 - 3*z^4 + z^2 - z */
+static const long X1_35_s_n_3[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, -1, 6, -6, -5, -9, -4, -2, 8, -9, -3 }; /* -3*z^11 - 9*z^10 + 8*z^9 - 2*z^8 - 4*z^7 - 9*z^6 - 5*z^5 - 6*z^4 + 6*z^3 - z^2 */
+static const long X1_35_s_n_4[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, -9, -3, 1, 3, 2, 0, -23, -15, 4 }; /* 4*z^10 - 15*z^9 - 23*z^8 + 2*z^6 + 3*z^5 + z^4 - 3*z^3 - 9*z^2 */
+static const long X1_35_s_n_5[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 6, 10, 3, 5, -1, 2, 8, 36, 7 }; /* 7*z^9 + 36*z^8 + 8*z^7 + 2*z^6 - z^5 + 5*z^4 + 3*z^3 + 10*z^2 + 6*z */
+static const long X1_35_s_n_6[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, -1, -6, -3, -3, 5, 1, 17, -10, -14 }; /* -14*z^8 - 10*z^7 + 17*z^6 + z^5 + 5*z^4 - 3*z^3 - 3*z^2 - 6*z - 1 */
+static const long X1_35_s_n_7[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, 1, 1, 0, -6, -5, -16, -22, 3 }; /* 3*z^7 - 22*z^6 - 16*z^5 - 5*z^4 - 6*z^3 + z + 1 */
+static const long X1_35_s_n_8[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 2, 4, 4, 18, 7 }; /* 7*z^6 + 18*z^5 + 4*z^4 + 4*z^3 + 2*z^2 */
+static const long X1_35_s_n_9[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, -1, 0, -4, -5 }; /* -5*z^5 - 4*z^4 - z^2 */
+static const long X1_35_s_n_10[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, 0, 0, 1 }; /* z^4 */
+static const long *X1_35_s_n[13] = {
+  (long *)(evaltyp(t_POL) | _evallg(13)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_35_s_n_0, X1_35_s_n_1, X1_35_s_n_2, X1_35_s_n_3, X1_35_s_n_4, X1_35_s_n_5, X1_35_s_n_6, X1_35_s_n_7, X1_35_s_n_8, X1_35_s_n_9, X1_35_s_n_10
+};
+/* z^5*u^9 + (-6*z^6 - 3*z^5 - z^3 - z^2)*u^8 + (13*z^7 + 16*z^6 + 2*z^5 + 5*z^4 + 8*z^3 + 2*z^2 + 1)*u^7 + (-10*z^8 - 31*z^7 - 9*z^6 - 10*z^5 - 22*z^4 - 13*z^3 + z^2 - 5*z - 1)*u^6 + (-3*z^9 + 21*z^8 + 16*z^7 + 10*z^6 + 30*z^5 + 28*z^4 - 3*z^3 + 6*z^2 + 6*z)*u^5 + (8*z^10 + 7*z^9 - 11*z^8 - 5*z^7 - 22*z^6 - 25*z^5 + 5*z^4 + 6*z^3 - 10*z^2)*u^4 + (-3*z^11 - 16*z^10 - 3*z^9 + z^8 + 7*z^7 + 6*z^6 - 8*z^5 - 20*z^4 + 5*z^3)*u^3 + (6*z^11 + 8*z^10 - z^9 + 3*z^7 + 7*z^6 + 16*z^5 + z^4 - 2*z^3  [...]
+static const long X1_35_s_d_0[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1 }; /* -z^10 - z^5 */
+static const long X1_35_s_d_1[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 1, 0, 3, -1, -4, -2, -1, 1, 1, -3 }; /* -3*z^11 + z^10 + z^9 - z^8 - 2*z^7 - 4*z^6 - z^5 + 3*z^4 + z^2 */
+static const long X1_35_s_d_2[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, -1, 0, -2, 1, 16, 7, 3, 0, -1, 8, 6 }; /* 6*z^11 + 8*z^10 - z^9 + 3*z^7 + 7*z^6 + 16*z^5 + z^4 - 2*z^3 - z */
+static const long X1_35_s_d_3[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 5, -20, -8, 6, 7, 1, -3, -16, -3 }; /* -3*z^11 - 16*z^10 - 3*z^9 + z^8 + 7*z^7 + 6*z^6 - 8*z^5 - 20*z^4 + 5*z^3 */
+static const long X1_35_s_d_4[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, -10, 6, 5, -25, -22, -5, -11, 7, 8 }; /* 8*z^10 + 7*z^9 - 11*z^8 - 5*z^7 - 22*z^6 - 25*z^5 + 5*z^4 + 6*z^3 - 10*z^2 */
+static const long X1_35_s_d_5[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 6, 6, -3, 28, 30, 10, 16, 21, -3 }; /* -3*z^9 + 21*z^8 + 16*z^7 + 10*z^6 + 30*z^5 + 28*z^4 - 3*z^3 + 6*z^2 + 6*z */
+static const long X1_35_s_d_6[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, -1, -5, 1, -13, -22, -10, -9, -31, -10 }; /* -10*z^8 - 31*z^7 - 9*z^6 - 10*z^5 - 22*z^4 - 13*z^3 + z^2 - 5*z - 1 */
+static const long X1_35_s_d_7[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, 1, 0, 2, 8, 5, 2, 16, 13 }; /* 13*z^7 + 16*z^6 + 2*z^5 + 5*z^4 + 8*z^3 + 2*z^2 + 1 */
+static const long X1_35_s_d_8[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, -1, -1, 0, -3, -6 }; /* -6*z^6 - 3*z^5 - z^3 - z^2 */
+static const long X1_35_s_d_9[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 0, 0, 0, 1 }; /* z^5 */
+static const long *X1_35_s_d[12] = {
+  (long *)(evaltyp(t_POL) | _evallg(12)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_35_s_d_0, X1_35_s_d_1, X1_35_s_d_2, X1_35_s_d_3, X1_35_s_d_4, X1_35_s_d_5, X1_35_s_d_6, X1_35_s_d_7, X1_35_s_d_8, X1_35_s_d_9
+};
+/* (z^7 - 2*z^6 + 2*z^5 - z^4)*u^8 + (4*z^8 - 4*z^7 + 4*z^5 - 4*z^4)*u^7 + (6*z^9 + 2*z^8 - 10*z^7 + 10*z^6 + z^5 - 13*z^4 + 4*z^3 - z^2)*u^6 + (4*z^10 + 10*z^9 - 10*z^8 + 24*z^6 - 36*z^5 + 2*z^4 + 2*z^3 - 2*z^2)*u^5 + (z^11 + 8*z^10 + z^9 - 9*z^8 + 27*z^7 - 9*z^6 - 55*z^5 + 34*z^4 - 13*z^3)*u^4 + (2*z^11 + 4*z^10 - 4*z^9 + 8*z^8 + 26*z^7 - 54*z^6 - 24*z^5 + 50*z^4 - 38*z^3 + 12*z^2 - 2*z)*u^3 + (z^11 + 15*z^8 - 3*z^7 - 43*z^6 + 9*z^5 + 29*z^4 - 39*z^3 + 22*z^2 - 7*z + 1)*u^2 + (2*z^9 +  [...]
+static const long X1_36_crv_0[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, 0, 0, 0, 1, -3, 0, 1 }; /* z^9 - 3*z^7 + z^6 */
+static const long X1_36_crv_1[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, 2, -10, 18, -14, -10, 6, 2 }; /* 2*z^9 + 6*z^8 - 10*z^7 - 14*z^6 + 18*z^5 - 10*z^4 + 2*z^3 */
+static const long X1_36_crv_2[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 1, -7, 22, -39, 29, 9, -43, -3, 15, 0, 0, 1 }; /* z^11 + 15*z^8 - 3*z^7 - 43*z^6 + 9*z^5 + 29*z^4 - 39*z^3 + 22*z^2 - 7*z + 1 */
+static const long X1_36_crv_3[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, -2, 12, -38, 50, -24, -54, 26, 8, -4, 4, 2 }; /* 2*z^11 + 4*z^10 - 4*z^9 + 8*z^8 + 26*z^7 - 54*z^6 - 24*z^5 + 50*z^4 - 38*z^3 + 12*z^2 - 2*z */
+static const long X1_36_crv_4[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, -13, 34, -55, -9, 27, -9, 1, 8, 1 }; /* z^11 + 8*z^10 + z^9 - 9*z^8 + 27*z^7 - 9*z^6 - 55*z^5 + 34*z^4 - 13*z^3 */
+static const long X1_36_crv_5[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, -2, 2, 2, -36, 24, 0, -10, 10, 4 }; /* 4*z^10 + 10*z^9 - 10*z^8 + 24*z^6 - 36*z^5 + 2*z^4 + 2*z^3 - 2*z^2 */
+static const long X1_36_crv_6[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, -1, 4, -13, 1, 10, -10, 2, 6 }; /* 6*z^9 + 2*z^8 - 10*z^7 + 10*z^6 + z^5 - 13*z^4 + 4*z^3 - z^2 */
+static const long X1_36_crv_7[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, 0, 0, -4, 4, 0, -4, 4 }; /* 4*z^8 - 4*z^7 + 4*z^5 - 4*z^4 */
+static const long X1_36_crv_8[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, 0, 0, 0, -1, 2, -2, 1 }; /* z^7 - 2*z^6 + 2*z^5 - z^4 */
+static const long *X1_36_crv[11] = {
+  (long *)(evaltyp(t_POL) | _evallg(11)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_36_crv_0, X1_36_crv_1, X1_36_crv_2, X1_36_crv_3, X1_36_crv_4, X1_36_crv_5, X1_36_crv_6, X1_36_crv_7, X1_36_crv_8
+};
+/* (z^3 - z)*u^4 + (4*z^4 - 4*z^2)*u^3 + (5*z^5 + z^4 - 6*z^3 - z^2 - 1)*u^2 + (2*z^6 + 2*z^5 - 4*z^4 - 2*z^3 - 2*z)*u + (z^6 - z^5 - 2*z^4 + 3*z^3 - 5*z^2 + 3*z - 1) */
+static const long X1_36_r_n_0[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, -1, 3, -5, 3, -2, -1, 1 }; /* z^6 - z^5 - 2*z^4 + 3*z^3 - 5*z^2 + 3*z - 1 */
+static const long X1_36_r_n_1[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, -2, 0, -2, -4, 2, 2 }; /* 2*z^6 + 2*z^5 - 4*z^4 - 2*z^3 - 2*z */
+static const long X1_36_r_n_2[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, -1, 0, -1, -6, 1, 5 }; /* 5*z^5 + z^4 - 6*z^3 - z^2 - 1 */
+static const long X1_36_r_n_3[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, -4, 0, 4 }; /* 4*z^4 - 4*z^2 */
+static const long X1_36_r_n_4[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, -1, 0, 1 }; /* z^3 - z */
+static const long *X1_36_r_n[7] = {
+  (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_36_r_n_0, X1_36_r_n_1, X1_36_r_n_2, X1_36_r_n_3, X1_36_r_n_4
+};
+/* (z^3 - z)*u^4 + (6*z^4 - 2*z^3 - 4*z^2 + z)*u^3 + (7*z^5 + 3*z^4 - 12*z^3 + 3*z^2 + z - 1)*u^2 + (2*z^6 + 5*z^5 - 5*z^4 - 8*z^3 + 9*z^2 - 5*z + 1)*u + (z^6 - 3*z^4 + z^3) */
+static const long X1_36_r_d_0[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 0, 1, -3, 0, 1 }; /* z^6 - 3*z^4 + z^3 */
+static const long X1_36_r_d_1[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 1, -5, 9, -8, -5, 5, 2 }; /* 2*z^6 + 5*z^5 - 5*z^4 - 8*z^3 + 9*z^2 - 5*z + 1 */
+static const long X1_36_r_d_2[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, -1, 1, 3, -12, 3, 7 }; /* 7*z^5 + 3*z^4 - 12*z^3 + 3*z^2 + z - 1 */
+static const long X1_36_r_d_3[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 1, -4, -2, 6 }; /* 6*z^4 - 2*z^3 - 4*z^2 + z */
+static const long X1_36_r_d_4[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, -1, 0, 1 }; /* z^3 - z */
+static const long *X1_36_r_d[7] = {
+  (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_36_r_d_0, X1_36_r_d_1, X1_36_r_d_2, X1_36_r_d_3, X1_36_r_d_4
+};
+/* (z^3 - z)*u^4 + (2*z^4 + 2*z^3 - 4*z^2 - z)*u^3 + (z^5 + 3*z^4 - 2*z^3 - 6*z^2 - 1)*u^2 + (z^5 + z^4 - 4*z^3 - 5*z^2 + z - 1)*u + (-2*z^3 - 2*z^2 + 2*z - 1) */
+static const long X1_36_s_n_0[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, -1, 2, -2, -2 }; /* -2*z^3 - 2*z^2 + 2*z - 1 */
+static const long X1_36_s_n_1[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, -1, 1, -5, -4, 1, 1 }; /* z^5 + z^4 - 4*z^3 - 5*z^2 + z - 1 */
+static const long X1_36_s_n_2[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, -1, 0, -6, -2, 3, 1 }; /* z^5 + 3*z^4 - 2*z^3 - 6*z^2 - 1 */
+static const long X1_36_s_n_3[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, -1, -4, 2, 2 }; /* 2*z^4 + 2*z^3 - 4*z^2 - z */
+static const long X1_36_s_n_4[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, -1, 0, 1 }; /* z^3 - z */
+static const long *X1_36_s_n[7] = {
+  (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_36_s_n_0, X1_36_s_n_1, X1_36_s_n_2, X1_36_s_n_3, X1_36_s_n_4
+};
+/* (z^3 - z)*u^4 + (4*z^4 - 4*z^2)*u^3 + (3*z^5 + 5*z^4 - 8*z^3 - 2*z^2 + z - 1)*u^2 + (4*z^5 - 10*z^3 + 4*z^2 - 2*z)*u + (z^5 - z^4 - 4*z^3 + 3*z^2 - z) */
+static const long X1_36_s_d_0[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, -1, 3, -4, -1, 1 }; /* z^5 - z^4 - 4*z^3 + 3*z^2 - z */
+static const long X1_36_s_d_1[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, -2, 4, -10, 0, 4 }; /* 4*z^5 - 10*z^3 + 4*z^2 - 2*z */
+static const long X1_36_s_d_2[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, -1, 1, -2, -8, 5, 3 }; /* 3*z^5 + 5*z^4 - 8*z^3 - 2*z^2 + z - 1 */
+static const long X1_36_s_d_3[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, -4, 0, 4 }; /* 4*z^4 - 4*z^2 */
+static const long X1_36_s_d_4[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, -1, 0, 1 }; /* z^3 - z */
+static const long *X1_36_s_d[7] = {
+  (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_36_s_d_0, X1_36_s_d_1, X1_36_s_d_2, X1_36_s_d_3, X1_36_s_d_4
+};
+/* (z^4 + 4*z^3 + 6*z^2 + 4*z + 1)*x^18 + (4*z^6 + 27*z^5 + 61*z^4 + 53*z^3 + 3*z^2 - 20*z - 8)*x^17 + (6*z^8 + 64*z^7 + 227*z^6 + 318*z^5 + 86*z^4 - 186*z^3 - 123*z^2 + 28*z + 28)*x^16 + (4*z^10 + 70*z^9 + 390*z^8 + 899*z^7 + 697*z^6 - 460*z^5 - 878*z^4 - 71*z^3 + 299*z^2 + 18*z - 56)*x^15 + (z^12 + 36*z^11 + 334*z^10 + 1256*z^9 + 1944*z^8 + 227*z^7 - 2560*z^6 - 1975*z^5 + 530*z^4 + 635*z^3 - 205*z^2 - 65*z + 70)*x^14 + (7*z^13 + 137*z^12 + 885*z^11 + 2414*z^10 + 2085*z^9 - 2931*z^8 - 6 [...]
+static const long X1_37_crv_0[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, 0, 0, 0, 0, 0, 0, 1 }; /* z^7 */
+static const long X1_37_crv_1[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, 0, 0, 0, 6, -12, -7, -1 }; /* -z^9 - 7*z^8 - 12*z^7 + 6*z^6 */
+static const long X1_37_crv_2[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, 0, 0, 15, -72, 30, 77, 26 }; /* 26*z^9 + 77*z^8 + 30*z^7 - 72*z^6 + 15*z^5 */
+static const long X1_37_crv_3[15] = {
+  evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 0, 0, 0, 20, -180, 321, 201, -325, -265, -15, 35, 10 }; /* 10*z^12 + 35*z^11 - 15*z^10 - 265*z^9 - 325*z^8 + 201*z^7 + 321*z^6 - 180*z^5 + 20*z^4 */
+static const long X1_37_crv_4[17] = {
+  evaltyp(t_VECSMALL) | _evallg(17), vZ, 0, 0, 0, 15, -240, 910, -400, -1655, 185, 1350, 555, -180, -210, -60, -5 }; /* -5*z^14 - 60*z^13 - 210*z^12 - 180*z^11 + 555*z^10 + 1350*z^9 + 185*z^8 - 1655*z^7 - 400*z^6 + 910*z^5 - 240*z^4 + 15*z^3 */
+static const long X1_37_crv_5[19] = {
+  evaltyp(t_VECSMALL) | _evallg(19), vZ, 0, 0, 6, -180, 1275, -2249, -2053, 4495, 3656, -2293, -3469, -891, 678, 564, 166, 22, 1 }; /* z^16 + 22*z^15 + 166*z^14 + 564*z^13 + 678*z^12 - 891*z^11 - 3469*z^10 - 2293*z^9 + 3656*z^8 + 4495*z^7 - 2053*z^6 - 2249*z^5 + 1275*z^4 - 180*z^3 + 6*z^2 */
+static const long X1_37_crv_6[20] = {
+  evaltyp(t_VECSMALL) | _evallg(20), vZ, 0, 1, -72, 978, -3726, 1372, 9941, -1905, -13100, -4834, 6155, 6267, 1278, -1079, -807, -243, -39, -3 }; /* -3*z^17 - 39*z^16 - 243*z^15 - 807*z^14 - 1079*z^13 + 1278*z^12 + 6267*z^11 + 6155*z^10 - 4834*z^9 - 13100*z^8 - 1905*z^7 + 9941*z^6 + 1372*z^5 - 3726*z^4 + 978*z^3 - 72*z^2 + z */
+static const long X1_37_crv_7[21] = {
+  evaltyp(t_VECSMALL) | _evallg(21), vZ, 0, -12, 395, -3053, 5741, 7183, -16253, -16256, 12561, 22272, 5183, -9008, -7639, -1585, 789, 595, 180, 32, 3 }; /* 3*z^18 + 32*z^17 + 180*z^16 + 595*z^15 + 789*z^14 - 1585*z^13 - 7639*z^12 - 9008*z^11 + 5183*z^10 + 22272*z^9 + 12561*z^8 - 16256*z^7 - 16253*z^6 + 7183*z^5 + 5741*z^4 - 3053*z^3 + 395*z^2 - 12*z */
+static const long X1_37_crv_8[22] = {
+  evaltyp(t_VECSMALL) | _evallg(22), vZ, 0, 66, -1264, 5725, -2065, -20366, 2999, 34475, 16281, -20839, -25859, -5435, 7317, 5622, 1311, -162, -172, -52, -10, -1 }; /* -z^19 - 10*z^18 - 52*z^17 - 172*z^16 - 162*z^15 + 1311*z^14 + 5622*z^13 + 7317*z^12 - 5435*z^11 - 25859*z^10 - 20839*z^9 + 16281*z^8 + 34475*z^7 + 2999*z^6 - 20366*z^5 - 2065*z^4 + 5725*z^3 - 1264*z^2 + 66*z */
+static const long X1_37_crv_9[21] = {
+  evaltyp(t_VECSMALL) | _evallg(21), vZ, 0, -210, 2525, -5975, -8210, 20440, 25005, -16842, -40593, -14660, 18001, 19581, 4715, -2681, -2023, -501, -52, -5, -1 }; /* -z^18 - 5*z^17 - 52*z^16 - 501*z^15 - 2023*z^14 - 2681*z^13 + 4715*z^12 + 19581*z^11 + 18001*z^10 - 14660*z^9 - 40593*z^8 - 16842*z^7 + 25005*z^6 + 20440*z^5 - 8210*z^4 - 5975*z^3 + 2525*z^2 - 210*z */
+static const long X1_37_crv_10[19] = {
+  evaltyp(t_VECSMALL) | _evallg(19), vZ, 1, 412, -3145, 1991, 14573, -1252, -29776, -20987, 16424, 31592, 12096, -7355, -8129, -2320, 129, 184, 26 }; /* 26*z^16 + 184*z^15 + 129*z^14 - 2320*z^13 - 8129*z^12 - 7355*z^11 + 12096*z^10 + 31592*z^9 + 16424*z^8 - 20987*z^7 - 29776*z^6 - 1252*z^5 + 14573*z^4 + 1991*z^3 - 3145*z^2 + 412*z + 1 */
+static const long X1_37_crv_11[18] = {
+  evaltyp(t_VECSMALL) | _evallg(18), vZ, -8, -494, 2270, 2488, -8675, -13117, 4413, 23552, 16913, -6010, -14529, -6515, 414, 1210, 363, 35 }; /* 35*z^15 + 363*z^14 + 1210*z^13 + 414*z^12 - 6515*z^11 - 14529*z^10 - 6010*z^9 + 16913*z^8 + 23552*z^7 + 4413*z^6 - 13117*z^5 - 8675*z^4 + 2488*z^3 + 2270*z^2 - 494*z - 8 */
+static const long X1_37_crv_12[17] = {
+  evaltyp(t_VECSMALL) | _evallg(17), vZ, 28, 322, -733, -2730, -527, 6962, 10483, 664, -11481, -9749, -870, 2579, 1420, 294, 21 }; /* 21*z^14 + 294*z^13 + 1420*z^12 + 2579*z^11 - 870*z^10 - 9749*z^9 - 11481*z^8 + 664*z^7 + 10483*z^6 + 6962*z^5 - 527*z^4 - 2730*z^3 - 733*z^2 + 322*z + 28 */
+static const long X1_37_crv_13[16] = {
+  evaltyp(t_VECSMALL) | _evallg(16), vZ, -56, -50, 38, 306, 2034, 2372, -2982, -6951, -2931, 2085, 2414, 885, 137, 7 }; /* 7*z^13 + 137*z^12 + 885*z^11 + 2414*z^10 + 2085*z^9 - 2931*z^8 - 6951*z^7 - 2982*z^6 + 2372*z^5 + 2034*z^4 + 306*z^3 + 38*z^2 - 50*z - 56 */
+static const long X1_37_crv_14[15] = {
+  evaltyp(t_VECSMALL) | _evallg(15), vZ, 70, -65, -205, 635, 530, -1975, -2560, 227, 1944, 1256, 334, 36, 1 }; /* z^12 + 36*z^11 + 334*z^10 + 1256*z^9 + 1944*z^8 + 227*z^7 - 2560*z^6 - 1975*z^5 + 530*z^4 + 635*z^3 - 205*z^2 - 65*z + 70 */
+static const long X1_37_crv_15[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, -56, 18, 299, -71, -878, -460, 697, 899, 390, 70, 4 }; /* 4*z^10 + 70*z^9 + 390*z^8 + 899*z^7 + 697*z^6 - 460*z^5 - 878*z^4 - 71*z^3 + 299*z^2 + 18*z - 56 */
+static const long X1_37_crv_16[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, 28, 28, -123, -186, 86, 318, 227, 64, 6 }; /* 6*z^8 + 64*z^7 + 227*z^6 + 318*z^5 + 86*z^4 - 186*z^3 - 123*z^2 + 28*z + 28 */
+static const long X1_37_crv_17[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, -8, -20, 3, 53, 61, 27, 4 }; /* 4*z^6 + 27*z^5 + 61*z^4 + 53*z^3 + 3*z^2 - 20*z - 8 */
+static const long X1_37_crv_18[7] = {
+  evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, 4, 6, 4, 1 }; /* z^4 + 4*z^3 + 6*z^2 + 4*z + 1 */
+static const long *X1_37_crv[21] = {
+  (long *)(evaltyp(t_POL) | _evallg(21)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_37_crv_0, X1_37_crv_1, X1_37_crv_2, X1_37_crv_3, X1_37_crv_4, X1_37_crv_5, X1_37_crv_6, X1_37_crv_7, X1_37_crv_8, X1_37_crv_9, X1_37_crv_10, X1_37_crv_11, X1_37_crv_12, X1_37_crv_13, X1_37_crv_14, X1_37_crv_15, X1_37_crv_16, X1_37_crv_17, X1_37_crv_18
+};
+/* (z^2 + z + 1)*x - 1 */
+static const long X1_37_r_n_1[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, 1, 1, 1 }; /* z^2 + z + 1 */
+static const long *X1_37_r_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_m1, X1_37_r_n_1
+};
+/* x + (z^2 + z - 1) */
+static const long X1_37_r_d_0[5] = {
+  evaltyp(t_VECSMALL) | _evallg(5), vZ, -1, 1, 1 }; /* z^2 + z - 1 */
+static const long *X1_37_r_d[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_37_r_d_0, FLX_1
+};
+/* (z + 1)*x - 1 */
+static const long X1_37_s_n_1[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */
+static const long *X1_37_s_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_m1, X1_37_s_n_1
+};
+/* x + (z - 1) */
+static const long X1_37_s_d_0[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, -1, 1 }; /* z - 1 */
+static const long *X1_37_s_d[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_37_s_d_0, FLX_1
+};
+/* z^3*u^12 + (z^6 + 4*z^4 + 10*z^3 - z^2 + z)*u^11 + (4*z^7 + 10*z^6 + 2*z^5 + 39*z^4 + 41*z^3 - 5*z^2 + 7*z - 1)*u^10 + (z^9 + 4*z^8 + 38*z^7 + 32*z^6 + 26*z^5 + 167*z^4 + 88*z^3 - 10*z^2 + 17*z - 6)*u^9 + (4*z^10 + 3*z^9 + 39*z^8 + 141*z^7 + 28*z^6 + 144*z^5 + 396*z^4 + 94*z^3 - 18*z^2 + 12*z - 15)*u^8 + (6*z^11 + 14*z^10 + 173*z^8 + 234*z^7 - 44*z^6 + 421*z^5 + 545*z^4 - 4*z^3 - 50*z^2 - 17*z - 20)*u^7 + (4*z^12 + 25*z^11 - z^10 + 41*z^9 + 368*z^8 + 91*z^7 - 39*z^6 + 691*z^5 + 383*z^ [...]
+static const long X1_38_crv_0[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, 0, 0, 0, 0, 0, 0, -1 }; /* -z^7 */
+static const long X1_38_crv_1[16] = {
+  evaltyp(t_VECSMALL) | _evallg(16), vZ, 0, 0, 0, 0, 0, -3, -3, -3, 0, 1, 1, 0, 0, 1 }; /* z^13 + z^10 + z^9 - 3*z^7 - 3*z^6 - 3*z^5 */
+static const long X1_38_crv_2[16] = {
+  evaltyp(t_VECSMALL) | _evallg(16), vZ, 0, 0, 0, -3, -15, -25, 6, 6, -9, 10, 12, -3, 4, 4 }; /* 4*z^13 + 4*z^12 - 3*z^11 + 12*z^10 + 10*z^9 - 9*z^8 + 6*z^7 + 6*z^6 - 25*z^5 - 15*z^4 - 3*z^3 */
+static const long X1_38_crv_3[16] = {
+  evaltyp(t_VECSMALL) | _evallg(16), vZ, 0, -1, -5, -39, -90, -17, 107, -10, -34, 78, 27, -10, 17, 6 }; /* 6*z^13 + 17*z^12 - 10*z^11 + 27*z^10 + 78*z^9 - 34*z^8 - 10*z^7 + 107*z^6 - 17*z^5 - 90*z^4 - 39*z^3 - 5*z^2 - z */
+static const long X1_38_crv_4[16] = {
+  evaltyp(t_VECSMALL) | _evallg(16), vZ, -1, -9, -34, -146, -153, 210, 249, -135, 61, 202, -7, 4, 26, 4 }; /* 4*z^13 + 26*z^12 + 4*z^11 - 7*z^10 + 202*z^9 + 61*z^8 - 135*z^7 + 249*z^6 + 210*z^5 - 153*z^4 - 146*z^3 - 34*z^2 - 9*z - 1 */
+static const long X1_38_crv_5[16] = {
+  evaltyp(t_VECSMALL) | _evallg(16), vZ, -6, -28, -82, -236, 24, 594, 166, -163, 326, 171, -33, 30, 17, 1 }; /* z^13 + 17*z^12 + 30*z^11 - 33*z^10 + 171*z^9 + 326*z^8 - 163*z^7 + 166*z^6 + 594*z^5 + 24*z^4 - 236*z^3 - 82*z^2 - 28*z - 6 */
+static const long X1_38_crv_6[15] = {
+  evaltyp(t_VECSMALL) | _evallg(15), vZ, -15, -38, -91, -168, 383, 691, -39, 91, 368, 41, -1, 25, 4 }; /* 4*z^12 + 25*z^11 - z^10 + 41*z^9 + 368*z^8 + 91*z^7 - 39*z^6 + 691*z^5 + 383*z^4 - 168*z^3 - 91*z^2 - 38*z - 15 */
+static const long X1_38_crv_7[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, -20, -17, -50, -4, 545, 421, -44, 234, 173, 0, 14, 6 }; /* 6*z^11 + 14*z^10 + 173*z^8 + 234*z^7 - 44*z^6 + 421*z^5 + 545*z^4 - 4*z^3 - 50*z^2 - 17*z - 20 */
+static const long X1_38_crv_8[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, -15, 12, -18, 94, 396, 144, 28, 141, 39, 3, 4 }; /* 4*z^10 + 3*z^9 + 39*z^8 + 141*z^7 + 28*z^6 + 144*z^5 + 396*z^4 + 94*z^3 - 18*z^2 + 12*z - 15 */
+static const long X1_38_crv_9[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, -6, 17, -10, 88, 167, 26, 32, 38, 4, 1 }; /* z^9 + 4*z^8 + 38*z^7 + 32*z^6 + 26*z^5 + 167*z^4 + 88*z^3 - 10*z^2 + 17*z - 6 */
+static const long X1_38_crv_10[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, -1, 7, -5, 41, 39, 2, 10, 4 }; /* 4*z^7 + 10*z^6 + 2*z^5 + 39*z^4 + 41*z^3 - 5*z^2 + 7*z - 1 */
+static const long X1_38_crv_11[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 1, -1, 10, 4, 0, 1 }; /* z^6 + 4*z^4 + 10*z^3 - z^2 + z */
+static const long X1_38_crv_12[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 0, 1 }; /* z^3 */
+static const long *X1_38_crv[15] = {
+  (long *)(evaltyp(t_POL) | _evallg(15)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_38_crv_0, X1_38_crv_1, X1_38_crv_2, X1_38_crv_3, X1_38_crv_4, X1_38_crv_5, X1_38_crv_6, X1_38_crv_7, X1_38_crv_8, X1_38_crv_9, X1_38_crv_10, X1_38_crv_11, X1_38_crv_12
+};
+/* (z^3 - z^2)*u^10 + (z^5 + 4*z^4 + 2*z^3 - 8*z^2 + 2*z)*u^9 + (6*z^6 + 10*z^5 + 14*z^4 - 13*z^3 - 17*z^2 + 9*z - 1)*u^8 + (15*z^7 + 25*z^6 + 22*z^5 + 10*z^4 - 45*z^3 - 11*z^2 + 13*z - 2)*u^7 + (21*z^8 + 46*z^7 + 21*z^6 + 33*z^5 - 20*z^4 - 63*z^3 + 5*z^2 + 12*z - 1)*u^6 + (17*z^9 + 58*z^8 + 14*z^7 + 25*z^6 + 39*z^5 - 67*z^4 - 42*z^3 + 21*z^2 + 10*z)*u^5 + (7*z^10 + 45*z^9 + 24*z^8 - 27*z^7 + 75*z^6 - 9*z^5 - 71*z^4 + 23*z^2 + 4*z)*u^4 + (z^11 + 17*z^10 + 30*z^9 - 32*z^8 + 9*z^7 + 68*z^6 [...]
+static const long X1_38_r_n_0[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, 0, 0, 0, -2, 1, 1, -1 }; /* -z^9 + z^8 + z^7 - 2*z^6 */
+static const long X1_38_r_n_1[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 0, 2, -9, -6, 13, -1, -6, 2, 1 }; /* z^11 + 2*z^10 - 6*z^9 - z^8 + 13*z^7 - 6*z^6 - 9*z^5 + 2*z^4 */
+static const long X1_38_r_n_2[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 6, -1, -38, 16, 33, -24, -2, 12, 2 }; /* 2*z^11 + 12*z^10 - 2*z^9 - 24*z^8 + 33*z^7 + 16*z^6 - 38*z^5 - z^4 + 6*z^3 */
+static const long X1_38_r_n_3[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 8, 17, -32, -49, 68, 9, -32, 30, 17, 1 }; /* z^11 + 17*z^10 + 30*z^9 - 32*z^8 + 9*z^7 + 68*z^6 - 49*z^5 - 32*z^4 + 17*z^3 + 8*z^2 */
+static const long X1_38_r_n_4[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 4, 23, 0, -71, -9, 75, -27, 24, 45, 7 }; /* 7*z^10 + 45*z^9 + 24*z^8 - 27*z^7 + 75*z^6 - 9*z^5 - 71*z^4 + 23*z^2 + 4*z */
+static const long X1_38_r_n_5[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 10, 21, -42, -67, 39, 25, 14, 58, 17 }; /* 17*z^9 + 58*z^8 + 14*z^7 + 25*z^6 + 39*z^5 - 67*z^4 - 42*z^3 + 21*z^2 + 10*z */
+static const long X1_38_r_n_6[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, -1, 12, 5, -63, -20, 33, 21, 46, 21 }; /* 21*z^8 + 46*z^7 + 21*z^6 + 33*z^5 - 20*z^4 - 63*z^3 + 5*z^2 + 12*z - 1 */
+static const long X1_38_r_n_7[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, -2, 13, -11, -45, 10, 22, 25, 15 }; /* 15*z^7 + 25*z^6 + 22*z^5 + 10*z^4 - 45*z^3 - 11*z^2 + 13*z - 2 */
+static const long X1_38_r_n_8[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, -1, 9, -17, -13, 14, 10, 6 }; /* 6*z^6 + 10*z^5 + 14*z^4 - 13*z^3 - 17*z^2 + 9*z - 1 */
+static const long X1_38_r_n_9[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 2, -8, 2, 4, 1 }; /* z^5 + 4*z^4 + 2*z^3 - 8*z^2 + 2*z */
+static const long X1_38_r_n_10[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, -1, 1 }; /* z^3 - z^2 */
+static const long *X1_38_r_n[13] = {
+  (long *)(evaltyp(t_POL) | _evallg(13)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_38_r_n_0, X1_38_r_n_1, X1_38_r_n_2, X1_38_r_n_3, X1_38_r_n_4, X1_38_r_n_5, X1_38_r_n_6, X1_38_r_n_7, X1_38_r_n_8, X1_38_r_n_9, X1_38_r_n_10
+};
+/* (z^3 - z^2)*u^10 + (z^5 + 5*z^4 + z^3 - 8*z^2 + 2*z)*u^9 + (7*z^6 + 12*z^5 + 17*z^4 - 20*z^3 - 15*z^2 + 9*z - 1)*u^8 + (19*z^7 + 28*z^6 + 30*z^5 + 10*z^4 - 61*z^3 - 3*z^2 + 13*z - 2)*u^7 + (26*z^8 + 58*z^7 + 19*z^6 + 54*z^5 - 32*z^4 - 82*z^3 + 20*z^2 + 12*z - 1)*u^6 + (19*z^9 + 74*z^8 + 21*z^7 + 16*z^6 + 75*z^5 - 93*z^4 - 53*z^3 + 36*z^2 + 10*z)*u^5 + (7*z^10 + 51*z^9 + 43*z^8 - 41*z^7 + 72*z^6 + 35*z^5 - 106*z^4 - 2*z^3 + 31*z^2 + 4*z)*u^4 + (z^11 + 17*z^10 + 37*z^9 - 26*z^8 - 14*z^7 [...]
+static const long X1_38_r_d_0[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, 0, 0, 0, -2, 1, 1, -1 }; /* -z^9 + z^8 + z^7 - 2*z^6 */
+static const long X1_38_r_d_1[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 0, 2, -11, -5, 14, -2, -6, 2, 1 }; /* z^11 + 2*z^10 - 6*z^9 - 2*z^8 + 14*z^7 - 5*z^6 - 11*z^5 + 2*z^4 */
+static const long X1_38_r_d_2[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 8, -10, -41, 27, 31, -29, 1, 12, 2 }; /* 2*z^11 + 12*z^10 + z^9 - 29*z^8 + 31*z^7 + 27*z^6 - 41*z^5 - 10*z^4 + 8*z^3 */
+static const long X1_38_r_d_3[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 10, 19, -59, -33, 90, -14, -26, 37, 17, 1 }; /* z^11 + 17*z^10 + 37*z^9 - 26*z^8 - 14*z^7 + 90*z^6 - 33*z^5 - 59*z^4 + 19*z^3 + 10*z^2 */
+static const long X1_38_r_d_4[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 4, 31, -2, -106, 35, 72, -41, 43, 51, 7 }; /* 7*z^10 + 51*z^9 + 43*z^8 - 41*z^7 + 72*z^6 + 35*z^5 - 106*z^4 - 2*z^3 + 31*z^2 + 4*z */
+static const long X1_38_r_d_5[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 10, 36, -53, -93, 75, 16, 21, 74, 19 }; /* 19*z^9 + 74*z^8 + 21*z^7 + 16*z^6 + 75*z^5 - 93*z^4 - 53*z^3 + 36*z^2 + 10*z */
+static const long X1_38_r_d_6[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, -1, 12, 20, -82, -32, 54, 19, 58, 26 }; /* 26*z^8 + 58*z^7 + 19*z^6 + 54*z^5 - 32*z^4 - 82*z^3 + 20*z^2 + 12*z - 1 */
+static const long X1_38_r_d_7[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, -2, 13, -3, -61, 10, 30, 28, 19 }; /* 19*z^7 + 28*z^6 + 30*z^5 + 10*z^4 - 61*z^3 - 3*z^2 + 13*z - 2 */
+static const long X1_38_r_d_8[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, -1, 9, -15, -20, 17, 12, 7 }; /* 7*z^6 + 12*z^5 + 17*z^4 - 20*z^3 - 15*z^2 + 9*z - 1 */
+static const long X1_38_r_d_9[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 2, -8, 1, 5, 1 }; /* z^5 + 5*z^4 + z^3 - 8*z^2 + 2*z */
+static const long X1_38_r_d_10[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, -1, 1 }; /* z^3 - z^2 */
+static const long *X1_38_r_d[13] = {
+  (long *)(evaltyp(t_POL) | _evallg(13)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_38_r_d_0, X1_38_r_d_1, X1_38_r_d_2, X1_38_r_d_3, X1_38_r_d_4, X1_38_r_d_5, X1_38_r_d_6, X1_38_r_d_7, X1_38_r_d_8, X1_38_r_d_9, X1_38_r_d_10
+};
+/* (z^3 - z^2)*u^9 + (z^5 + 3*z^4 + 3*z^3 - 8*z^2 + 2*z)*u^8 + (5*z^6 + 7*z^5 + 12*z^4 - 6*z^3 - 19*z^2 + 9*z - 1)*u^7 + (10*z^7 + 20*z^6 + 11*z^5 + 17*z^4 - 31*z^3 - 19*z^2 + 13*z - 2)*u^6 + (12*z^8 + 31*z^7 + 15*z^6 + 12*z^5 + 8*z^4 - 52*z^3 - 10*z^2 + 12*z - 1)*u^5 + (10*z^9 + 30*z^8 + 9*z^7 + 13*z^6 + 15*z^5 - 22*z^4 - 46*z^3 + 6*z^2 + 10*z)*u^4 + (5*z^10 + 23*z^9 - 2*z^8 - 4*z^7 + 42*z^6 - 27*z^5 - 25*z^4 - 13*z^3 + 15*z^2 + 4*z)*u^3 + (z^11 + 11*z^10 + 4*z^9 - 24*z^8 + 35*z^7 + 2*z [...]
+static const long X1_38_s_n_0[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 0, 0, 2, -4, 1, 2, -1, -1, 1 }; /* z^11 - z^10 - z^9 + 2*z^8 + z^7 - 4*z^6 + 2*z^5 */
+static const long X1_38_s_n_1[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 2, 6, -8, -11, 13, 4, -11, 5, 2 }; /* 2*z^11 + 5*z^10 - 11*z^9 + 4*z^8 + 13*z^7 - 11*z^6 - 8*z^5 + 6*z^4 + 2*z^3 */
+static const long X1_38_s_n_2[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 6, 7, -3, -30, 2, 35, -24, 4, 11, 1 }; /* z^11 + 11*z^10 + 4*z^9 - 24*z^8 + 35*z^7 + 2*z^6 - 30*z^5 - 3*z^4 + 7*z^3 + 6*z^2 */
+static const long X1_38_s_n_3[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 4, 15, -13, -25, -27, 42, -4, -2, 23, 5 }; /* 5*z^10 + 23*z^9 - 2*z^8 - 4*z^7 + 42*z^6 - 27*z^5 - 25*z^4 - 13*z^3 + 15*z^2 + 4*z */
+static const long X1_38_s_n_4[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 10, 6, -46, -22, 15, 13, 9, 30, 10 }; /* 10*z^9 + 30*z^8 + 9*z^7 + 13*z^6 + 15*z^5 - 22*z^4 - 46*z^3 + 6*z^2 + 10*z */
+static const long X1_38_s_n_5[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, -1, 12, -10, -52, 8, 12, 15, 31, 12 }; /* 12*z^8 + 31*z^7 + 15*z^6 + 12*z^5 + 8*z^4 - 52*z^3 - 10*z^2 + 12*z - 1 */
+static const long X1_38_s_n_6[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, -2, 13, -19, -31, 17, 11, 20, 10 }; /* 10*z^7 + 20*z^6 + 11*z^5 + 17*z^4 - 31*z^3 - 19*z^2 + 13*z - 2 */
+static const long X1_38_s_n_7[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, -1, 9, -19, -6, 12, 7, 5 }; /* 5*z^6 + 7*z^5 + 12*z^4 - 6*z^3 - 19*z^2 + 9*z - 1 */
+static const long X1_38_s_n_8[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 2, -8, 3, 3, 1 }; /* z^5 + 3*z^4 + 3*z^3 - 8*z^2 + 2*z */
+static const long X1_38_s_n_9[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, -1, 1 }; /* z^3 - z^2 */
+static const long *X1_38_s_n[12] = {
+  (long *)(evaltyp(t_POL) | _evallg(12)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_38_s_n_0, X1_38_s_n_1, X1_38_s_n_2, X1_38_s_n_3, X1_38_s_n_4, X1_38_s_n_5, X1_38_s_n_6, X1_38_s_n_7, X1_38_s_n_8, X1_38_s_n_9
+};
+/* (z^3 - z^2)*u^9 + (z^5 + 4*z^4 + 2*z^3 - 8*z^2 + 2*z)*u^8 + (6*z^6 + 9*z^5 + 15*z^4 - 13*z^3 - 17*z^2 + 9*z - 1)*u^7 + (14*z^7 + 23*z^6 + 19*z^5 + 17*z^4 - 47*z^3 - 11*z^2 + 13*z - 2)*u^6 + (17*z^8 + 43*z^7 + 13*z^6 + 33*z^5 - 4*z^4 - 71*z^3 + 5*z^2 + 12*z - 1)*u^5 + (12*z^9 + 46*z^8 + 16*z^7 + 4*z^6 + 51*z^5 - 48*z^4 - 57*z^3 + 21*z^2 + 10*z)*u^4 + (5*z^10 + 29*z^9 + 17*z^8 - 18*z^7 + 39*z^6 + 17*z^5 - 60*z^4 - 15*z^3 + 23*z^2 + 4*z)*u^3 + (z^11 + 11*z^10 + 11*z^9 - 18*z^8 + 12*z^7 + [...]
+static const long X1_38_s_d_0[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 0, 0, 0, -3, 2, 1, -1, -1, 1 }; /* z^11 - z^10 - z^9 + z^8 + 2*z^7 - 3*z^6 */
+static const long X1_38_s_d_1[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 4, -3, -11, 0, 11, -1, -8, 5, 2 }; /* 2*z^11 + 5*z^10 - 8*z^9 - z^8 + 11*z^7 - 11*z^5 - 3*z^4 + 4*z^3 */
+static const long X1_38_s_d_2[14] = {
+  evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 8, 9, -30, -14, 24, 12, -18, 11, 11, 1 }; /* z^11 + 11*z^10 + 11*z^9 - 18*z^8 + 12*z^7 + 24*z^6 - 14*z^5 - 30*z^4 + 9*z^3 + 8*z^2 */
+static const long X1_38_s_d_3[13] = {
+  evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 4, 23, -15, -60, 17, 39, -18, 17, 29, 5 }; /* 5*z^10 + 29*z^9 + 17*z^8 - 18*z^7 + 39*z^6 + 17*z^5 - 60*z^4 - 15*z^3 + 23*z^2 + 4*z */
+static const long X1_38_s_d_4[12] = {
+  evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 10, 21, -57, -48, 51, 4, 16, 46, 12 }; /* 12*z^9 + 46*z^8 + 16*z^7 + 4*z^6 + 51*z^5 - 48*z^4 - 57*z^3 + 21*z^2 + 10*z */
+static const long X1_38_s_d_5[11] = {
+  evaltyp(t_VECSMALL) | _evallg(11), vZ, -1, 12, 5, -71, -4, 33, 13, 43, 17 }; /* 17*z^8 + 43*z^7 + 13*z^6 + 33*z^5 - 4*z^4 - 71*z^3 + 5*z^2 + 12*z - 1 */
+static const long X1_38_s_d_6[10] = {
+  evaltyp(t_VECSMALL) | _evallg(10), vZ, -2, 13, -11, -47, 17, 19, 23, 14 }; /* 14*z^7 + 23*z^6 + 19*z^5 + 17*z^4 - 47*z^3 - 11*z^2 + 13*z - 2 */
+static const long X1_38_s_d_7[9] = {
+  evaltyp(t_VECSMALL) | _evallg(9), vZ, -1, 9, -17, -13, 15, 9, 6 }; /* 6*z^6 + 9*z^5 + 15*z^4 - 13*z^3 - 17*z^2 + 9*z - 1 */
+static const long X1_38_s_d_8[8] = {
+  evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 2, -8, 2, 4, 1 }; /* z^5 + 4*z^4 + 2*z^3 - 8*z^2 + 2*z */
+static const long X1_38_s_d_9[6] = {
+  evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, -1, 1 }; /* z^3 - z^2 */
+static const long *X1_38_s_d[12] = {
+  (long *)(evaltyp(t_POL) | _evallg(12)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_38_s_d_0, X1_38_s_d_1, X1_38_s_d_2, X1_38_s_d_3, X1_38_s_d_4, X1_38_s_d_5, X1_38_s_d_6, X1_38_s_d_7, X1_38_s_d_8, X1_38_s_d_9
+};
+/* z^12*x^14 + (-z^23 - 2*z^22 - 4*z^21 - 6*z^20 - 9*z^19 - 12*z^18 - 16*z^17 - 20*z^16 - 25*z^15 - 30*z^14 - 36*z^13 - 12*z^12)*x^13 + (-18*z^23 - 52*z^22 - 100*z^21 - 147*z^20 - 187*z^19 - 208*z^18 - 216*z^17 - 218*z^16 - 248*z^15 - 348*z^14 - 596*z^13 - 650*z^12 - 483*z^11 - 308*z^10 - 188*z^9 - 108*z^8 - 58*z^7 - 28*z^6 - 12*z^5 - 4*z^4 - z^3)*x^12 + (-153*z^23 - 594*z^22 - 1300*z^21 - 2055*z^20 - 2574*z^19 - 2556*z^18 - 1806*z^17 - 261*z^16 + 1845*z^15 + 3786*z^14 + 3780*z^13 + 2178 [...]
+static const long X1_39_crv_0[31] = {
+  evaltyp(t_VECSMALL) | _evallg(31), vZ, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 16, 120, 560, 1820, 4368, 8008, 11440, 12870, 11440, 8008, 4368, 1820, 560, 120, 16, 1 }; /* z^28 + 16*z^27 + 120*z^26 + 560*z^25 + 1820*z^24 + 4368*z^23 + 8008*z^22 + 11440*z^21 + 12870*z^20 + 11440*z^19 + 8008*z^18 + 4368*z^17 + 1820*z^16 + 560*z^15 + 120*z^14 + 16*z^13 + z^12 */
+static const long X1_39_crv_1[31] = {
+  evaltyp(t_VECSMALL) | _evallg(31), vZ, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -12, -156, -930, -3335, -7885, -12470, -12024, -2916, 11580, 22600, 23900, 17206, 8834, 3220, 800, 123, 9 }; /* 9*z^28 + 123*z^27 + 800*z^26 + 3220*z^25 + 8834*z^24 + 17206*z^23 + 23900*z^22 + 22600*z^21 + 11580*z^20 - 2916*z^19 - 12024*z^18 - 12470*z^17 - 7885*z^16 - 3335*z^15 - 930*z^14 - 156*z^13 - 12*z^12 */
+static const long X1_39_crv_2[31] = {
+  evaltyp(t_VECSMALL) | _evallg(31), vZ, 0, 0, 0, 1, 21, 216, 1444, 7032, 26520, 80432, 201168, 422268, 753402, 1153404, 1525872, 1752384, 1749258, 1513356, 1128252, 723204, 405039, 209364, 108084, 56208, 26488, 9912, 2640, 443, 36 }; /* 36*z^28 + 443*z^27 + 2640*z^26 + 9912*z^25 + 26488*z^24 + 56208*z^23 + 108084*z^22 + 209364*z^21 + 405039*z^20 + 723204*z^19 + 1128252*z^18 + 1513356*z^17 + 1749258*z^16 + 1752384*z^15 + 1525872*z^14 + 1153404*z^13 + 753402*z^12 + 422268*z^11 + 201168*z^ [...]
+static const long X1_39_crv_3[31] = {
+  evaltyp(t_VECSMALL) | _evallg(31), vZ, 0, 0, 0, -3, -54, -456, -2360, -8090, -17649, -14782, 58652, 320100, 913956, 1907052, 3166854, 4342211, 5012510, 4919796, 4115740, 2925262, 1758603, 897424, 398596, 161856, 61860, 21000, 5544, 966, 84 }; /* 84*z^28 + 966*z^27 + 5544*z^26 + 21000*z^25 + 61860*z^24 + 161856*z^23 + 398596*z^22 + 897424*z^21 + 1758603*z^20 + 2925262*z^19 + 4115740*z^18 + 4919796*z^17 + 5012510*z^16 + 4342211*z^15 + 3166854*z^14 + 1907052*z^13 + 913956*z^12 + 320100*z^ [...]
+static const long X1_39_crv_4[31] = {
+  evaltyp(t_VECSMALL) | _evallg(31), vZ, 0, 0, 0, 6, 90, 600, 2216, 4030, -2842, -41460, -134160, -244602, -204565, 270580, 1391660, 3031220, 4657354, 5608136, 5505000, 4469310, 3004995, 1667408, 765412, 297098, 101730, 31200, 7896, 1386, 126 }; /* 126*z^28 + 1386*z^27 + 7896*z^26 + 31200*z^25 + 101730*z^24 + 297098*z^23 + 765412*z^22 + 1667408*z^21 + 3004995*z^20 + 4469310*z^19 + 5505000*z^18 + 5608136*z^17 + 4657354*z^16 + 3031220*z^15 + 1391660*z^14 + 270580*z^13 - 204565*z^12 - 24460 [...]
+static const long X1_39_crv_5[31] = {
+  evaltyp(t_VECSMALL) | _evallg(31), vZ, 0, 0, 0, -10, -120, -600, -1366, 333, 11565, 34350, 39780, -44343, -271552, -540912, -540060, 55910, 1236231, 2539962, 3353964, 3341835, 2628990, 1650292, 826386, 332211, 110495, 31770, 7704, 1344, 126 }; /* 126*z^28 + 1344*z^27 + 7704*z^26 + 31770*z^25 + 110495*z^24 + 332211*z^23 + 826386*z^22 + 1650292*z^21 + 2628990*z^20 + 3341835*z^19 + 3353964*z^18 + 2539962*z^17 + 1236231*z^16 + 55910*z^15 - 540060*z^14 - 540912*z^13 - 271552*z^12 - 44343*z^ [...]
+static const long X1_39_crv_6[31] = {
+  evaltyp(t_VECSMALL) | _evallg(31), vZ, 0, 0, 0, 15, 135, 480, 496, -1916, -7416, -6456, 20760, 72513, 79677, -68172, -375720, -626120, -521846, 6228, 693252, 1162575, 1213200, 922068, 528492, 230394, 77944, 21640, 5076, 876, 84 }; /* 84*z^28 + 876*z^27 + 5076*z^26 + 21640*z^25 + 77944*z^24 + 230394*z^23 + 528492*z^22 + 922068*z^21 + 1213200*z^20 + 1162575*z^19 + 693252*z^18 + 6228*z^17 - 521846*z^16 - 626120*z^15 - 375720*z^14 - 68172*z^13 + 79677*z^12 + 72513*z^11 + 20760*z^10 - 6456* [...]
+static const long X1_39_crv_7[31] = {
+  evaltyp(t_VECSMALL) | _evallg(31), vZ, -1, -14, -112, -637, -2744, -9268, -25634, -61105, -129905, -245998, -404852, -565402, -669214, -706388, -743626, -829121, -883369, -768278, -461620, -94892, 166136, 245336, 188602, 96449, 34678, 9452, 2164, 369, 36 }; /* 36*z^28 + 369*z^27 + 2164*z^26 + 9452*z^25 + 34678*z^24 + 96449*z^23 + 188602*z^22 + 245336*z^21 + 166136*z^20 - 94892*z^19 - 461620*z^18 - 768278*z^17 - 883369*z^16 - 829121*z^15 - 743626*z^14 - 706388*z^13 - 669214*z^12 - 56540 [...]
+static const long X1_39_crv_8[31] = {
+  evaltyp(t_VECSMALL) | _evallg(31), vZ, 0, 0, 0, -15, -240, -1740, -7784, -25122, -65124, -144524, -280656, -474318, -686088, -842244, -893172, -859748, -787386, -678672, -516680, -320022, -140013, -23112, 21288, 20526, 8890, 2400, 540, 91, 9 }; /* 9*z^28 + 91*z^27 + 540*z^26 + 2400*z^25 + 8890*z^24 + 20526*z^23 + 21288*z^22 - 23112*z^21 - 140013*z^20 - 320022*z^19 - 516680*z^18 - 678672*z^17 - 787386*z^16 - 859748*z^15 - 893172*z^14 - 842244*z^13 - 686088*z^12 - 474318*z^11 - 280656*z^ [...]
+static const long X1_39_crv_9[31] = {
+  evaltyp(t_VECSMALL) | _evallg(31), vZ, 0, 0, 0, 10, 130, 720, 2314, 5035, 7806, 6900, -5820, -43146, -114251, -207128, -284760, -316700, -306131, -269898, -216012, -151485, -87840, -38140, -9736, 192, 1005, 270, 60, 10, 1 }; /* z^28 + 10*z^27 + 60*z^26 + 270*z^25 + 1005*z^24 + 192*z^23 - 9736*z^22 - 38140*z^21 - 87840*z^20 - 151485*z^19 - 216012*z^18 - 269898*z^17 - 306131*z^16 - 316700*z^15 - 284760*z^14 - 207128*z^13 - 114251*z^12 - 43146*z^11 - 5820*z^10 + 6900*z^9 + 7806*z^8 + 5035 [...]
+static const long X1_39_crv_10[26] = {
+  evaltyp(t_VECSMALL) | _evallg(26), vZ, 0, 0, 0, -6, -60, -240, -544, -818, -616, 720, 3780, 7806, 8717, 268, -17560, -34940, -43894, -44924, -39972, -31080, -20535, -10860, -4080, -816 }; /* -816*z^23 - 4080*z^22 - 10860*z^21 - 20535*z^20 - 31080*z^19 - 39972*z^18 - 44924*z^17 - 43894*z^16 - 34940*z^15 - 17560*z^14 + 268*z^13 + 8717*z^12 + 7806*z^11 + 3780*z^10 + 720*z^9 - 616*z^8 - 818*z^7 - 544*z^6 - 240*z^5 - 60*z^4 - 6*z^3 */
+static const long X1_39_crv_11[26] = {
+  evaltyp(t_VECSMALL) | _evallg(26), vZ, 0, 0, 0, 3, 21, 60, 124, 192, 243, 266, 360, 849, 2178, 3780, 3786, 1845, -261, -1806, -2556, -2574, -2055, -1300, -594, -153 }; /* -153*z^23 - 594*z^22 - 1300*z^21 - 2055*z^20 - 2574*z^19 - 2556*z^18 - 1806*z^17 - 261*z^16 + 1845*z^15 + 3786*z^14 + 3780*z^13 + 2178*z^12 + 849*z^11 + 360*z^10 + 266*z^9 + 243*z^8 + 192*z^7 + 124*z^6 + 60*z^5 + 21*z^4 + 3*z^3 */
+static const long X1_39_crv_12[26] = {
+  evaltyp(t_VECSMALL) | _evallg(26), vZ, 0, 0, 0, -1, -4, -12, -28, -58, -108, -188, -308, -483, -650, -596, -348, -248, -218, -216, -208, -187, -147, -100, -52, -18 }; /* -18*z^23 - 52*z^22 - 100*z^21 - 147*z^20 - 187*z^19 - 208*z^18 - 216*z^17 - 218*z^16 - 248*z^15 - 348*z^14 - 596*z^13 - 650*z^12 - 483*z^11 - 308*z^10 - 188*z^9 - 108*z^8 - 58*z^7 - 28*z^6 - 12*z^5 - 4*z^4 - z^3 */
+static const long X1_39_crv_13[26] = {
+  evaltyp(t_VECSMALL) | _evallg(26), vZ, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -12, -36, -30, -25, -20, -16, -12, -9, -6, -4, -2, -1 }; /* -z^23 - 2*z^22 - 4*z^21 - 6*z^20 - 9*z^19 - 12*z^18 - 16*z^17 - 20*z^16 - 25*z^15 - 30*z^14 - 36*z^13 - 12*z^12 */
+static const long X1_39_crv_14[15] = {
+  evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; /* z^12 */
+static const long *X1_39_crv[17] = {
+  (long *)(evaltyp(t_POL) | _evallg(17)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_39_crv_0, X1_39_crv_1, X1_39_crv_2, X1_39_crv_3, X1_39_crv_4, X1_39_crv_5, X1_39_crv_6, X1_39_crv_7, X1_39_crv_8, X1_39_crv_9, X1_39_crv_10, X1_39_crv_11, X1_39_crv_12, X1_39_crv_13, X1_39_crv_14
+};
+/* -z */
+static const long *X1_39_r_n[3] = {
+  (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_mZ
+};
+/* 1 */
+static const long *X1_39_r_d[3] = {
+  (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_1
+};
+/* (z + 1)*x + (z + 1) */
+static const long X1_39_s_n_0[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */
+static const long X1_39_s_n_1[4] = {
+  evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */
+static const long *X1_39_s_n[4] = {
+  (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)),
+  X1_39_s_n_0, X1_39_s_n_1
+};
+/* z */
+static const long *X1_39_s_d[3] = {
+  (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)),
+  FLX_Z
+};
+
+
+static const X1_info X1_table[LAST_X1_LEVEL - FIRST_X1_LEVEL + 1] = {
+  { (GEN)X1_13_crv, (GEN)X1_13_r_n, (GEN)X1_13_r_d, 0, (GEN)X1_13_s_n, (GEN)X1_13_s_d, 1, RS_MAP },
+  { (GEN)X1_14_crv, (GEN)X1_14_r_n, (GEN)X1_14_r_d, 1, (GEN)X1_14_s_n, (GEN)X1_14_s_d, 0, RS_MAP },
+  { (GEN)X1_15_crv, (GEN)X1_15_r_n, (GEN)X1_15_r_d, 1, (GEN)X1_15_s_n, (GEN)X1_15_s_d, 1, RS_MAP },
+  { (GEN)X1_16_crv, (GEN)X1_16_r_n, (GEN)X1_16_r_d, 0, (GEN)X1_16_s_n, (GEN)X1_16_s_d, 0, RS_MAP },
+  { (GEN)X1_17_crv, (GEN)X1_17_r_n, (GEN)X1_17_r_d, 0, (GEN)X1_17_s_n, (GEN)X1_17_s_d, 0, RS_MAP },
+  { (GEN)X1_18_crv, (GEN)X1_18_r_n, (GEN)X1_18_r_d, 0, (GEN)X1_18_s_n, (GEN)X1_18_s_d, 0, RS_MAP },
+  { (GEN)X1_19_crv, (GEN)X1_19_r_n, (GEN)X1_19_r_d, 1, (GEN)X1_19_s_n, (GEN)X1_19_s_d, 1, RS_MAP },
+  { (GEN)X1_20_crv, (GEN)X1_20_r_n, (GEN)X1_20_r_d, 0, (GEN)X1_20_s_n, (GEN)X1_20_s_d, 0, TQ_MAP },
+  { (GEN)X1_21_crv, (GEN)X1_21_r_n, (GEN)X1_21_r_d, 1, (GEN)X1_21_s_n, (GEN)X1_21_s_d, 1, RS_MAP },
+  { (GEN)X1_22_crv, (GEN)X1_22_r_n, (GEN)X1_22_r_d, 0, (GEN)X1_22_s_n, (GEN)X1_22_s_d, 0, RS_MAP },
+  { (GEN)X1_23_crv, (GEN)X1_23_r_n, (GEN)X1_23_r_d, 0, (GEN)X1_23_s_n, (GEN)X1_23_s_d, 0, RS_MAP },
+  { (GEN)X1_24_crv, (GEN)X1_24_r_n, (GEN)X1_24_r_d, 0, (GEN)X1_24_s_n, (GEN)X1_24_s_d, 0, TQ_MAP },
+  { (GEN)X1_25_crv, (GEN)X1_25_r_n, (GEN)X1_25_r_d, 0, (GEN)X1_25_s_n, (GEN)X1_25_s_d, 0, RS_MAP },
+  { (GEN)X1_26_crv, (GEN)X1_26_r_n, (GEN)X1_26_r_d, 0, (GEN)X1_26_s_n, (GEN)X1_26_s_d, 0, RS_MAP },
+  { (GEN)X1_27_crv, (GEN)X1_27_r_n, (GEN)X1_27_r_d, 0, (GEN)X1_27_s_n, (GEN)X1_27_s_d, 0, RS_MAP },
+  { (GEN)X1_28_crv, (GEN)X1_28_r_n, (GEN)X1_28_r_d, 0, (GEN)X1_28_s_n, (GEN)X1_28_s_d, 0, QT_MAP },
+  { (GEN)X1_29_crv, (GEN)X1_29_r_n, (GEN)X1_29_r_d, 0, (GEN)X1_29_s_n, (GEN)X1_29_s_d, 1, RS_MAP },
+  { (GEN)X1_30_crv, (GEN)X1_30_r_n, (GEN)X1_30_r_d, 0, (GEN)X1_30_s_n, (GEN)X1_30_s_d, 0, TQ_MAP },
+  { (GEN)X1_31_crv, (GEN)X1_31_r_n, (GEN)X1_31_r_d, 0, (GEN)X1_31_s_n, (GEN)X1_31_s_d, 0, RS_MAP },
+  { (GEN)X1_32_crv, (GEN)X1_32_r_n, (GEN)X1_32_r_d, 0, (GEN)X1_32_s_n, (GEN)X1_32_s_d, 0, QT_MAP },
+  { (GEN)X1_33_crv, (GEN)X1_33_r_n, (GEN)X1_33_r_d, 0, (GEN)X1_33_s_n, (GEN)X1_33_s_d, 0, T_MAP},
+  { (GEN)X1_34_crv, (GEN)X1_34_r_n, (GEN)X1_34_r_d, 0, (GEN)X1_34_s_n, (GEN)X1_34_s_d, 0, RS_MAP },
+  { (GEN)X1_35_crv, (GEN)X1_35_r_n, (GEN)X1_35_r_d, 0, (GEN)X1_35_s_n, (GEN)X1_35_s_d, 0, RS_MAP },
+  { (GEN)X1_36_crv, (GEN)X1_36_r_n, (GEN)X1_36_r_d, 0, (GEN)X1_36_s_n, (GEN)X1_36_s_d, 0, RS_MAP },
+  { (GEN)X1_37_crv, (GEN)X1_37_r_n, (GEN)X1_37_r_d, 0, (GEN)X1_37_s_n, (GEN)X1_37_s_d, 0, RS_MAP },
+  { (GEN)X1_38_crv, (GEN)X1_38_r_n, (GEN)X1_38_r_d, 0, (GEN)X1_38_s_n, (GEN)X1_38_s_d, 0, RS_MAP },
+  { (GEN)X1_39_crv, (GEN)X1_39_r_n, (GEN)X1_39_r_d, 0, (GEN)X1_39_s_n, (GEN)X1_39_s_d, 0, T_MAP }
+};
+
+INLINE const X1_info *
+get_X1_info(ulong N)
+{
+  return &X1_table[N - FIRST_X1_LEVEL];
+}
diff --git a/src/basemath/ellanal.c b/src/basemath/ellanal.c
index e9f0860..95331a4 100644
--- a/src/basemath/ellanal.c
+++ b/src/basemath/ellanal.c
@@ -19,6 +19,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 #include "pari.h"
 #include "paripriv.h"
 
+struct baby_giant
+{
+  GEN baby, giant, sum;
+  GEN bnd, rbnd;
+};
+
 /* Generic Buhler-Gross algorithm */
 
 struct bg_data
@@ -31,22 +37,23 @@ struct bg_data
   GEN p;  /* t_VECSMALL: primes <= rootbnd */
 };
 
-typedef void bg_fun(void*el, GEN *psum, GEN n, GEN a, long jmax);
+typedef void bg_fun(void*el, GEN n, GEN a);
 
 /* a = a_n, where p = bg->pp[i] divides n, and lasta = a_{n/p}.
- * Call fun(E, psum, N, a_N, 0), for all N, n | N, P^+(N) <= p, a_N != 0,
- * i.e. assumes that fun accumulates psum += a_N * w(N) */
+ * Call fun(E, N, a_N), for all N, n | N, P^+(N) <= p, a_N != 0,
+ * i.e. assumes that fun accumulates a_N * w(N) */
+
 static void
-gen_BG_add(void *E, bg_fun *fun, struct bg_data *bg, GEN *psum, GEN n, long i, GEN a, GEN lasta)
+gen_BG_add(void *E, bg_fun *fun, struct bg_data *bg, GEN n, long i, GEN a, GEN lasta)
 {
-  pari_sp av = avma, lim = stack_lim(av,2);
+  pari_sp av = avma;
   long j;
   ulong nn = itou_or_0(n);
   if (nn && nn <= bg->rootbnd) bg->an[nn] = itos(a);
 
   if (signe(a))
   {
-    fun(E, psum, n, a, 0);
+    fun(E, n, a);
     j = 1;
   }
   else
@@ -58,12 +65,8 @@ gen_BG_add(void *E, bg_fun *fun, struct bg_data *bg, GEN *psum, GEN n, long i, G
     if (cmpii(pn, bg->bnd) > 0) return;
     nexta = mulis(a, bg->ap[j]);
     if (i == j && umodiu(bg->N, p)) nexta = subii(nexta, mului(p, lasta));
-    gen_BG_add(E, fun, bg, psum, pn, j, nexta, a);
-    if (low_stack(lim, stack_lim(av,2)))
-    {
-      if (DEBUGMEM>1) pari_warn(warnmem,"gen_BG_add, p=%lu",p);
-      *psum = gerepilecopy(av, *psum);
-    }
+    gen_BG_add(E, fun, bg, pn, j, nexta, a);
+    avma = av;
   }
 }
 
@@ -90,39 +93,35 @@ gen_BG_init(struct bg_data *bg, GEN E, GEN N, GEN bnd, GEN ap)
   bg->an[1] = 1;
 }
 
-static GEN
-gen_BG_rec(void *E, bg_fun *fun, struct bg_data *bg, GEN sum0)
+static void
+gen_BG_rec(void *E, bg_fun *fun, struct bg_data *bg)
 {
-  long i, j, lp = lg(bg->p)-1, lim;
+  long i, j, lp = lg(bg->p)-1;
   GEN bndov2 = shifti(bg->bnd, -1);
   pari_sp av = avma, av2;
-  GEN sum, p;
+  GEN p;
   forprime_t S;
   (void)forprime_init(&S, utoipos(bg->p[lp]+1), bg->bnd);
-  av2 = avma; lim = stack_lim(av2,1);
+  av2 = avma;
   if(DEBUGLEVEL)
     err_printf("1st stage, using recursion for p <= %ld\n", bg->p[lp]);
-  sum = gcopy(sum0);
   for (i = 1; i <= lp; i++)
   {
     ulong pp = bg->p[i];
     long ap = bg->ap[i];
-    gen_BG_add(E, fun, bg, &sum, utoipos(pp), i, stoi(ap), gen_1);
-    if (low_stack(lim, stack_lim(av2,1)))
-    {
-      if (DEBUGMEM>1) pari_warn(warnmem,"ellL1, p=%lu",pp);
-      sum = gerepileupto(av2, sum);
-    }
+    gen_BG_add(E, fun, bg, utoipos(pp), i, stoi(ap), gen_1);
+    avma = av2;
   }
   if (DEBUGLEVEL) err_printf("2nd stage, looping for p <= %Ps\n", bndov2);
   while ( (p = forprime_next(&S)) )
   {
     long jmax;
     GEN ap = ellap(bg->E, p);
+    pari_sp av3 = avma;
     if (!signe(ap)) continue;
 
     jmax = itou( divii(bg->bnd, p) ); /* 2 <= jmax <= el->rootbound */
-    fun(E, &sum, p, ap, -jmax); /*Beware: create a cache on the stack */
+    fun(E, p, ap);
     for (j = 2;  j <= jmax; j++)
     {
       long aj = bg->an[j];
@@ -130,13 +129,10 @@ gen_BG_rec(void *E, bg_fun *fun, struct bg_data *bg, GEN sum0)
       if (!aj) continue;
       a = mulis(ap, aj);
       n = muliu(p, j);
-      fun(E, &sum, n, a, j);
-    }
-    if (low_stack(lim, stack_lim(av2,1)))
-    {
-      if (DEBUGMEM>1) pari_warn(warnmem,"ellL1, p=%Ps",p);
-      sum = gerepilecopy(av2, sum);
+      fun(E, n, a);
+      avma = av3;
     }
+    avma = av2;
     if (absi_cmp(p, bndov2) >= 0) break;
   }
   if (DEBUGLEVEL) err_printf("3nd stage, looping for p <= %Ps\n", bg->bnd);
@@ -144,469 +140,463 @@ gen_BG_rec(void *E, bg_fun *fun, struct bg_data *bg, GEN sum0)
   {
     GEN ap = ellap(bg->E, p);
     if (!signe(ap)) continue;
-    fun(E, &sum, p, ap, 0);
-    if (low_stack(lim, stack_lim(av2,1)))
-    {
-      if (DEBUGMEM>1) pari_warn(warnmem,"ellL1, p=%Ps",p);
-      sum = gerepilecopy(av2, sum);
-    }
+    fun(E, p, ap);
+    avma = av2;
   }
-  return gerepileupto(av, sum);
+  avma = av;
 }
 
-/* Computing L-series derivatives */
+/******************************************************************
+ *
+ * L functions of elliptic curves
+ * Pascal Molin (molin.maths at gmail.com) 2014
+ *
+ ******************************************************************/
 
-/* Implementation by C. Delaunay and X.-F. Roblot
-   after a GP script of Tom Womack and John Cremona
-   and the corresponding section of Henri Cohen's book GTM 239
-   Generic Buhler-Gross iteration and baby-step-giant-step implementation
-   by Bill Allombert.
-*/
-
-/* used to compute exp((g*bgbnd + b) C) = baby[b] * giant[g] */
-struct babygiant
+struct lcritical
 {
-  GEN baby, giant;
-  ulong bgbnd;
+  GEN h;    /* real */
+  long cprec; /* computation prec */
+  long L; /* number of points */
+  GEN  K; /* length of series */
+  long real;
 };
 
-struct ellld {
-  GEN E, N; /* ell, conductor */
-  GEN bnd; /* t_INT; will need all an for n <= bnd */
-  ulong rootbnd; /* floor(sqrt(bnd)) */
-  long r; /* we are computing L^{(r)}(1) */
-  GEN X; /* t_REAL, 2Pi / sqrt(N) */
-  GEN eX; /* t_REAL, exp(X) */
-  GEN emX; /* t_REAL, exp(-X) */
-  long epsbit;
-  /* only if r > 1 */
-  GEN alpha; /* t_VEC of t_REALs, except alpha[1] = gen_1 */
-  GEN A; /* t_VEC of t_REALs, A[1] = 1 */
-  /* only if r = 1 */
-  GEN gcache, gjcache; /* t_VEC of t_REALs */
-  /* only if r = 0 */
-  struct babygiant BG[1];
-};
-
-static GEN
-init_alpha(long m, long prec)
+static double
+logboundG0(long e, double aY)
 {
-  GEN a, si, p1;
-  GEN s = gadd(pol_x(0), zeroser(0, m+1));
-  long i;
-
-  si = s;
-  p1 = gmul(mpeuler(prec), s);
-  for (i = 2; i <= m; i++)
-  {
-    si = gmul(si, s); /* = s^i */
-    p1 = gadd(p1, gmul(divru(szeta(i, prec), i), si));
-  }
-  p1 = gexp(p1, prec); /* t_SER of valuation = 0 */
+  double cla, loggam;
+  cla = 1 + 1/sqrt(aY);
+  if (e) cla = ( cla + 1/(2*aY) ) / (2*sqrt(aY));
+  loggam = (e) ? log(2)-aY : -aY + log( log( 1+1/aY) );
+  return log(cla) + loggam;
+}
 
-  a = cgetg(m+2, t_VEC);
-  for (i = 1; i <= m+1; i++) gel(a, i) = gel(p1, i+1);
-  return a;
+static void
+param_points(GEN N, double Y, double tmax, long bprec, long *cprec, long *L,
+             GEN *K, double *h)
+{
+  double D, a, aY, X, logM;
+  long d = 2, w = 1;
+  tmax *= d;
+  D = bprec * LOG2 + M_PI/4*tmax + 2;
+  *cprec = nbits2prec(ceil(D / LOG2) + 5);
+  a = 2 * M_PI / sqrt(gtodouble(N));
+  aY = a * cos(M_PI/2*Y);
+  logM = log(4) + logboundG0(w+1, aY) + tmax * Y * M_PI/2;
+  *h = ( 2 * M_PI * M_PI / 2 * Y ) / ( D + logM );
+  X = log( D / a);
+  *L = ceil( X / *h);
+  *K = ceil_safe(dbltor( D / a ));
 }
 
-/* assume r >= 2, return a t_VEC A of t_REALs of length > 2.
- * NB: A[1] = 1 */
 static GEN
-init_A(long r, long m, long prec)
+vecF2_lk(GEN E, GEN K, GEN rbnd, GEN Q, GEN sleh, long prec)
 {
-  const long l = m+1;
-  long j, s, n;
-  GEN A, B, ONE, fj;
-  pari_sp av0, av;
-
-  A = cgetg(l, t_VEC); /* will contain the final result */
-  gel(A,1) = real_1(prec);
-  for (j = 2; j < l; j++) gel(A,j) = cgetr(prec);
-  av0 = avma;
-  B = cgetg(l, t_VEC); /* scratch space */
-  for (j = 1; j < l; j++) gel(B,j) = cgetr(prec);
-  ONE = real_1(prec);
-  av = avma;
-
-  /* We alternate between two temp arrays A, B (initially virtually filled
-   * ONEs = 1.), which are swapped after each loop.
-   * After the last loop, we want A to contain the final array: make sure
-   * we swap an even number of times */
-  if (odd(r)) swap(A, B);
-
-  /* s = 1 */
-    for (n = 2; n <= m; n++)
-    {
-      GEN p3 = ONE; /* j = 1 */
-      for (j = 2; j <= n; j++) p3 = addrr(p3, divru(ONE, j));
-      affrr(p3, gel(B, n)); avma = av;
-    }
-  swap(A, B); /* B becomes the new A, old A becomes the new scratchspace */
-  for (s = 2; s <= r; s++)
+  pari_sp av = avma, av2;
+  long l, L  = lg(K)-1;
+  GEN a = anellsmall(E, itos(gel(K,1)));
+  GEN S = cgetg(L+1, t_VEC);
+  for (l = 1; l <= L; l++)
+    gel(S,l) = cgetr(prec);
+  av2 = avma;
+  for (l = 1; l <= L; ++l)
   {
-    for (n = 2; n <= m; n++)
+    GEN e1, Sl;
+    long aB, b, A, B;
+    GEN z, zB;
+    pari_sp av3;
+    long Kl = itou(gel(K,l));
+    /* FIXME: could reduce prec here (useful for large prec) */
+    e1 = gel(Q, l);
+    Sl = real_0(prec);;
+    /* baby-step giant step */
+    A = rbnd[l]; B = A;
+    z = powersr(e1, B); zB = gel(z, B+1);
+    av3 = avma;
+    for (aB = A*B; aB >= 0; aB -= B)
     {
-      GEN p3 = ONE; /* j = 1 */
-      for (j = 2; j <= n; j++) p3 = addrr(p3, divru(gel(A, j), j));
-      affrr(p3, gel(B, n)); avma = av;
+      GEN s = real_0(prec); /* could change also prec here */
+      for (b = B; b > 0; --b)
+      {
+        long k = aB+b;
+        if (k <= Kl && a[k]) s = addrr(s, mulsr(a[k], gel(z, b+1)));
+        if (gc_needed(av3, 1))
+          gerepileall(av3, 2, &s, &Sl);
+      }
+      Sl = addrr(mulrr(Sl, zB), s);
     }
-    swap(A, B); /* B becomes the new A, old A becomes the new scratchspace */
+    affrr(mulrr(Sl, gel(sleh,l)), gel(S, l)); /* to avoid copying all S */
+    avma = av2;
   }
-
-  /* leave A[1] (division by 1) alone */
-  fj = ONE; /* will destroy ONE now */
-  for (j = 2; j < l; j++)
-  {
-    affrr(mulru(fj, j), fj);
-    affrr(divrr(gel(A,j), fj), gel(A,j));
-    avma = av;
-  }
-  avma = av0; return A;
+  return gerepilecopy(av, S);
 }
 
-/* x > 0 t_REAL, M >= 2 */
-static long
-estimate_prec_Sx(GEN x, long M)
+/* Return C, C[i][j] = Q[j]^i, i = 1..nb */
+static void
+baby_init(struct baby_giant *bb, GEN Q, GEN bnd, GEN rbnd, long prec)
 {
-  GEN p1, p2;
-  pari_sp av = avma;
-
-  x = rtor(x, DEFAULTPREC);
-  p1 = divri(powru(x, M-2), mpfact(M-1)); /* x^(M-2) / (M-1)! */
-  if (expo(x) < 0)
+  long i, j, l = lg(Q);
+  GEN R, C, r0;
+  C = cgetg(l,t_VEC);
+  for (i = 1; i < l; ++i)
+    gel(C, i) = powersr(gel(Q, i), rbnd[i]);
+  R = cgetg(l,t_VEC);
+  r0 = real_0(prec);
+  for (i = 1; i < l; ++i)
   {
-    p2 = divrr(mulrr(p1, powru(x,3)), mulur(M,subsr(1,x)));/* x^(M+1)/(1-x)M! */
-    if (cmprr(p2,p1) < 0) p1 = p2;
+    gel(R, i) = cgetg(rbnd[i]+1, t_VEC);
+    gmael(R, i, 1) = cgetr(prec);
+    affrr(gmael(C, i, 2),gmael(R, i, 1));
+    for (j = 2; j <= rbnd[i]; j++)
+    {
+      gmael(R, i, j) = cgetr(prec);
+      affrr(r0, gmael(R, i, j));
+    }
   }
-  avma = av; return expo(p1);
+  bb->baby = C; bb->giant = R;
+  bb->bnd = bnd; bb->rbnd = rbnd;
 }
 
-/* x a t_REAL */
 static long
-number_of_terms_Sx(GEN x, long epsbit)
+baby_size(GEN rbnd, long Ks, long prec)
 {
-  long M, M1, M2;
-  M1 = (long)(epsbit * 7.02901423262); /* epsbit * log(2) / (log(3) - 1) */
-  M2 = itos(ceil_safe(gmul2n(x,1))); /* >= 2x */
-  if (M2 < 2) M2 = 2;
-  M = M2;
-  for(;;)
-  {
-    if (estimate_prec_Sx(x, M) < -epsbit) M1 = M; else M2 = M;
-    M = (M1+M2+1) >> 1;
-    if (M >= M1) return M1;
-  }
+  long i, s, m, l = lg(rbnd);
+  for (s = 0, i = 1; i < l; ++i)
+    s += rbnd[i];
+  m = 2*s*prec + 3*l + s;
+  if (DEBUGLEVEL > 0)
+    err_printf("ellL1: BG_add: %ld words, ellan: %ld words\n", m, Ks);
+  return m;
 }
 
-/* X t_REAL, emX = exp(-X) t_REAL; return t_INT */
-static GEN
-cutoff_point(long r, GEN X, GEN emX, long epsbit, long prec)
+static void
+ellL1_add(void *E, GEN n, GEN a)
 {
-  GEN M1 = ceil_safe(divsr(7*prec2nbits(prec)+1, X));
-  GEN M2 = gen_2, M = M1;
-  for(;;)
-  {
-    GEN c = divrr(powgi(emX, M), powru(mulri(X,M), r+1));
-    if (expo(c) < -epsbit) M1 = M; else M2 = M;
-    M = shifti(addii(M1, M2), -1);
-    if (cmpii(M2, M) >= 0) return M;
-  }
+  pari_sp av = avma;
+  struct baby_giant *bb = (struct baby_giant*) E;
+  long j, l = lg(bb->giant);
+  for (j = 1; j < l; j++)
+    if (cmpii(n, gel(bb->bnd,j)) <= 0)
+    {
+      ulong r, q = udiviu_rem(n, bb->rbnd[j], &r);
+      GEN giant = gel(bb->giant, j), baby = gel(bb->baby, j);
+      affrr(addrr(gel(giant, q+1), mulri(gel(baby, r+1), a)), gel(giant, q+1));
+      avma = av;
+    } else break;
 }
 
-/* x "small" t_REAL, use power series expansion. Returns a t_REAL */
 static GEN
-compute_Gr_VSx(struct ellld *el, GEN x)
+vecF2_lk_bsgs(GEN E, GEN bnd, GEN rbnd, GEN Q, GEN sleh, GEN N, long prec)
 {
   pari_sp av = avma;
-  long r = el->r, n;
-  /* n = 2 */
-  GEN p1 = divrs(sqrr(x), -2); /* (-1)^(n-1) x^n / n! */
-  GEN p2 = x;
-  GEN p3 = shiftr(p1, -r);
-  for (n = 3; ; n++)
+  struct bg_data bg;
+  struct baby_giant bb;
+  long k, L = lg(bnd)-1;
+  GEN S;
+  baby_init(&bb, Q, bnd, rbnd, prec);
+  gen_BG_init(&bg, E, N, gel(bnd,1), NULL);
+  gen_BG_rec((void*) &bb, ellL1_add, &bg);
+  S = cgetg(L+1, t_VEC);
+  for (k = 1; k <= L; ++k)
   {
-    if (expo(p3) < -el->epsbit) return gerepilecopy(av, p2);
-    p2 = addrr(p2, p3);
-    p1 = divrs(mulrr(p1, x), -n); /* (-1)^(n-1) x^n / n! */
-    p3 = divri(p1, powuu(n, r));
+    pari_sp av2 = avma;
+    long j, g = rbnd[k];
+    GEN giant = gmael(bb.baby, k, g+1);
+    GEN Sl = real_0(prec);
+    for (j = g; j >=1; j--)
+      Sl = addrr(mulrr(Sl, giant), gmael(bb.giant,k,j));
+    gel(S, k) = gerepileupto(av2, mulrr(gel(sleh,k), Sl));
   }
-  /* sum_{n = 1}^{oo} (-1)^(n-1) x^n / (n! n^r) */
+  return gerepileupto(av, S);
 }
 
-/* t_REAL, assume r >= 2. m t_INT or NULL; Returns a t_REAL */
 static GEN
-compute_Gr_Sx(struct ellld *el, GEN m, ulong sm)
+vecF(struct lcritical *C, GEN E)
 {
-  pari_sp av = avma;
-  const long thresh_SMALL = 5;
-  long i, r = el->r;
-  GEN x = m? mulir(m, el->X): mulur(sm, el->X);
-  GEN logx = mplog(x), p4;
-  /* i = 0 */
-  GEN p3 = gel(el->alpha, r+1);
-  GEN p2 = logx;
-  for (i = 1; i < r; i++)
-  { /* p2 = (logx)^i / i! */
-    p3 = addrr(p3, mulrr(gel(el->alpha, r-i+1), p2));
-    p2 = divru(mulrr(p2, logx), i+1);
+  pari_sp av = avma, av2;
+  long prec = C->cprec, Ks = itos_or_0(C->K), l, L = C->L;
+  GEN N = ellQ_get_N(E);
+  GEN PiN = shiftr(divrr(mppi(prec), gsqrt(N, prec)), 1);
+  GEN eh = mpexp(C->h), elh = powersr(eh, L-1), sleh = elh;
+  GEN Q, bnd, rbnd, vec;
+  rbnd = cgetg(L+1, t_VECSMALL);
+  av2 = avma;
+  bnd = cgetg(L+1, t_VEC);
+  Q  = cgetg(L+1, t_VEC);
+  for (l = 1; l <= L; ++l)
+  {
+    gel(bnd,l) = l==1 ? C->K: ceil_safe(divir(C->K, gel(elh, l)));
+    rbnd[l] = itou(sqrtint(gel(bnd,l)))+1;
+    gel(Q, l) = mpexp(mulrr(negr(PiN), gel(elh, l)));
   }
-  /* i = r, use alpha[1] = 1 */
-  p3 = addrr(p3, p2);
-
-  if (cmprs(x, thresh_SMALL) < 0)
-    p4 = compute_Gr_VSx(el, x); /* x "small" use expansion near 0 */
+  gerepileall(av2, 2, &bnd, &Q);
+  if (Ks && baby_size(rbnd, Ks, prec) > (Ks>>1))
+    vec = vecF2_lk(E, bnd, rbnd, Q, sleh, prec);
   else
-  { /* x "large" use expansion at infinity */
-    pari_sp av = avma, lim = stack_lim(av, 2);
-    long M = lg(el->A);
-    GEN xi = sqrr(x); /* x^2 */
-    p4 = x; /* i = 1. Uses A[1] = 1; NB: M > 1 */
-    for (i = 2; i < M; i++)
-    {
-      GEN p5 = mulrr(xi, gel(el->A, i));
-      if (expo(p5) < -el->epsbit) break;
-      p4 = addrr(p4, p5);
-      xi = mulrr(xi, x); /* = x^i */
-      if (low_stack(lim, stack_lim(av, 2)))
-      {
-        if (DEBUGMEM > 0) pari_warn(warnmem, "compute_Gr_Sx");
-        gerepileall(av, 2, &xi, &p4);
-      }
-    }
-    p4 = mulrr(p4, m? powgi(el->emX, m): powru(el->emX, sm));
-  }
-  return gerepileuptoleaf(av, odd(r)? subrr(p4, p3): subrr(p3, p4));
+    vec = vecF2_lk_bsgs(E, bnd, rbnd, Q, sleh, N, prec);
+  return gerepileupto(av, vec);
 }
 
-/* return G_r(X), cache values G(n*X), n < rootbnd.
- * If r = 0, G(x) = exp(-x), cache Baby/Giant struct in el->BG
- * If r >= 2, precompute the expansions at 0 and oo of G */
+/* ************************************************************************
+ *
+ * Compute Lambda function by Fourier inversion
+ *
+ */
+
 static GEN
-init_G(struct ellld *el, long prec)
+glambda(GEN t, GEN vec, GEN h, long real, long prec)
 {
-  if (el->r == 0)
+  GEN ehs, elhs;
+  GEN r;
+  long L = lg(vec)-1, l;
+  /* assume vec is a grid */
+  ehs = gexp(gmul(gen_I(),gmul(h, t)), prec);
+  elhs = (real == 1) ? gen_1 : mkcomplex(gen_0, gen_m1);
+  r = greal(gmul(greal(gel(vec, 1)), elhs)); /* FIXME: sure ? */
+  /* FIXME: summing backward may be more stable */
+  for (l = 2; l <= L; ++l)
   {
-    ulong bnd = el->rootbnd+1;
-    el->BG->bgbnd = bnd;
-    el->BG->baby  = powruvec(el->emX, bnd);
-    el->BG->giant = powruvec(gel(el->BG->baby,bnd), bnd);
-    return gel(el->BG->baby, 1);
+    elhs = gmul(elhs, ehs);
+    r = gadd(r, gmulsg(2, greal(gmul(gel(vec, l), elhs))));
   }
-  if (el->r == 1)
-    el->gcache = mpveceint1(el->X, el->eX, el->rootbnd);
-  else
-  {
-    long m, j, l = el->rootbnd;
-    GEN G;
-    m = number_of_terms_Sx(mulri(el->X, el->bnd), el->epsbit);
-    el->alpha = init_alpha(el->r, prec);
-    el->A = init_A(el->r, m, prec);
-    G = cgetg(l+1, t_VEC);
-    for (j = 1; j <= l; j++) gel(G,j) = compute_Gr_Sx(el, NULL, j);
-    el->gcache = G;
-  }
-  return gel(el->gcache, 1);
+  return gmul(mulsr(2, h), r);
 }
 
-/* r >= 2; sum += G(n*X) * a_n / n */
-static void
-ellld_L1(void *E, GEN *psum, GEN n, GEN a, long j)
-{
-  struct ellld *el = (struct ellld *)E;
-  GEN G;
-  (void)j;
-  if (cmpiu(n, el->rootbnd) <= 0)
-    G = gel(el->gcache, itou(n));
-  else
-    G = compute_Gr_Sx(el, n, 0);
-  *psum = addrr(*psum, divri(mulir(a, G), n));
-}
-/* r = 1; sum += G(n*X) * a_n / n, where G = eint1.
- * If j < 0, cache values G(n*a*X), 1 <= a <= |j| in gjcache
- * If j > 0, assume n = N*j and retrieve G(N*j*X), from gjcache */
-static void
-ellld_L1r1(void *E, GEN *psum, GEN n, GEN a, long j)
+static GEN
+Lpoints(struct lcritical *C, GEN e, GEN tmax, long bprec)
 {
-  struct ellld *el = (struct ellld *)E;
-  GEN G;
-  if (j==0)
-  {
-    if (cmpiu(n, el->rootbnd) <= 0)
-      G = gel(el->gcache, itou(n));
-    else
-      G = mpeint1(mulir(n,el->X), powgi(el->eX,n));
-  }
-  else if (j < 0)
-  {
-    el->gjcache = mpveceint1(mulir(n,el->X), powgi(el->eX,n), -j);
-    G = gel(el->gjcache, 1);
-  }
-  else
-    G = gel(el->gjcache, j);
-  *psum = addrr(*psum, divri(mulir(a, G), n));
+  double h = 0, Y = .97;
+  GEN N = ellQ_get_N(e);
+  param_points(N, Y, gtodouble(tmax), bprec, &C->cprec, &C->L, &C->K, &h);
+  C->real = ellrootno_global(e);
+  C->h = rtor(dbltor(h), C->cprec);
+  return vecF(C, e);
 }
 
-/* assume n / h->bgbnd fits in an ulong */
-static void
-get_baby_giant(struct babygiant *h, GEN n, GEN *b, GEN *g)
-{
-  ulong r, q = udiviu_rem(n, h->bgbnd, &r);
-  *b = r? gel(h->baby,r): NULL;
-  *g = q? gel(h->giant,q): NULL;
-}
-static void
-ellld_L1r0(void *E, GEN *psum, GEN n, GEN a, long j)
+static GEN
+Llambda(GEN vec, struct lcritical *C, GEN t, long prec)
 {
-  GEN b, g, G;
-  get_baby_giant(((struct ellld*)E)->BG, n, &b, &g);
-  (void)j;
-  if (!b)      G = g;
-  else if (!g) G = b;
-  else         G = mulrr(b,g);
-  *psum = addrr(*psum, divri(mulir(a, G), n));
+  GEN lambda = glambda(gprec_w(t, C->cprec), vec, C->h, C->real, C->cprec);
+  return gprec_w(lambda, prec);
 }
-static void
-heegner_L1(void*E, GEN *psum, GEN n, GEN a, long jmax)
+
+/* 2*(2*Pi)^(-s)*gamma(s)*N^(s/2); */
+static GEN
+ellgammafactor(GEN N, GEN s, long prec)
 {
-  long j, l = lg(*psum);
-  GEN b, g, sum = cgetg(l, t_VEC);
-  get_baby_giant((struct babygiant*)E, n, &b, &g);
-  (void)jmax;
-  for (j = 1; j < l; j++)
-  {
-    GEN G;
-    if (!b)      G = real_i(gel(g,j));
-    else if (!g) G = real_i(gel(b,j));
-    else         G = mulreal(gel(b,j), gel(g,j));
-    gel(sum, j) = addrr(gel(*psum,j), divri(mulir(a, G), n));
-  }
-  *psum = sum;
+  GEN Ns2 = gpow(N, gdivgs(s, 2), prec);
+  Ns2 = gmul(Ns2, gmulsg(2, gpow(shiftr(mppi(prec), 1), gneg(s), prec)));
+  return gmul(Ns2, ggamma(s, prec));
 }
 
-/* Basic data independent from r (E, N, X, eX, emX) already filled,
- * Returns a t_REAL */
 static GEN
-ellL1_i(struct ellld *el, struct bg_data *bg, long r, GEN ap, long prec)
+ellL1_eval(GEN e, GEN vec, struct lcritical *C, GEN t, long prec)
 {
-  GEN sum;
-  if (DEBUGLEVEL) err_printf("in ellL1 with r = %ld, prec = %ld\n", r, prec);
-  el->r = r;
-  el->bnd = cutoff_point(r, el->X, el->emX, el->epsbit, prec);
-  gen_BG_init(bg,el->E,el->N,el->bnd,ap);
-  el->rootbnd = bg->rootbnd;
-  sum = init_G(el, prec);
-  if (DEBUGLEVEL>=3) err_printf("el_bnd = %Ps, N=%Ps\n", el->bnd, el->N);
-  sum = gen_BG_rec(el, r>=2? ellld_L1: (r==1? ellld_L1r1: ellld_L1r0), bg, sum);
-  return mulri(shiftr(sum, 1), mpfact(r));
+  GEN gam = ellgammafactor(ellQ_get_N(e), gaddgs(t, 1), prec);
+  return gdiv(Llambda(vec, C, t, prec), gam);
 }
 
-static void
-init_el(struct ellld *el, GEN E, long *parity, long bitprec)
+static GEN
+ellL1_der(GEN e, GEN vec, struct lcritical *C, GEN t, long der, long prec)
 {
-  GEN eX;
-  long prec;
-
-  el->E = E = ellanal_globalred(E, NULL);
-  el->N = ellQ_get_N(E);
-  prec = nbits2prec(bitprec+(expi(el->N)>>1));
-  el->X = divrr(Pi2n(1, prec), sqrtr(itor(el->N, prec))); /* << 1 */
-  eX = mpexp(el->X);
-  if (realprec(eX) > prec) eX = rtor(eX, prec); /* avoid spurious accuracy increase */
-  el->eX = eX;
-  el->emX = invr(el->eX);
-  el->epsbit = bitprec+1;
-  *parity = (ellrootno_global(E) > 0)? 0: 1; /* rank parity */
+  GEN r = polcoeff0(ellL1_eval(e, vec, C, t, prec), der, 0);
+  if (odd(der>>1)) r = gneg(r);
+  return gmul(r, mpfact(der));
 }
 
 static GEN
 ellL1_bitprec(GEN E, long r, long bitprec)
 {
   pari_sp av = avma;
-  struct ellld el;
-  struct bg_data bg;
-  long parity;
-  long prec = nbits2prec(bitprec)+1;
-  if (r<0) pari_err_DOMAIN("ellL1","derivative order","<",gen_0,stoi(r));
-  init_el(&el, E, &parity, bitprec);
-  if (parity != (r & 1)) return gen_0;
-  return gerepileuptoleaf(av, ellL1_i(&el, &bg, r, NULL, prec));
+  struct lcritical C;
+  long prec = nbits2prec(bitprec);
+  GEN e, vec, t;
+  if (r < 0)
+    pari_err_DOMAIN("ellL1", "derivative order", "<", gen_0, stoi(r));
+  e = ellanal_globalred(E, NULL);
+  if (r == 0 && ellrootno_global(e) < 0) { avma = av; return gen_0; }
+  vec = Lpoints(&C, e, gen_0, bitprec);
+  t = r ? scalarser(gen_1, 0, r):  zeroser(0, 0);
+  setvalp(t, 1);
+  return gerepileupto(av, ellL1_der(e, vec, &C, t, r, prec));
 }
 
 GEN
 ellL1(GEN E, long r, long prec) { return ellL1_bitprec(E, r, prec2nbits(prec)); }
 
-GEN
-ellanalyticrank(GEN e, GEN eps, long prec)
+static GEN
+ellanalyticrank_bprec(GEN E, GEN eps, long bprec)
 {
-  struct ellld el;
-  struct bg_data bg;
-  long rk;
   pari_sp av = avma, av2;
-  GEN ap = NULL;
-  pari_timer T;
-
+  long prec = nbits2prec(bprec);
+  struct lcritical C;
+  pari_timer ti;
+  GEN e, vec;
+  long rk;
+  if (DEBUGLEVEL) timer_start(&ti);
   if (!eps)
-    eps = real2n(-prec2nbits(prec)/2+1, DEFAULTPREC);
+    eps = real2n(-bprec/2+1, DEFAULTPREC);
   else
     if (typ(eps) != t_REAL) {
       eps = gtofp(eps, DEFAULTPREC);
       if (typ(eps) != t_REAL) pari_err_TYPE("ellanalyticrank", eps);
     }
-  init_el(&el, e, &rk, prec2nbits(prec)); /* set rk to rank parity (0 or 1) */
-  if (DEBUGLEVEL) {
-    err_printf("ellanalyticrank: rank is %s, eps=%Ps\n", rk? "odd": "even",eps);
-    timer_start(&T);
-  }
+  e = ellanal_globalred(E, NULL);
+  vec = Lpoints(&C, e, gen_0, bprec);
+  if (DEBUGLEVEL) timer_printf(&ti, "init L");
   av2 = avma;
-  for(;; rk += 2)
+  for (rk = C.real>0 ? 0: 1;  ; rk += 2)
   {
-    GEN Lr1 = ellL1_i(&el, &bg, rk, ap, prec);
-    if (DEBUGLEVEL) timer_printf(&T, "L^(%ld)=%Ps", rk, Lr1);
-    if (absr_cmp(Lr1, eps) > 0) return gerepilecopy(av, mkvec2(stoi(rk), Lr1));
-    ap = gerepilecopy(av2, bg.ap);
+    GEN Lrk;
+    GEN t = rk ? scalarser(gen_1, 0, rk):  zeroser(0, 0);
+    setvalp(t, 1);
+    Lrk = ellL1_der(e, vec, &C, t, rk, prec);
+    if (DEBUGLEVEL) timer_printf(&ti, "L^(%ld)=%Ps", rk, Lrk);
+    if (absr_cmp(Lrk, eps) > 0)
+      return gerepilecopy(av, mkvec2(stoi(rk), Lrk));
+    avma = av2;
   }
 }
 
-/* This file is a C version by Bill Allombert of a GP script by
+GEN
+ellanalyticrank(GEN E, GEN eps, long prec)
+{
+  return ellanalyticrank_bprec(E, eps, prec2nbits(prec));
+}
+
+/*        Heegner point computation
+
+   This section is a C version by Bill Allombert of a GP script by
    Christophe Delaunay which was based on a GP script by John Cremona.
    Reference: Henri Cohen's book GTM 239.
 */
 
+static void
+heegner_L1_bg(void*E, GEN n, GEN a)
+{
+  struct baby_giant *bb = (struct baby_giant*) E;
+  long j, l = lg(bb->giant);
+  for (j = 1; j < l; j++)
+    if (cmpii(n, gel(bb->bnd,j)) <= 0)
+    {
+      ulong r, q = udiviu_rem(n, bb->rbnd[j], &r);
+      GEN giant = gel(bb->giant, j), baby = gel(bb->baby, j);
+      gaffect(gadd(gel(giant, q+1), gdiv(gmul(gel(baby, r+1), a), n)), gel(giant, q+1));
+    }
+}
+
+static void
+heegner_L1(void*E, GEN n, GEN a)
+{
+  struct baby_giant *bb = (struct baby_giant*) E;
+  long j, l = lg(bb->giant);
+  for (j = 1; j < l; j++)
+    if (cmpii(n, gel(bb->bnd,j)) <= 0)
+    {
+      ulong r, q = udiviu_rem(n, bb->rbnd[j], &r);
+      GEN giant = gel(bb->giant, j), baby = gel(bb->baby, j);
+      GEN ex = mulreal(gel(baby, r+1), gel(giant, q+1));
+      affrr(addrr(gel(bb->sum, j), divri(mulri(ex, a), n)), gel(bb->sum, j));
+    }
+}
 /* Return C, C[i][j] = Q[j]^i, i = 1..nb */
-static GEN
-fillstep(GEN Q, long nb)
+static void
+baby_init2(struct baby_giant *bb, GEN Q, GEN bnd, GEN rbnd, long prec)
+{
+  long i, j, l = lg(Q);
+  GEN R, C, r0;
+  C = cgetg(l,t_VEC);
+  for (i = 1; i < l; ++i)
+    gel(C, i) = gpowers(gel(Q, i), rbnd[i]);
+  R = cgetg(l,t_VEC);
+  r0 = mkcomplex(real_0(prec),real_0(prec));
+  for (i = 1; i < l; ++i)
+  {
+    gel(R, i) = cgetg(rbnd[i]+1, t_VEC);
+    gmael(R, i, 1) = cgetc(prec);
+    gaffect(gmael(C, i, 2),gmael(R, i, 1));
+    for (j = 2; j <= rbnd[i]; j++)
+    {
+      gmael(R, i, j) = cgetc(prec);
+      gaffect(r0, gmael(R, i, j));
+    }
+  }
+  bb->baby = C; bb->giant = R;
+  bb->bnd = bnd; bb->rbnd = rbnd;
+}
+
+/* Return C, C[i][j] = Q[j]^i, i = 1..nb */
+static void
+baby_init3(struct baby_giant *bb, GEN Q, GEN bnd, GEN rbnd, long prec)
 {
-  long i, k, l = lg(Q);
-  GEN C = cgetg(nb+1,t_VEC);
-  gel(C,1) = Q;
-  for (i = 2; i<=nb; ++i)
+  long i, l = lg(Q);
+  GEN R, C, S;
+  C = cgetg(l,t_VEC);
+  for (i = 1; i < l; ++i)
+    gel(C, i) = gpowers(gel(Q, i), rbnd[i]);
+  R = cgetg(l,t_VEC);
+  for (i = 1; i < l; ++i)
+    gel(R, i) = gpowers(gmael(C, i, 1+rbnd[i]), rbnd[i]);
+  S = cgetg(l,t_VEC);
+  for (i = 1; i < l; ++i)
   {
-    gel(C,i) = cgetg(l, t_VEC);
-    for (k = 1; k<l; ++k) gmael(C,i,k) = gmul(gel(Q,k),gmael(C,i-1,k));
+    gel(S, i) = cgetr(prec);
+    affrr(real_i(gmael(C, i, 2)), gel(S, i));
   }
-  return C;
+  bb->baby = C; bb->giant = R; bb->sum = S;
+  bb->bnd = bnd; bb->rbnd = rbnd;
 }
 
 /* ymin a t_REAL */
 static GEN
-heegner_psi(GEN E, GEN N, GEN ymin, GEN points, long bitprec)
+heegner_psi(GEN E, GEN N, GEN points, long bitprec)
 {
-  pari_sp av = avma;
-  struct babygiant BG[1];
+  pari_sp av = avma, av2;
+  struct baby_giant bb;
   struct bg_data bg;
-  ulong bnd;
-  long k, np = lg(points), prec = nbits2prec(bitprec)+1;
-  GEN sum, Q, pi2 = Pi2n(1, prec);
-  GEN B = ceilr(divrr(mulur(bitprec,mplog2(DEFAULTPREC)), mulrr(pi2, ymin)));
-  gen_BG_init(&bg,E,N,B,NULL);
-  bnd = bg.rootbnd + 1;
-  BG->bgbnd = bnd;
-  Q = cgetg(np, t_VEC);
-  for (k = 1; k<np; ++k) gel(Q, k) = expIxy(pi2, gel(points, k), prec);
-  BG->baby  = fillstep(Q, bnd);
-  BG->giant = fillstep(gel(BG->baby, bnd), bnd);
-  sum = gen_BG_rec((void*)BG, heegner_L1, &bg, real_i(Q));
-  return gerepileupto(av, sum);
+  long k, L = lg(points)-1, prec = nbits2prec(bitprec)+EXTRAPRECWORD;
+  GEN  Q, pi2 = Pi2n(1, prec), bnd, rbnd;
+  long l;
+  GEN B = divrr(mulur(bitprec,mplog2(DEFAULTPREC)), pi2);
+  GEN bndmax;
+  rbnd = cgetg(L+1, t_VECSMALL);
+  av2 = avma;
+  bnd = cgetg(L+1, t_VEC);
+  Q  = cgetg(L+1, t_VEC);
+  for (l = 1; l <= L; ++l)
+  {
+    gel(bnd,l) = ceil_safe(divrr(B,gimag(gel(points, l))));
+    rbnd[l] = itou(sqrtint(gel(bnd,l)))+1;
+    gel(Q, l) = expIxy(pi2, gel(points, l), prec);
+  }
+  gerepileall(av2, 2, &bnd, &Q);
+  bndmax = gel(bnd,vecindexmax(bnd));
+  gen_BG_init(&bg, E, N, bndmax, NULL);
+  if (bitprec >= 1900)
+  {
+    GEN S;
+    baby_init2(&bb, Q, bnd, rbnd, prec);
+    gen_BG_rec((void*)&bb, heegner_L1_bg, &bg);
+    S = cgetg(L+1, t_VEC);
+    for (k = 1; k <= L; ++k)
+    {
+      pari_sp av2 = avma;
+      long j, g = rbnd[k];
+      GEN giant = gmael(bb.baby, k, g+1);
+      GEN Sl = real_0(prec);
+      for (j = g; j >=1; j--)
+        Sl = gadd(gmul(Sl, giant), gmael(bb.giant,k,j));
+      gel(S, k) = gerepileupto(av2, real_i(Sl));
+    }
+    return gerepileupto(av, S);
+  }
+  else
+  {
+    baby_init3(&bb, Q, bnd, rbnd, prec);
+    gen_BG_rec((void*)&bb, heegner_L1, &bg);
+    return gerepilecopy(av, bb.sum);
+  }
 }
 
 /*Returns lambda_bad list for one prime p, nv = localred(E, p) */
@@ -627,12 +617,12 @@ lambda1(GEN E, GEN nv, GEN p, long prec)
       gel(res, j) = gmul(lp, gsubgs(gdivgs(sqru(j), n), j)); /* j^2/n - j */
   }
   else if (kod < -4)
-    res = mkvec2(negr(lp), divrs(mulrs(lp, kod), 4));
+    res = mkvec2(negr(lp), shiftr(mulrs(lp, kod), -2));
   else
   {
     const long lam[] = {8,9,0,6,0,0,0,3,4};
     long m = -lam[kod+4];
-    res = mkvec(divrs(mulrs(lp, m), 6));
+    res = mkvec(divru(mulrs(lp, m), 6));
   }
   return gerepilecopy(av, res);
 }
@@ -719,8 +709,8 @@ hnaive_max(GEN ell, GEN ht)
   GEN hj     = heightQ(j, prec);
   GEN logb2p = signe(b2)? addrr(logplusQ(gdivgs(b2, 12),prec), mplog2(prec))
                         : real_1(prec);
-  GEN mu     = addrr(divrs(addrr(logd, logj),6), logb2p);
-  return addrs(addrr(addrr(ht, divrs(hj,12)), mu), 2);
+  GEN mu     = addrr(divru(addrr(logd, logj),6), logb2p);
+  return addrs(addrr(addrr(ht, divru(hj,12)), mu), 2);
 }
 
 static GEN
@@ -963,7 +953,7 @@ twistcurve(GEN e, GEN D)
   GEN D2 = sqri(D);
   GEN a4 = mulii(mulsi(-27, D2), ell_get_c4(e));
   GEN a6 = mulii(mulsi(-54, mulii(D, D2)), ell_get_c6(e));
-  return ellinit(mkvec2(a4,a6),NULL,0);
+  return ellinit(mkvec2(a4,a6),NULL,DEFAULTPREC);
 }
 
 static GEN
@@ -982,7 +972,7 @@ heegner_indexmult(GEN om, long t, GEN tam, long prec)
 {
   pari_sp av = avma;
   GEN Ovr = gabs(gimag(gel(om, 2)), prec); /* O_vol/O_re, t_REAL */
-  return gerepileupto(av, divrs(divir(tam, Ovr), 4*t*t));
+  return gerepileupto(av, divru(divir(tam, Ovr), 4*t*t));
 }
 
 
@@ -1054,9 +1044,11 @@ heegner_find_point(GEN e, GEN om, GEN ht, GEN z1, long k, long prec)
   pari_sp av = avma;
   long m;
   GEN Ore = gel(om, 1), Oim = gel(om, 2);
+  if (DEBUGLEVEL > 0)
+    err_printf("%ld*%ld multipliers to test\n",k,lg(lambdas)-1);
   for (m = 0; m < k; m++)
   {
-    GEN P, z2 = divrs(addrr(z1, mulsr(m, Ore)), k);
+    GEN P, z2 = divru(addrr(z1, mulsr(m, Ore)), k);
     if (DEBUGLEVEL > 1)
       err_printf("Trying multiplier %ld\n",m);
     P = heegner_try_point(e, lambdas, ht, z2, prec);
@@ -1177,6 +1169,7 @@ listfill(GEN N, GEN b, GEN c, GEN d, GEN L, long *s)
 static GEN
 listheegner(GEN N, GEN faN4, GEN listQ, GEN D)
 {
+  pari_sp av = avma;
   const long kmin = 30;
   long h = itos(gel(quadclassunit0(D, 0, NULL, DEFAULTPREC), 1));
   GEN ymin, b = Zn_sqrt(D, faN4), L = vectrunc_init(h+1);
@@ -1201,7 +1194,7 @@ listheegner(GEN N, GEN faN4, GEN listQ, GEN D)
     gel(L, k) = mkvec3(t, stoi(lg(Lk) - 2), Q);
     if (!ymin || gcmp(y, ymin) < 0) ymin = y;
   }
-  return mkvec3(ymin, L, D);
+  return gerepilecopy(av, mkvec3(ymin, L, D));
 }
 
 /* Q | N, P = prime divisors of N, R[i] = local epsilon-factor at P[i].
@@ -1216,7 +1209,7 @@ rootno(GEN Q, GEN P, GEN R)
 }
 
 static void
-heegner_find_disc(GEN *ymin, GEN *points, GEN *coefs, long *pind, GEN E,
+heegner_find_disc(GEN *points, GEN *coefs, long *pind, GEN E,
                   GEN indmult, long prec)
 {
   long d = 0;
@@ -1245,8 +1238,12 @@ heegner_find_disc(GEN *ymin, GEN *points, GEN *coefs, long *pind, GEN E,
       GEN indmultD = heegner_indexmultD(faN, indmult, itos(D), sqrtD);
       do
       {
-        GEN mulf = ltwist1(E, D, bprec+expo(indmultD));
-        GEN indr = mulrr(indmultD, mulf);
+        GEN mulf, indr;
+        pari_timer ti;
+        if (DEBUGLEVEL) timer_start(&ti);
+        mulf = ltwist1(E, D, bprec+expo(indmultD));
+        if (DEBUGLEVEL) timer_printf(&ti,"ellL1twist");
+        indr = mulrr(indmultD, mulf);
         if (DEBUGLEVEL>=1) err_printf("Disc = %Ps, Index^2 = %Ps\n", D, indr);
         if (signe(indr)>0 && expo(indr) >= -1) /* indr >=.5 */
         {
@@ -1259,7 +1256,6 @@ heegner_find_disc(GEN *ymin, GEN *points, GEN *coefs, long *pind, GEN E,
             continue;
           }
           *pind = itos(indi);
-          *ymin = gsqrt(gel(Lk, 1), prec);
           L = gel(Lk, 2); l = lg(L);
           pts = cgetg(l, t_VEC);
           cfs = cgetg(l, t_VECSMALL);
@@ -1272,6 +1268,9 @@ heegner_find_disc(GEN *ymin, GEN *points, GEN *coefs, long *pind, GEN E,
             if (!equali1(z)) c *= 2;
             cfs[i] = c;
           }
+          if (DEBUGLEVEL == 1)
+            err_printf("N = %Ps, ymin*N = %Ps\n",N,
+                       gmul(gsqrt(gel(Lk, 1), prec),N));
           *coefs = cfs; *points = pts; return;
         }
       } while(0);
@@ -1280,8 +1279,8 @@ heegner_find_disc(GEN *ymin, GEN *points, GEN *coefs, long *pind, GEN E,
   }
 }
 
-static GEN
-ell_apply_globalred_all(GEN e, GEN *N, GEN *cb, GEN *tam)
+GEN
+ellanal_globalred_all(GEN e, GEN *cb, GEN *N, GEN *tam)
 {
   GEN E = ellanal_globalred(e, cb), red = obj_check(E, Q_GLOBALRED);
   *N = gel(red, 1);
@@ -1294,13 +1293,13 @@ GEN
 ellheegner(GEN E)
 {
   pari_sp av = avma;
-  GEN z, P, ht, points, coefs, ymin, s, om, indmult;
+  GEN z, P, ht, points, coefs, s, om, indmult;
   long ind, lint, k, l, wtor, etor;
   long bitprec = 16, prec = nbits2prec(bitprec)+1;
-  pari_timer T;
+  pari_timer ti;
   GEN N, cb, tam, torsion;
 
-  E = ell_apply_globalred_all(E, &N, &cb, &tam);
+  E = ellanal_globalred_all(E, &cb, &N, &tam);
   if (ellrootno_global(E) == 1)
     pari_err_DOMAIN("ellheegner", "(analytic rank)%2","=",gen_0,E);
   torsion = elltors(E);
@@ -1310,7 +1309,9 @@ ellheegner(GEN E)
   {
     GEN hnaive, l1;
     long bitneeded;
+    if (DEBUGLEVEL) timer_start(&ti);
     l1 = ellL1_bitprec(E, 1, bitprec);
+    if (DEBUGLEVEL) timer_printf(&ti,"ellL1");
     if (expo(l1) < 1 - bitprec/2)
       pari_err_DOMAIN("ellheegner", "analytic rank",">",gen_1,E);
     om = ellR_omega(E,prec);
@@ -1325,11 +1326,10 @@ ellheegner(GEN E)
     prec = nbits2prec(bitprec)+1;
   }
   indmult = heegner_indexmult(om, wtor, tam, prec);
-  heegner_find_disc(&ymin, &points, &coefs, &ind, E, indmult, prec);
-  if (DEBUGLEVEL == 1) err_printf("N = %Ps, ymin*N = %Ps\n",N,gmul(ymin,N));
-  if (DEBUGLEVEL) timer_start(&T);
-  s = heegner_psi(E, N, ymin, points, bitprec);
-  if (DEBUGLEVEL) timer_printf(&T,"heegner_psi");
+  heegner_find_disc(&points, &coefs, &ind, E, indmult, prec);
+  if (DEBUGLEVEL) timer_start(&ti);
+  s = heegner_psi(E, N, points, bitprec);
+  if (DEBUGLEVEL) timer_printf(&ti,"heegner_psi");
   l = lg(points);
   z = mulsr(coefs[1], gel(s, 1));
   for (k = 2; k < l; ++k) z = addrr(z, mulsr(coefs[k], gel(s, k)));
@@ -1337,7 +1337,7 @@ ellheegner(GEN E)
   z = gsub(z, gmul(gel(om,1), ground(gdiv(z, gel(om,1)))));
   lint = wtor > 1 ? cgcd(ind, etor): 1;
   P = heegner_find_point(E, om, ht, gmulsg(2*lint, z), lint*2*ind, prec);
-  if (DEBUGLEVEL) timer_printf(&T,"heegner_find_point");
+  if (DEBUGLEVEL) timer_printf(&ti,"heegner_find_point");
   if (cb) P = ellchangepointinv(P, cb);
   return gerepilecopy(av, P);
 }
diff --git a/src/basemath/elliptic.c b/src/basemath/elliptic.c
index c68f47f..65a741d 100644
--- a/src/basemath/elliptic.c
+++ b/src/basemath/elliptic.c
@@ -25,16 +25,22 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
    The third entry is a vector describing the isomorphism E' \to E.
 */
 
+static ulong
+Fl_c4_to_a4(ulong c4, ulong p)
+{ return Fl_neg(Fl_mul(c4, 27, p), p); }
 static void
 Fl_c4c6_to_a4a6(ulong c4, ulong c6, ulong p, ulong *a4, ulong *a6)
 {
-  *a4 = Fl_neg(Fl_mul(c4, 27, p), p);
+  *a4 = Fl_c4_to_a4(c4, p);
   *a6 = Fl_neg(Fl_mul(c6, 54, p), p);
 }
+static GEN
+c4_to_a4(GEN c4, GEN p)
+{ return Fp_neg(Fp_mulu(c4, 27, p), p); }
 static void
 c4c6_to_a4a6(GEN c4, GEN c6, GEN p, GEN *a4, GEN *a6)
 {
-  *a4 = Fp_neg(Fp_mulu(c4, 27, p), p);
+  *a4 = c4_to_a4(c4, p);
   *a6 = Fp_neg(Fp_mulu(c6, 54, p), p);
 }
 static void
@@ -52,18 +58,44 @@ Fl_ell_to_a4a6(GEN E, ulong p, ulong *a4, ulong *a6)
   Fl_c4c6_to_a4a6(c4, c6, p, a4, a6);
 }
 
+/* [6,3b2,3a1,108a3] */
+static GEN
+a4a6_ch(GEN E, GEN p)
+{
+  GEN a1 = Rg_to_Fp(ell_get_a1(E),p);
+  GEN a3 = Rg_to_Fp(ell_get_a3(E),p);
+  GEN b2 = Rg_to_Fp(ell_get_b2(E),p);
+  retmkvec4(modsi(6,p),Fp_mulu(b2,3,p),Fp_mulu(a1,3,p),Fp_mulu(a3,108,p));
+}
+static GEN
+a4a6_ch_Fl(GEN E, ulong p)
+{
+  ulong a1 = Rg_to_Fl(ell_get_a1(E),p);
+  ulong a3 = Rg_to_Fl(ell_get_a3(E),p);
+  ulong b2 = Rg_to_Fl(ell_get_b2(E),p);
+  return mkvecsmall4(6 % p,Fl_mul(b2,3,p),Fl_mul(a1,3,p),Fl_mul(a3,108,p));
+}
+
 static GEN
 ell_to_a4a6_bc(GEN E, GEN p)
 {
-  GEN a1, a3, b2, c4, c6;
-  a1 = Rg_to_Fp(ell_get_a1(E),p);
-  a3 = Rg_to_Fp(ell_get_a3(E),p);
-  b2 = Rg_to_Fp(ell_get_b2(E),p);
-  c4 = Rg_to_Fp(ell_get_c4(E),p);
-  c6 = Rg_to_Fp(ell_get_c6(E),p);
-  /* [-27c4, -54c6, [6,3b2,3a1,108a3]] */
-  retmkvec3(Fp_neg(Fp_mulu(c4, 27, p), p), Fp_neg(Fp_mulu(c6, 54, p), p),
-            mkvec4(modsi(6,p),Fp_mulu(b2,3,p),Fp_mulu(a1,3,p),Fp_mulu(a3,108,p)));
+  GEN A4, A6;
+  ell_to_a4a6(E, p, &A4, &A6);
+  retmkvec3(A4, A6, a4a6_ch(E,p));
+}
+GEN
+point_to_a4a6(GEN E, GEN P, GEN p, GEN *pa4)
+{
+  GEN c4 = Rg_to_Fp(ell_get_c4(E),p);
+  *pa4 = c4_to_a4(c4, p);
+  return FpE_changepointinv(RgV_to_FpV(P,p), a4a6_ch(E,p), p);
+}
+GEN
+point_to_a4a6_Fl(GEN E, GEN P, ulong p, ulong *pa4)
+{
+  ulong c4 = Rg_to_Fl(ell_get_c4(E),p);
+  *pa4 = Fl_c4_to_a4(c4, p);
+  return Fle_changepointinv(RgC_to_Flc(P,p), a4a6_ch_Fl(E,p), p);
 }
 
 void
@@ -87,6 +119,9 @@ checkell5(GEN E)
 void
 checkell(GEN E)
 { if (typ(E)!=t_VEC || lg(E) != 17) pari_err_TYPE("checkell",E); }
+void
+checkellisog(GEN v)
+{ if (typ(v)!=t_VEC || lg(v) != 4) pari_err_TYPE("checkellisog",v); }
 
 void
 checkell_Q(GEN E)
@@ -123,7 +158,7 @@ ellff_get_p(GEN E)
   return typ(fg)==t_INT? fg: FF_p_i(fg);
 }
 
-static int
+int
 ell_is_integral(GEN E)
 {
   return typ(ell_get_a1(E)) == t_INT
@@ -133,83 +168,170 @@ ell_is_integral(GEN E)
       && typ(ell_get_a6(E)) == t_INT;
 }
 
-
 static void
 checkcoordch(GEN z)
 { if (typ(z)!=t_VEC || lg(z) != 5) pari_err_TYPE("checkcoordch",z); }
 
-/* 4 X^3 + b2 X^2 + 2b4 X + b6, N is the characteristic of the base
- * ring of NULL (char = 0) */
-static GEN
-RHSpol(GEN e, GEN N)
+/* 4 X^3 + b2 X^2 + 2b4 X + b6 */
+GEN
+ec_bmodel(GEN e)
 {
   GEN b2 = ell_get_b2(e), b6 = ell_get_b6(e), b42 = gmul2n(ell_get_b4(e),1);
-  return mkpoln(4, N? modsi(4,N): utoipos(4), b2, b42, b6);
+  return mkpoln(4, utoipos(4), b2, b42, b6);
 }
 
 static int
 invcmp(void *E, GEN x, GEN y) { (void)E; return -gcmp(x,y); }
 
 static GEN
-doellR_roots(GEN e, long prec)
+doellR_roots(GEN e, long prec0)
 {
-  GEN R = roots(RHSpol(e,NULL), prec);
-  long s = ellR_get_sign(e);
+  GEN R, d1, d2, d3, e1, e2, e3;
+  long s = ellR_get_sign(e), prec = prec0;
+START:
+  R = roots(ec_bmodel(e), prec);
   if (s > 0)
   { /* sort 3 real roots in decreasing order */
     R = real_i(R);
     gen_sort_inplace(R, NULL, &invcmp, NULL);
-  } else if (s < 0)
-  { /* make sure e1 is real, imag(e2) > 0 and imag(e3) < 0 */
-    gel(R,1) = real_i(gel(R,1));
-    if (signe(gmael(R,2,2)) < 0) swap(gel(R,2), gel(R,3));
+    e1 = gel(R,1);
+    e2 = gel(R,2);
+    e3 = gel(R,3);
+    d3 = subrr(e1,e2);
+    d1 = subrr(e2,e3);
+    d2 = subrr(e1,e3);
+    if (realprec(d3) < prec0 || realprec(d1) < prec0)
+    {
+      prec = precdbl(prec);
+      if (DEBUGLEVEL) pari_warn(warnprec,"doellR_roots", prec);
+      goto START;
+    }
+  } else {
+    e1 = gel(R,1);
+    e2 = gel(R,2);
+    e3 = gel(R,3);
+    if (s < 0)
+    { /* make sure e1 is real, imag(e2) > 0 and imag(e3) < 0 */
+      e1 = real_i(e1);
+      if (signe(gel(e2,2)) < 0) swap(e2, e3);
+    }
+    d3 = gsub(e1,e2);
+    d1 = gsub(e2,e3);
+    d2 = gsub(e1,e3);
   }
-  return R;
+  return mkcol6(e1,e2,e3,d1,d2,d3);
 }
 static GEN
 ellR_root(GEN e, long prec) { return gel(ellR_roots(e,prec),1); }
 
-/* x^3 + a2 x^2 + a4 x + a6 */
-static GEN
-ellRHS(GEN e, GEN x)
+/* Given E and the x-coordinate of a point Q = [xQ, yQ], return
+ *   f(xQ) = xQ^3 + E.a2 * xQ^2 + E.a4 * xQ + E.a6
+ * where E is given by y^2 + h(x)y = f(x). */
+GEN
+ec_f_evalx(GEN E, GEN x)
 {
+  pari_sp av = avma;
   GEN z;
-  z = gadd(ell_get_a2(e),x);
-  z = gadd(ell_get_a4(e), gmul(x,z));
-  z = gadd(ell_get_a6(e), gmul(x,z));
-  return z;
+  z = gadd(ell_get_a2(E),x);
+  z = gadd(ell_get_a4(E), gmul(x,z));
+  z = gadd(ell_get_a6(E), gmul(x,z));
+  return gerepileupto(av, z); /* ((x + E.a2) * x + E.a4) * x + E.a6 */
 }
 
 /* a1 x + a3 */
-static GEN
-ellLHS0(GEN e, GEN x)
+GEN
+ec_h_evalx(GEN e, GEN x)
 {
   GEN a1 = ell_get_a1(e);
   GEN a3 = ell_get_a3(e);
-  return gequal0(a1)? a3: gadd(a3, gmul(x,a1));
+  return gadd(a3, gmul(x,a1));
 }
-
 static GEN
-ellLHS0_i(GEN e, GEN x)
+Zec_h_evalx(GEN e, GEN x)
 {
   GEN a1 = ell_get_a1(e);
   GEN a3 = ell_get_a3(e);
   return signe(a1)? addii(a3, mulii(x, a1)): a3;
 }
-
-/* y^2 + a1 xy + a3 y */
+/* y^2 + a1 xy + a3 y = y^2 + h(x)y */
 static GEN
-ellLHS(GEN e, GEN z)
+ec_LHS_evalQ(GEN e, GEN Q)
 {
-  GEN y = gel(z,2);
-  return gmul(y, gadd(y, ellLHS0(e,gel(z,1))));
+  GEN x = gel(Q,1), y = gel(Q,2);
+  return gmul(y, gadd(y, ec_h_evalx(e,x)));
 }
 
-/* 2y + a1 x + a3 */
-static GEN
-d_ellLHS(GEN e, GEN z)
+/* Given E and a point Q = [xQ, yQ], return
+ *   3 * xQ^2 + 2 * E.a2 * xQ + E.a4 - E.a1 * yQ.
+ * which is the derivative of the curve equation
+ *   f(x) - (y^2 + h(x)y) = 0
+ * wrt x evaluated at Q */
+GEN
+ec_dFdx_evalQ(GEN E, GEN Q)
+{
+  pari_sp av = avma;
+  GEN x = gel(Q,1), y = gel(Q,2);
+  GEN a1 = ell_get_a1(E);
+  GEN a2 = ell_get_a2(E);
+  GEN a4 = ell_get_a4(E);
+  GEN tmp = gmul(gadd(gmulsg(3L,x), gmul2n(a2,1)), x);
+  return gerepileupto(av, gadd(tmp, gsub(a4, gmul(a1, y))));
+}
+
+/* 2y + a1 x + a3 = -ec_dFdy_evalQ */
+GEN
+ec_dmFdy_evalQ(GEN e, GEN Q)
+{
+  GEN x = gel(Q,1), y = gel(Q,2);
+  return gadd(ec_h_evalx(e,x), gmul2n(y,1));
+}
+/* Given E and a point Q = [xQ, yQ], return
+ *  -(2 * yQ + E.a1 * xQ + E.a3)
+ * which is the derivative of the curve equation
+ *  f(x) - (y^2 + h(x)y) = 0
+ * wrt y evaluated at Q */
+GEN
+ec_dFdy_evalQ(GEN E, GEN Q)
+{
+  pari_sp av = avma;
+  return gerepileupto(av, gneg(ec_dmFdy_evalQ(E,Q)));
+}
+
+/* Given E and a point Q = [xQ, yQ], return
+ *   4 xQ^3 + E.b2 xQ^2 + 2 E.b4 xQ + E.b6
+ * which is the 2-division polynomial of E evaluated at Q */
+GEN
+ec_2divpol_evalx(GEN E, GEN x)
+{
+  pari_sp av = avma;
+  GEN b2 = ell_get_b2(E);
+  GEN b4 = ell_get_b4(E);
+  GEN b6 = ell_get_b6(E);
+  GEN t1 = gmul(gadd(gmulsg(4L, x), b2), x);
+  GEN t2 = gadd(t1, gmulsg(2L, b4));
+  return gerepileupto(av, gadd(gmul(t2, x), b6));
+}
+
+/* Given E and a point Q = [xQ, yQ], return
+ *   6 xQ^2 + E.b2 xQ + E.b4
+ * which, if f is the curve equation, is 2 dfdx - E.a1 dfdy evaluated at Q */
+GEN
+ec_half_deriv_2divpol_evalx(GEN E, GEN x)
 {
-  return gadd(ellLHS0(e, gel(z,1)), gmul2n(gel(z,2),1));
+  pari_sp av = avma;
+  GEN b2 = ell_get_b2(E);
+  GEN b4 = ell_get_b4(E);
+  GEN res = gadd(gmul(gadd(gmulsg(6L, x), b2), x), b4);
+  return gerepileupto(av, res);
+}
+
+/* Return the characteristic of the ring over which E is defined. */
+GEN
+ellbasechar(GEN E)
+{
+  pari_sp av = avma;
+  GEN D = ell_get_disc(E);
+  return gerepileuptoint(av, characteristic(D));
 }
 
 /* return basic elliptic struct y[1..13], y[14] (domain type) and y[15]
@@ -318,7 +440,7 @@ ellprint(GEN e)
   checkell5(e);
   vx = fetch_var(); name_var(vx, "X");
   vy = fetch_var(); name_var(vy, "Y"); z = mkvec2(pol_x(vx), pol_x(vy));
-  err_printf("%Ps - (%Ps)\n", ellLHS(e, z), ellRHS(e, pol_x(vx)));
+  err_printf("%Ps - (%Ps)\n", ec_LHS_evalQ(e, z), ec_f_evalx(e, pol_x(vx)));
   (void)delete_var();
   (void)delete_var(); avma = av;
 }
@@ -327,20 +449,22 @@ ellprint(GEN e)
 static GEN
 doellR_ab(GEN E, long prec)
 {
-  GEN b2 = ell_get_b2(E), b4 = ell_get_b4(E), e1 = ellR_root(E, prec);
-  GEN a, b, t, w;
+  GEN b2 = ell_get_b2(E), R = ellR_roots(E, prec);
+  GEN e1 = gel(R,1), d2 = gel(R,5), d3 =  gel(R,6), a, b, t;
 
-  t = gmul2n(gadd(gmulsg(12,e1), b2), -2); /* = (12 e1 + b2) / 4 */
-  w = sqrtr( gmul2n(gadd(b4, gmul(e1,gadd(b2, mulur(6,e1)))),1) );
-  if (gsigne(t) > 0) setsigne(w, -1);
-  /* w^2 = 2b4 + 2b2 e1 + 12 e1^2 = 4(e1-e2)(e1-e3) */
-  a = gmul2n(gsub(w,t),-2);
-  b = gmul2n(w,-1); /* = sqrt( (e1 - e2)(e1 - e3) ) */
+  t = gmul2n(gadd(mulur(12,e1), b2), -4); /* = (12 e1 + b2) / 16 */
+  if (ellR_get_sign(E) > 0)
+    b = mulrr(d3,d2);
+  else
+    b = cxnorm(d3);
+  b = sqrtr(b); /* = sqrt( (e1 - e2)(e1 - e3) ) */
+  if (gsigne(t) > 0) togglesign(b);
+  a = gsub(gmul2n(b,-1),t);
   return mkvec2(a, b);
 }
 GEN
 ellR_ab(GEN E, long prec)
-{ return obj_checkbuild_prec(E, R_AB, &doellR_ab, prec); }
+{ return obj_checkbuild_realprec(E, R_AB, &doellR_ab, prec); }
 
 /* return x mod p */
 static GEN
@@ -387,6 +511,17 @@ static void
 chk_p(GEN p, GEN p2)
 { if (!equalii(p, p2)) pari_err_MODULUS("ellinit", p,p2); }
 
+static int
+fix_nftype(GEN *pp)
+{
+  switch(nftyp(*pp))
+  {
+    case typ_NF: case typ_BNF: break;
+    case typ_BNR:*pp = bnr_get_bnf(*pp); break;
+    default: return 0;
+  }
+  return 1;
+}
 static long
 base_ring(GEN x, GEN *pp, long *prec)
 {
@@ -414,11 +549,15 @@ base_ring(GEN x, GEN *pp, long *prec)
     case t_FFELT:
       p = *pp;
       break;
+    case t_VEC:
+      t = t_VEC; p = *pp;
+      if (fix_nftype(&p)) break;
     default:
       pari_err_TYPE("elliptic curve base_ring", *pp);
       return 0;
   }
   /* Possible cases:
+   * t = t_VEC (p an nf or bnf)
    * t = t_FFELT (p t_FFELT)
    * t = t_INTMOD (p a prime)
    * t = t_PADIC (p a prime, e = padic prec)
@@ -469,6 +608,10 @@ base_ring(GEN x, GEN *pp, long *prec)
           default: pari_err_TYPE("elliptic curve base_ring", x);
         }
         break;
+      case t_COL:
+      case t_POL:
+      case t_POLMOD:
+        if (t == t_VEC) break;
       default: /* base ring too general */
         return t_COMPLEX;
     }
@@ -479,95 +622,144 @@ base_ring(GEN x, GEN *pp, long *prec)
 static GEN
 ellinit_Rg(GEN x, int real, long prec)
 {
-  pari_sp av=avma;
   GEN y;
   long s;
   if (!(y = initsmall(x, 4))) return NULL;
   s = real? gsigne( ell_get_disc(y) ): 0;
   gel(y,14) = mkvecsmall(t_ELL_Rg);
   gel(y,15) = mkvec(mkvecsmall2(prec2nbits(prec), s));
-  return gerepilecopy(av, y);
+  return y;
 }
 
 static GEN
 ellinit_Qp(GEN x, GEN p, long prec)
 {
-  pari_sp av=avma;
   GEN y;
   if (lg(x) > 6) x = vecslice(x,1,5);
   x = QpV_to_QV(x); /* make entries rational */
   if (!(y = initsmall(x, 2))) return NULL;
   gel(y,14) = mkvecsmall(t_ELL_Qp);
   gel(y,15) = mkvec(zeropadic(p, prec));
-  return gerepilecopy(av, y);
+  return y;
 }
 
 static GEN
 ellinit_Q(GEN x, long prec)
 {
-  pari_sp av=avma;
   GEN y;
   long s;
   if (!(y = initsmall(x, 8))) return NULL;
   s = gsigne( ell_get_disc(y) );
   gel(y,14) = mkvecsmall(t_ELL_Q);
   gel(y,15) = mkvec(mkvecsmall2(prec2nbits(prec), s));
-  return gerepilecopy(av, y);
+  return y;
+}
+
+/* shallow basistoalg */
+static GEN
+nftoalg(GEN nf, GEN x)
+{
+  switch(typ(x))
+  {
+    case t_INT: case t_FRAC: case t_POLMOD: return x;
+    default: return basistoalg(nf, x);
+  }
+}
+static GEN
+nfVtoalg(GEN nf, GEN x)
+{
+  long i, l;
+  GEN y = cgetg_copy(x,&l);
+  for (i=1; i<l; i++) gel(y,i) = nftoalg(nf,gel(x,i));
+  return y;
+}
+
+static GEN
+ellinit_nf(GEN x, GEN p)
+{
+  GEN y;
+  if (lg(x) > 6) x = vecslice(x,1,5);
+  x = nfVtoalg(p, x);
+  if (!(y = initsmall(x, 1))) return NULL;
+  gel(y,14) = mkvecsmall(t_ELL_NF);
+  gel(y,15) = mkvec(p);
+  return y;
 }
 
 static GEN
 ellinit_Fp(GEN x, GEN p)
 {
-  pari_sp av=avma;
   long i;
   GEN y, disc;
   if (!(y = initsmall(x, 4))) return NULL;
   if (cmpiu(p,3)<=0) /* ell_to_a4a6_bc does not handle p<=3 */
-  {
-    y = FF_ellinit(y,p_to_FF(p,0));
-    if (!y) return NULL;
-    return gerepilecopy(av, y);
-  }
+    return FF_ellinit(y,p_to_FF(p,0));
   disc = Rg_to_Fp(ell_get_disc(y),p);
   if (!signe(disc)) return NULL;
   for(i=1;i<=13;i++)
     gel(y,i) = Fp_to_mod(Rg_to_Fp(gel(y,i),p),p);
   gel(y,14) = mkvecsmall(t_ELL_Fp);
   gel(y,15) = mkvec2(p, ell_to_a4a6_bc(y, p));
-  return gerepilecopy(av, y);
+  return y;
 }
 
 static GEN
 ellinit_Fq(GEN x, GEN fg)
 {
-  pari_sp av=avma;
   GEN y;
   if (!(y = initsmall(x, 4))) return NULL;
-  y = FF_ellinit(y,fg);
-  return y ? gerepilecopy(av, y): NULL;
+  return FF_ellinit(y,fg);
 }
 
+static GEN
+ellinit_nf_to_Fq(GEN x, GEN P)
+{
+  GEN nf = ellnf_get_nf(x), e = vecslice(x,1,5);
+  GEN T,p, modP;
+  if (get_modpr(P))
+  { /* modpr accept */
+    modP = P;
+    p = modpr_get_p(modP);
+  }
+  else
+  { /* pr, initialize modpr */
+    GEN d = Q_denom(e);
+    p = pr_get_p(P);
+    modP = dvdii(d,p)? nfmodprinit(nf,P): zkmodprinit(nf,P);
+  }
+  T = modpr_get_T(modP);
+  e = nfV_to_FqV(e, nf, modP);
+  return T? ellinit_Fq(e,Tp_to_FF(T,p)): ellinit_Fp(e,p);
+}
 GEN
-ellinit(GEN x, GEN p, long prec)
+ellinit(GEN x, GEN D, long prec)
 {
   pari_sp av = avma;
   GEN y;
   switch(typ(x))
   {
     case t_STR: x = gel(ellsearchcurve(x),2); break;
-    case t_VEC: break;
+    case t_VEC:
+      if (lg(x) > 6) checkell(x);
+      break;
     default: pari_err_TYPE("ellxxx [not an elliptic curve (ell5)]",x);
   }
-  switch (base_ring(x, &p, &prec))
+  if (D && get_prid(D))
+  {
+    if (ell_get_type(x) != t_ELL_NF) pari_err_TYPE("ellinit",x);
+    y = ellinit_nf_to_Fq(x, D);
+    goto END;
+  }
+  switch (base_ring(x, &D, &prec))
   {
   case t_PADIC:
-    y = ellinit_Qp(x, p, prec);
+    y = ellinit_Qp(x, D, prec);
     break;
   case t_INTMOD:
-    y = ellinit_Fp(x, p);
+    y = ellinit_Fp(x, D);
     break;
   case t_FFELT:
-    y = ellinit_Fq(x, p);
+    y = ellinit_Fq(x, D);
     break;
   case t_FRAC:
     y = ellinit_Q(x, prec);
@@ -575,11 +767,15 @@ ellinit(GEN x, GEN p, long prec)
   case t_REAL:
     y = ellinit_Rg(x, 1, prec);
     break;
+  case t_VEC:
+    y = ellinit_nf(x, D);
+    break;
   default:
     y = ellinit_Rg(x, 0, prec);
   }
+END:
   if (!y) { avma = av; return cgetg(1,t_VEC); }
-  return y;
+  return gerepilecopy(av,y);
 }
 
 /********************************************************************/
@@ -782,11 +978,11 @@ coordch_r(GEN e, GEN r)
   /* A2 = a2 + 3r */
   gel(y,2) = gadd(a2,rx3);
   /* A3 = a1 r + a3 */
-  gel(y,3) = ellLHS0(e,r);
+  gel(y,3) = ec_h_evalx(e,r);
   /* A4 = 3r^2 + 2a2 r + a4 */
   gel(y,4) = gadd(ell_get_a4(e), gmul(r,gadd(gmul2n(a2,1),rx3)));
   /* A6 = r^3 + a2 r^2 + a4 r + a6 */
-  gel(y,5) = ellRHS(e,r);
+  gel(y,5) = ec_f_evalx(e,r);
   if (lg(y) == 6) return y;
 
   b4 = ell_get_b4(e);
@@ -1040,16 +1236,6 @@ static void
 E_compose_rst(GEN *vtotal, GEN *e, GEN r, GEN s, GEN t)
 { *e=coordch_rst(*e,r,s,t); composev_rst(vtotal,r,s,t); }
 
-/* apply [1,r,0,0] to P */
-static GEN
-ellchangepoint_r(GEN P, GEN r)
-{
-  GEN x, y, a;
-  if (ell_is_inf(P)) return P;
-  x = gel(P,1); y = gel(P,2); a = gsub(x,r);
-  return mkvec2(a, y);
-}
-
 /* X = (x-r)/u^2
  * Y = (y - s(x-r) - t) / u^3 */
 static GEN
@@ -1145,9 +1331,10 @@ oncurve(GEN e, GEN z)
   pari_sp av;
 
   checkellpt(z); if (ell_is_inf(z)) return 1; /* oo */
+  if (ell_get_type(e) == t_ELL_NF) z = nfVtoalg(ellnf_get_nf(e), z);
   av = avma;
-  LHS = ellLHS(e,z);
-  RHS = ellRHS(e,gel(z,1)); x = gsub(LHS,RHS);
+  LHS = ec_LHS_evalQ(e,z);
+  RHS = ec_f_evalx(e,gel(z,1)); x = gsub(LHS,RHS);
   if (gequal0(x)) { avma = av; return 1; }
   pl = precision(LHS);
   pr = precision(RHS);
@@ -1166,7 +1353,7 @@ ellisoncurve(GEN e, GEN x)
 {
   long i, tx = typ(x), lx;
 
-  checkell5(e);
+  checkell(e);
   if (!is_vec_t(tx)) pari_err_TYPE("ellisoncurve [point]", x);
   lx = lg(x); if (lx==1) return cgetg(1,tx);
   tx = typ(gel(x,1));
@@ -1185,24 +1372,32 @@ elladd(GEN e, GEN z1, GEN z2)
   GEN p1, p2, x, y, x1, x2, y1, y2;
   pari_sp av = avma, tetpil;
 
-  checkell5(e); checkellpt(z1); checkellpt(z2);
+  checkell(e); checkellpt(z1); checkellpt(z2);
   if (ell_is_inf(z1)) return gcopy(z2);
   if (ell_is_inf(z2)) return gcopy(z1);
 
   x1 = gel(z1,1); y1 = gel(z1,2);
   x2 = gel(z2,1); y2 = gel(z2,2);
+  if (ell_get_type(e) == t_ELL_NF)
+  {
+    GEN nf = ellnf_get_nf(e);
+    x1 = nftoalg(nf, x1);
+    x2 = nftoalg(nf, x2);
+    y1 = nftoalg(nf, y1);
+    y2 = nftoalg(nf, y2);
+  }
   if (x1 == x2 || gequal(x1,x2))
   { /* y1 = y2 or -LHS0-y2 */
     if (y1 != y2)
     {
       int eq;
       if (precision(y1) || precision(y2))
-        eq = (gexpo(gadd(ellLHS0(e,x1),gadd(y1,y2))) >= gexpo(y1));
+        eq = (gexpo(gadd(ec_h_evalx(e,x1),gadd(y1,y2))) >= gexpo(y1));
       else
         eq = gequal(y1,y2);
       if (!eq) { avma = av; return ellinf(); }
     }
-    p2 = d_ellLHS(e,z1);
+    p2 = ec_dmFdy_evalQ(e,z1);
     if (gequal0(p2)) { avma = av; return ellinf(); }
     p1 = gadd(gsub(ell_get_a4(e),gmul(ell_get_a1(e),y1)),
               gmul(x1,gadd(gmul2n(ell_get_a2(e),1),gmulsg(3,x1))));
@@ -1213,7 +1408,7 @@ elladd(GEN e, GEN z1, GEN z2)
   }
   p1 = gdiv(p1,p2);
   x = gsub(gmul(p1,gadd(p1,ell_get_a1(e))), gadd(gadd(x1,x2),ell_get_a2(e)));
-  y = gadd(gadd(y1, ellLHS0(e,x)), gmul(p1,gsub(x,x1)));
+  y = gadd(gadd(y1, ec_h_evalx(e,x)), gmul(p1,gsub(x,x1)));
   tetpil = avma; p1 = cgetg(3,t_VEC);
   gel(p1,1) = gcopy(x);
   gel(p1,2) = gneg(y); return gerepile(av,tetpil,p1);
@@ -1222,11 +1417,19 @@ elladd(GEN e, GEN z1, GEN z2)
 static GEN
 ellneg_i(GEN e, GEN z)
 {
-  GEN t;
+  GEN t, x, y;
   if (ell_is_inf(z)) return z;
+  x = gel(z,1);
+  y = gel(z,2);
+  if (ell_get_type(e) == t_ELL_NF)
+  {
+    GEN nf = ellnf_get_nf(e);
+    x = nftoalg(nf,x);
+    y = nftoalg(nf,y);
+  }
   t = cgetg(3,t_VEC);
-  gel(t,1) = gel(z,1);
-  gel(t,2) = gneg_i(gadd(gel(z,2), ellLHS0(e,gel(z,1))));
+  gel(t,1) = x;
+  gel(t,2) = gneg_i(gadd(y, ec_h_evalx(e,x)));
   return t;
 }
 
@@ -1235,12 +1438,12 @@ ellneg(GEN e, GEN z)
 {
   pari_sp av;
   GEN t, y;
-  checkell5(e); checkellpt(z);
+  checkell(e); checkellpt(z);
   if (ell_is_inf(z)) return z;
   t = cgetg(3,t_VEC);
   gel(t,1) = gcopy(gel(z,1));
   av = avma;
-  y = gneg(gadd(gel(z,2), ellLHS0(e,gel(z,1))));
+  y = gneg(gadd(gel(z,2), ec_h_evalx(e,gel(z,1))));
   gel(t,2) = gerepileupto(av, y);
   return t;
 }
@@ -1249,7 +1452,7 @@ GEN
 ellsub(GEN e, GEN z1, GEN z2)
 {
   pari_sp av = avma;
-  checkell5(e); checkellpt(z2);
+  checkell(e); checkellpt(z2);
   return gerepileupto(av, elladd(e, z1, ellneg_i(e,z2)));
 }
 
@@ -1258,9 +1461,16 @@ static GEN
 ellordinate_i(GEN E, GEN x, long prec)
 {
   pari_sp av = avma;
-  GEN a = ellRHS(E,x), b = ellLHS0(E,x), D = gadd(gsqr(b), gmul2n(a,2));
-  GEN d, y, p;
+  GEN a, b, D, d, y, p, nf = NULL;
 
+  if (ell_get_type(E) == t_ELL_NF)
+  {
+    nf = ellnf_get_nf(E);
+    x = nftoalg(nf,x);
+  }
+  a = ec_f_evalx(E,x);
+  b = ec_h_evalx(E,x);
+  D = gadd(gsqr(b), gmul2n(a,2));
   /* solve y*(y+b) = a */
   if (gequal0(D)) {
     if (ell_get_type(E) == t_ELL_Fq && equaliu(ellff_get_p(E),2))
@@ -1292,6 +1502,17 @@ ellordinate_i(GEN E, GEN x, long prec)
       if (!issquareall(D,&d)) { avma = av; return cgetg(1,t_VEC); }
       break;
 
+    case t_ELL_NF:
+    {
+      GEN T = mkpoln(3, gen_1, gen_0, gneg(D));
+      setvarn(T, fetch_var_higher());
+      d = nfroots(nf, T);
+      delete_var();
+      if (lg(d) == 1) { avma = av; return cgetg(1, t_VEC); }
+      d = gel(d,1);
+      break;
+    }
+
     case t_ELL_Qp:
       p = ellQp_get_p(E);
       D = cvtop(D, p, ellQp_get_prec(E));
@@ -1388,7 +1609,7 @@ ellmul_CM(GEN e, GEN z, GEN n)
   x = gdiv(p1,q1);
   y = gdiv(gsub(gmul(p1p,q1), gmul(p1,q1p)), gmul(n,gsqr(q1)));
   x = gsub(x, b2ov12);
-  y = gsub( gmul(d_ellLHS(e,z), y), ellLHS0(e,x));
+  y = gsub( gmul(ec_dmFdy_evalQ(e,z), y), ec_h_evalx(e,x));
   return mkvec2(x, gmul2n(y,-1));
 }
 
@@ -1419,7 +1640,7 @@ ellmul_Z(GEN e, GEN z, GEN n)
 {
   long s;
   if (ell_is_inf(z)) return ellinf();
-  if (lg(e)==17 && ell_over_Fq(e)) return ellffmul(e,z,n);
+  if (ell_over_Fq(e)) return ellffmul(e,z,n);
   s = signe(n);
   if (!s) return ellinf();
   if (s < 0) z = ellneg_i(e,z);
@@ -1510,8 +1731,7 @@ static GEN
 ellmul_CM_aux(GEN e, GEN z, GEN a, GEN w)
 {
   GEN A, B, q;
-  checkell(e);
-  if (typ(a) != t_INT) pari_err_TYPE("ellmul_CM",a);
+  if (typ(a) != t_INT) pari_err_TYPE("ellmul_Z",a);
   q = CM_factor(e, w);
   if (!q) pari_err_TYPE("ellmul [not a complex multiplication]",w);
   if (q != gen_1) w = gdiv(w, q);
@@ -1539,7 +1759,7 @@ ellmul(GEN e, GEN z, GEN n)
 {
   pari_sp av = avma;
 
-  checkell5(e); checkellpt(z);
+  checkell(e); checkellpt(z);
   if (ell_is_inf(z)) return ellinf();
   switch(typ(n))
   {
@@ -1582,10 +1802,8 @@ ellomega_cx(GEN E, long prec)
 {
   pari_sp av = avma;
   GEN roots = ellR_roots(E,prec);
-  GEN e1=gel(roots,1), e2=gel(roots,2), e3=gel(roots,3);
-  GEN a = gsqrt(gsub(e1,e2),prec);
-  GEN b = gsqrt(gsub(e2,e3),prec);
-  GEN c = gsqrt(gsub(e1,e3),prec);
+  GEN d1=gel(roots,4), d2=gel(roots,5), d3=gel(roots,6);
+  GEN a = gsqrt(d3,prec), b = gsqrt(d1,prec), c = gsqrt(d2,prec);
   return gerepileupto(av, ellomega_agm(a,b,c,prec));
 }
 
@@ -1596,12 +1814,11 @@ static GEN
 doellR_omega(GEN E, long prec)
 {
   pari_sp av = avma;
-  GEN roots, e1, e3, z, a, b, c;
+  GEN roots, d2, z, a, b, c;
   if (ellR_get_sign(E) >= 0) return ellomega_cx(E,prec);
   roots = ellR_roots(E,prec);
-  e1 = gel(roots,1);
-  e3 = gel(roots,3);
-  z = gsqrt(gsub(e1,e3),prec); /* imag(e1-e3) > 0, so that b > 0*/
+  d2 = gel(roots,5);
+  z = gsqrt(d2,prec); /* imag(e1-e3) > 0, so that b > 0*/
   a = gel(z,1); /* >= 0 */
   b = gel(z,2);
   c = gabs(z, prec);
@@ -1614,13 +1831,13 @@ doellR_eta(GEN E, long prec)
 
 GEN
 ellR_omega(GEN E, long prec)
-{ return obj_checkbuild_prec(E, R_PERIODS, &doellR_omega, prec); }
+{ return obj_checkbuild_realprec(E, R_PERIODS, &doellR_omega, prec); }
 GEN
 ellR_eta(GEN E, long prec)
-{ return obj_checkbuild_prec(E, R_ETA, &doellR_eta, prec); }
+{ return obj_checkbuild_realprec(E, R_ETA, &doellR_eta, prec); }
 GEN
 ellR_roots(GEN E, long prec)
-{ return obj_checkbuild_prec(E, R_ROOTS, &doellR_roots, prec); }
+{ return obj_checkbuild_realprec(E, R_ROOTS, &doellR_roots, prec); }
 
 /********************************************************************/
 /**                                                                **/
@@ -1647,14 +1864,14 @@ zell_closest_0(GEN om, GEN x, GEN ro)
 static GEN
 zellcx(GEN E, GEN P, long prec)
 {
-  GEN roots = ellR_roots(E, prec+EXTRAPRECWORD);
-  GEN x0 = gel(P,1), y0 = d_ellLHS(E,P);
+  GEN R = ellR_roots(E, prec+EXTRAPRECWORD);
+  GEN x0 = gel(P,1), y0 = ec_dmFdy_evalQ(E,P);
   if (gequal0(y0))
-    return zell_closest_0(ellomega_cx(E,prec),x0,roots);
+    return zell_closest_0(ellomega_cx(E,prec),x0,R);
   else
   {
-    GEN e1 = gel(roots,1), e2 = gel(roots,2), e3 = gel(roots,3);
-    GEN a = gsqrt(gsub(e1,e3),prec), b = gsqrt(gsub(e1,e2),prec);
+    GEN e2 = gel(R,2), e3 = gel(R,3), d2 = gel(R,5), d3 = gel(R,6);
+    GEN a = gsqrt(d2,prec), b = gsqrt(d3,prec);
     GEN r = gsqrt(gdiv(gsub(x0,e3), gsub(x0,e2)),prec);
     GEN t = gdiv(gneg(y0), gmul2n(gmul(r,gsub(x0,e2)),1));
     GEN ar = real_i(a), br = real_i(b), ai = imag_i(a), bi = imag_i(b);
@@ -1668,13 +1885,13 @@ zellcx(GEN E, GEN P, long prec)
 static GEN
 zellrealneg(GEN E, GEN P, long prec)
 {
-  GEN x0 = gel(P,1), y0 = d_ellLHS(E,P);
+  GEN x0 = gel(P,1), y0 = ec_dmFdy_evalQ(E,P);
   if (gequal0(y0)) return gmul2n(gel(ellR_omega(E,prec),1),-1);
   else
   {
-    GEN roots = ellR_roots(E, prec+EXTRAPRECWORD);
-    GEN e1 = gel(roots,1), e3 = gel(roots,3);
-    GEN a = gsqrt(gsub(e1,e3),prec);
+    GEN R = ellR_roots(E, prec+EXTRAPRECWORD);
+    GEN d2 = gel(R,5), e3 = gel(R,3);
+    GEN a = gsqrt(d2,prec);
     GEN z = gsqrt(gsub(x0,e3), prec);
     GEN ar = real_i(a), zr = real_i(z), ai = imag_i(a), zi = imag_i(z);
     GEN t = gdiv(gneg(y0), gmul2n(gnorm(z),1));
@@ -1687,14 +1904,16 @@ zellrealneg(GEN E, GEN P, long prec)
 static GEN
 zellrealpos(GEN E, GEN P, long prec)
 {
-  GEN roots = ellR_roots(E, prec+EXTRAPRECWORD);
-  GEN e1,e2,e3, a,b, x0 = gel(P,1), y0 = d_ellLHS(E,P);
-  if (gequal0(y0)) return zell_closest_0(ellR_omega(E,prec), x0,roots);
-  e1 = gel(roots,1);
-  e2 = gel(roots,2);
-  e3 = gel(roots,3);
-  a = gsqrt(gsub(e1,e3),prec);
-  b = gsqrt(gsub(e1,e2),prec);
+  GEN R = ellR_roots(E, prec+EXTRAPRECWORD);
+  GEN d2,d3,e1,e2,e3, a,b, x0 = gel(P,1), y0 = ec_dmFdy_evalQ(E,P);
+  if (gequal0(y0)) return zell_closest_0(ellR_omega(E,prec), x0,R);
+  e1 = gel(R,1);
+  e2 = gel(R,2);
+  e3 = gel(R,3);
+  d2 = gel(R,5);
+  d3 = gel(R,6);
+  a = gsqrt(d2,prec);
+  b = gsqrt(d3,prec);
   if (gcmp(x0,e1)>0) {
     GEN r = gsqrt(gdiv(gsub(x0,e3), gsub(x0,e2)),prec);
     GEN t = gdiv(gneg(y0), gmul2n(gmul(r,gsub(x0,e2)),1));
@@ -1810,9 +2029,8 @@ START:
     u = Qp_sqrt(u2);
   else
   {
-    long v = fetch_user_var("u");
     GEN T = mkpoln(3, gen_1, gen_0, gneg(u2));
-    setvarn(T, v); u = mkpolmod(pol_x(v), T);
+    u = mkpolmod(pol_x(0), T);
   }
   return mkvec4(u2, u, q, mkvec2(a, b));
 }
@@ -1849,7 +2067,7 @@ zellQp(GEN E, GEN z, long prec)
   c0 = gadd(x, gmul2n(r0,-1)); ar1 = gmul(a,r1);
   delta = gdiv(ar1, gsqr(c0));
   x0 = gmul2n(gmul(c0,gaddsg(1,Qp_sqrt(gsubsg(1,gmul2n(delta,2))))),-1);
-  y0 = gdiv(gadd(y, gmul2n(d_ellLHS(E,z), -1)), gsubsg(1, gdiv(ar1,gsqr(x0))));
+  y0 = gdiv(gadd(y, gmul2n(ec_dmFdy_evalQ(E,z), -1)), gsubsg(1, gdiv(ar1,gsqr(x0))));
 
   x1 = gmul(x0, gsqr(gmul2n(gaddsg(1, Qp_sqrt(gdiv(gadd(x0,r1),x0))),-1)));
   y1 = gdiv(y0, gsubsg(1, gsqr(gdiv(r1,gmul2n(x1,2)))));
@@ -1858,133 +2076,651 @@ zellQp(GEN E, GEN z, long prec)
   (void)do_padic_agm(&x1,&y1, a,b);
   t = gmul(ellQp_u(E, prec), gmul2n(y1,1)); /* 2u y_oo */
   t = gdiv(gsub(t, x1), gadd(t, x1));
+  if (padicprec_relative(t) > prec) t = gprec(t, prec);
   return gerepileupto(av, t);
 }
 
+/* t to w := -1/y */
 GEN
-zell(GEN e, GEN z, long prec)
+ellformalw(GEN e, long n, long v)
 {
-  pari_sp av = avma;
-  GEN t;
-  long s;
-
-  checkell(e); checkellpt(z);
-  switch(ell_get_type(e))
-  {
-    case t_ELL_Qp:
-      prec = minss(ellQp_get_prec(e), padicprec_relative(z));
-      return zellQp(e, z, prec);
-    case t_ELL_Q: break;
-    case t_ELL_Rg: break;
-    default: pari_err_TYPE("ellpointtoz", e);
-  }
-  (void)ellR_omega(e, prec); /* type checking */
-  if (ell_is_inf(z)) return gen_0;
-  s = ellR_get_sign(e);
-  if (s && typ(gel(z,1))!=t_COMPLEX && typ(gel(z,2))!=t_COMPLEX)
-    t = (s < 0)? zellrealneg(e,z,prec): zellrealpos(e,z,prec);
-  else
-    t = zellcx(e,z,prec);
-  return gerepileupto(av,t);
+  pari_sp av = avma, av2;
+  GEN a1,a2,a3,a4,a6, a63;
+  GEN w = cgetg(3, t_SER), t, U, V, W, U2;
+  ulong mask, nold = 1;
+  if (v < 0) v = 0;
+  if (n <= 0) pari_err_DOMAIN("ellformalw","precision","<=",gen_0,stoi(n));
+  mask = quadratic_prec_mask(n);
+  t = pol_x(v);
+  checkell(e);
+  a1 = ell_get_a1(e); a2 = ell_get_a2(e); a3 = ell_get_a3(e);
+  a4 = ell_get_a4(e); a6 = ell_get_a6(e); a63 = gmulgs(a6,3);
+  w[1] = evalsigne(1)|evalvarn(v)|evalvalp(3);
+  gel(w,2) = gen_1; /* t^3 + O(t^4) */
+  /* use Newton iteration, doubling accuracy at each step
+   *
+   *            w^3 a6 + w^2(a4 t + a3) + w (a2 t^2 + a1 t - 1) + t^3
+   * w  <-  w - -----------------------------------------------------
+   *              w^2 (3a6) + w (2a4 t + 2a3) + (a2 t^2 + a1 t - 1)
+   *
+   *              w^3 a6 + w^2 U + w V + W
+   *      =: w -  -----------------------
+   *                w^2 (3a6) + 2w U + V
+   */
+  U = gadd(gmul(a4,t), a3);
+  U2 = gmul2n(U,1);
+  V = gsubgs(gadd(gmul(a2,gsqr(t)), gmul(a1,t)), 1);
+  W = gpowgs(t,3);
+  av2 = avma;
+  while (mask > 1)
+  { /* nold correct terms in w */
+    ulong i, nnew = nold << 1;
+    GEN num, den, wnew, w2, w3;
+    if (mask & 1) nnew--;
+    mask >>= 1;
+    wnew = cgetg(nnew+2, t_SER);
+    wnew[1] = w[1];
+    for (i = 2; i < nold+2; i++) gel(wnew,i) = gel(w,i);
+    for (     ; i < nnew+2; i++) gel(wnew,i) = gen_0;
+    w = wnew;
+    w2 = gsqr(w); w3 = gmul(w2,w);
+    num = gadd(gmul(a6,w3), gadd(gmul(U,w2), gadd(gmul(V,w), W)));
+    den = gadd(gmul(a63,w2), gadd(gmul(w,U2), V));
+
+    w = gerepileupto(av2, gsub(w, gdiv(num, den)));
+    nold = nnew;
+  }
+  return gerepilecopy(av, w);
 }
 
-enum period_type { t_PER_W, t_PER_WETA, t_PER_ELL };
-/* normalization / argument reduction for ellptic functions */
-typedef struct {
-  enum period_type type;
-  GEN in; /* original input */
-  GEN w1,w2,tau; /* original basis for L = <w1,w2> = w2 <1,tau> */
-  GEN W1,W2,Tau; /* new basis for L = <W1,W2> = W2 <1,tau> */
-  GEN a,b,c,d; /* t_INT; tau in F = h/Sl2, tau = g.t, g=[a,b;c,d] in SL(2,Z) */
-  GEN z,Z; /* z/w2 defined mod <1,tau>, Z = z + x*tau + y reduced mod <1,tau> */
-  GEN x,y; /* t_INT */
-  int swap; /* 1 if we swapped w1 and w2 */
-  int some_q_is_real; /* exp(2iPi g.tau) for some g \in SL(2,Z) */
-  int some_z_is_real; /* z + xw1 + yw2 is real for some x,y \in Z */
-  int some_z_is_pure_imag; /* z + xw1 + yw2 = it, t \in R */
-  int q_is_real; /* exp(2iPi tau) \in R */
-  int abs_u_is_1; /* |exp(2iPi Z)| = 1 */
-  long prec; /* precision(Z) */
-} ellred_t;
+static GEN
+ellformalpoint_i(GEN w, GEN wi)
+{ return mkvec2(gmul(pol_x(varn(w)),wi), gneg(wi)); }
 
-/* compute g in SL_2(Z), g.t is in the usual
-   fundamental domain. Internal function no check, no garbage. */
-static void
-set_gamma(GEN t, GEN *pa, GEN *pb, GEN *pc, GEN *pd)
+/* t to [x,y] */
+GEN
+ellformalpoint(GEN e, long n, long v)
 {
-  GEN a, b, c, d, run = dbltor(1. - 1e-8);
-  pari_sp av = avma, lim = stack_lim(av, 1);
+  pari_sp av = avma;
+  GEN w = ellformalw(e, n, v), wi = inv_ser(w);
+  return gerepilecopy(av, ellformalpoint_i(w, wi));
+}
 
-  a = d = gen_1;
-  b = c = gen_0;
-  for(;;)
+static GEN
+ellformaldifferential_i(GEN e, GEN w, GEN wi, GEN *px)
+{
+  GEN x, w1;
+  if (gequal0(ell_get_a1(e)) && gequal0(ell_get_a3(e)))
+  { /* dx/2y = dx * -w/2, avoid division */
+    x = gmul(pol_x(varn(w)), wi);
+    w1 = gmul(derivser(x), gneg(gmul2n(w,-1)));
+  }
+  else
   {
-    GEN m, n = ground(real_i(t));
-    if (signe(n))
-    { /* apply T^n */
-      t = gsub(t,n);
-      a = subii(a, mulii(n,c));
-      b = subii(b, mulii(n,d));
-    }
-    m = cxnorm(t); if (gcmp(m,run) > 0) break;
-    t = gneg_i(gdiv(gconj(t), m)); /* apply S */
-    togglesign_safe(&c); swap(a,c);
-    togglesign_safe(&d); swap(b,d);
-    if (low_stack(lim, stack_lim(av, 1))) {
-      if (DEBUGMEM>1) pari_warn(warnmem, "redimagsl2");
-      gerepileall(av, 5, &t, &a,&b,&c,&d);
-    }
+    GEN P = ellformalpoint_i(w, wi);
+    x = gel(P,1);
+    w1 = gdiv(derivser(x), ec_dmFdy_evalQ(e, P));
   }
-  *pa = a;
-  *pb = b;
-  *pc = c;
-  *pd = d;
+  *px = x; return w1;
 }
-/* Im t > 0. Return U.t in PSl2(Z)'s standard fundamental domain.
- * Set *pU to U. */
+/* t to [ dx / (2y + a1 x + a3), x * ... ]*/
 GEN
-redtausl2(GEN t, GEN *pU)
+ellformaldifferential(GEN e, long n, long v)
 {
   pari_sp av = avma;
-  GEN U, a,b,c,d;
-  set_gamma(t, &a, &b, &c, &d);
-  U = mkmat2(mkcol2(a,c), mkcol2(b,d));
-  t = gdiv(gadd(gmul(a,t), b),
-           gadd(gmul(c,t), d));
-  gerepileall(av, 2, &t, &U);
-  *pU = U; return t;
+  GEN w = ellformalw(e, n, v), wi = inv_ser(w), x;
+  GEN w1 = ellformaldifferential_i(e, w, wi, &x);
+  return gerepilecopy(av, mkvec2(w1,gmul(x,w1)));
 }
 
-/* swap w1, w2 so that Im(t := w1/w2) > 0. Set tau = representative of t in
- * the standard fundamental domain, and g in Sl_2, such that tau = g.t */
-static void
-red_modSL2(ellred_t *T, long prec)
+/* t to z, dz = w1 dt */
+GEN
+ellformallog(GEN e, long n, long v)
 {
-  long s, p;
-  T->tau = gdiv(T->w1,T->w2);
-  if (isexactzero(real_i(T->tau))) T->some_q_is_real = 1;
-  s = gsigne(imag_i(T->tau));
-  if (!s) pari_err_DOMAIN("elliptic function", "det(w1,w2)", "=", gen_0,
-                          mkvec2(T->w1,T->w2));
-  T->swap = (s < 0);
-  if (T->swap) { swap(T->w1, T->w2); T->tau = ginv(T->tau); }
-  set_gamma(T->tau, &T->a, &T->b, &T->c, &T->d);
-  /* update lattice */
-  T->W1 = gadd(gmul(T->a,T->w1), gmul(T->b,T->w2));
-  T->W2 = gadd(gmul(T->c,T->w1), gmul(T->d,T->w2));
-  T->Tau = gdiv(T->W1, T->W2);
-  if (isexactzero(real_i(T->Tau))) T->some_q_is_real = T->q_is_real = 1;
-  p = precision(T->Tau); if (!p) p = prec;
-  T->prec = p;
+  pari_sp av = avma;
+  GEN w = ellformalw(e, n, v), wi = inv_ser(w), x;
+  GEN w1 = ellformaldifferential_i(e, w, wi, &x);
+  return gerepileupto(av, integser(w1));
 }
-static void
-reduce_z(GEN z, ellred_t *T)
+/* z to t */
+GEN
+ellformalexp(GEN e, long n, long v)
 {
-  long p;
-  GEN Z;
-  T->abs_u_is_1 = 0;
-  T->some_z_is_real = 0;
-  T->some_z_is_pure_imag = 0;
+  pari_sp av = avma;
+  return gerepileupto(av, serreverse(ellformallog(e,n,v)));
+}
+/* [log_p (sigma(t) / t), log_E t], as power series, d (log_E t) := w1 dt;
+ * As a fonction of z: odd, = e.b2/12 * z + O(z^3).
+ *   sigma(z) = ellsigma(e) exp(e.b2/24*z^2)
+ * log_p(sigma(t)/t)=log(subst(sigma(z), x, ellformallog(e))/x) */
+static GEN
+ellformallogsigma_t(GEN e, long n)
+{
+  pari_sp av = avma;
+  GEN w = ellformalw(e, n, 0), wi = inv_ser(w), t = pol_x(0);
+  GEN x, s = ellformaldifferential_i(e, w, wi, &x);
+  GEN f = gmul(s, gadd(integser(gmul(x,s)), gmul2n(ell_get_a1(e),-1)));
+  return gerepilecopy(av, mkvec2(integser( gsub(ginv(gneg(t)), f) ),
+                                 integser(s)));
+}
+
+/* P = rational point of exact denominator d. Is Q singular on E(Fp) ? */
+static int
+FpE_issingular(GEN E, GEN P, GEN d, GEN p)
+{
+  pari_sp av = avma;
+  GEN t, x, y, a1, a2, a3, a4;
+  if (ell_is_inf(E) || !signe(remii(d,p))) return 0; /* 0_E is smooth */
+  P = Q_muli_to_int(P,d);
+  x = gel(P,1);
+  y = gel(P,2);
+  a1 = ell_get_a1(E);
+  a3 = ell_get_a3(E);
+  t = addii(shifti(y,1), addii(mulii(a1,x), mulii(a3,d)));
+  if (signe(remii(t,p))) { avma = av; return 0; }
+  a2 = ell_get_a2(E);
+  a4 = ell_get_a4(E);
+  d = Fp_inv(d, p);
+  x = Fp_mul(x,d,p);
+  y = Fp_mul(y,d,p);
+  t = subii(mulii(a1,y), addii(a4, mulii(x, addii(gmul2n(a2,1), muliu(x,3)))));
+  avma = av; return signe(remii(t,p))? 0: 1;
+}
+
+/* E/Q, P on E(Q). Let g > 0 minimal such that the image of R = [g]P in a
+ * minimal model is everywhere non-singular. return [R,g] */
+GEN
+ellnonsingularmultiple(GEN e, GEN P)
+{
+  pari_sp av = avma;
+  GEN ch, E = ellanal_globalred(e, &ch), NP, L, S, d, g = gen_1;
+  long i, l;
+  checkellpt(P);
+  if (ell_is_inf(P)) retmkvec2(gcopy(P), gen_1);
+  if (E != e) P = ellchangepoint(P, ch);
+  S = obj_check(E, Q_GLOBALRED);
+  NP = gmael(S,3,1);
+  L = gel(S,4);
+  l = lg(NP);
+  d = Q_denom(P);
+  for (i = 1; i < l; i++)
+  {
+    GEN c,kod, G = gel(L,i), p = gel(NP,i);/* prime of bad reduction */
+    if (!FpE_issingular(E, P, d, p)) continue;
+    c = gel(G, 4); /* Tamagawa number at p */
+    kod = gel(G, 2); /* Kodaira type */
+    if (cmpis(kod, 5) >= 0) /* I_nu */
+    {
+      long nu = itos(kod) - 4;
+      long n = minss(Q_pval(ec_dmFdy_evalQ(E,P), p), nu/2);
+      nu /= ugcd(nu, n);
+      g = muliu(g, nu);
+      P = ellmul_Z(E, P, utoipos(nu));
+      d = Q_denom(P);
+    } else if (cmpis(kod, -5) <= 0) /* I^*_nu */
+    { /* either 2 or 4 */
+      long nu = - itos(kod) - 4;
+      P = elladd(E, P,P);
+      d = Q_denom(P);
+      g = shifti(g,1);
+      if (odd(nu) && FpE_issingular(E, P, d, p))
+      { /* it's 4 */
+        P = elladd(E, P,P);
+        d = Q_denom(P);
+        g = shifti(g,1);
+      }
+    } else {
+      if (equaliu(c, 4)) c = gen_2;
+      P = ellmul(E, P, c);
+      d = Q_denom(P);
+      g = mulii(g, c);
+    }
+  }
+  if (E != e) P = ellchangepointinv(P, ch);
+  return gerepilecopy(av, mkvec2(P,g));
+}
+
+/* m >= 0, T = b6^2, g4 = b6^2 - b4 b8, return g_m(xP) mod N, in Mazur-Tate's
+ * notation (Duke 1991)*/
+static GEN
+rellg(hashtable *H, GEN m, GEN T, GEN g4, GEN b8, GEN N)
+{
+  hashentry *h;
+  GEN n, z, np2, np1, nm2, nm1, fp2, fp1, fm2, fm1, f;
+  ulong m4;
+  if (cmpiu(m, 4) <= 0) switch(itou(m))
+  {
+    case 0: return gen_0;
+    case 1: return gen_1;
+    case 2: return subiu(N,1);
+    case 3: return b8;
+    case 4: return g4;
+  }
+  if ((h = hash_search(H, (void*)m))) return (GEN)h->val;
+  m4 = mod4(m);
+  n = shifti(m, -1); f   = rellg(H,n,T,g4,b8,N);
+  np2 = addiu(n, 2); fp2 = rellg(H,np2,T,g4,b8,N);
+  np1 = addiu(n, 1); fp1 = rellg(H,np1,T,g4,b8,N);
+  nm2 = subiu(n, 2); fm2 = rellg(H,nm2,T,g4,b8,N);
+  nm1 = subiu(n, 1); fm1 = rellg(H,nm1,T,g4,b8,N);
+  if (odd(m4))
+  {
+    GEN t1 = Fp_mul(fp2, Fp_powu(f,3,N), N);
+    GEN t2 = Fp_mul(fm1, Fp_powu(fp1,3,N), N);
+    if (mpodd(n))
+      z = Fp_sub(t1, Fp_mul(T,t2,N), N);
+    else
+      z = Fp_sub(Fp_mul(T,t1,N), t2, N);
+  }
+  else
+  {
+    GEN t1 = Fp_mul(fm2, Fp_sqr(fp1,N), N);
+    GEN t2 = Fp_mul(fp2, Fp_sqr(fm1,N), N);
+    z = Fp_mul(f, Fp_sub(t1, t2, N), N);
+  }
+  hash_insert(H, (void*)m, (void*)z);
+  return z;
+}
+
+static GEN
+addii3(GEN x, GEN y, GEN z) { return addii(x,addii(y,z)); }
+static GEN
+addii4(GEN x, GEN y, GEN z, GEN t) { return addii(x,addii3(y,z,t)); }
+static GEN
+addii5(GEN x, GEN y, GEN z, GEN t, GEN u) { return addii(x,addii4(y,z,t,u)); }
+
+/* xP = [n,d] (corr. to n/d, coprime), such that the reduction of the point
+ * P = [xP,yP] is non singular at all places. Return x([m] P) mod N as
+ * [num,den] (coprime) */
+static GEN
+xmP(GEN e, GEN xP, GEN m, GEN N)
+{
+  pari_sp av = avma;
+  ulong k = expi(m);
+  hashtable *H = hash_create((5+k)*k, (ulong(*)(void*))&hash_GEN,
+                                      (int(*)(void*,void*))&gidentical, 1);
+  GEN b2 = ell_get_b2(e), b4 = ell_get_b4(e), n = gel(xP,1), d = gel(xP,2);
+  GEN b6 = ell_get_b6(e), b8 = ell_get_b8(e);
+  GEN B4, B6, B8, T, g4;
+  GEN d2 = Fp_sqr(d,N), d3 = Fp_mul(d2,d,N), d4 = Fp_sqr(d2,N);
+  GEN n2 = Fp_sqr(n,N), n3 = Fp_mul(n2,n,N), n4 = Fp_sqr(n2,N);
+  GEN nd = Fp_mul(n,d,N), n2d2 = Fp_sqr(nd,N);
+  GEN b2nd = Fp_mul(b2,nd, N), b2n2d = Fp_mul(b2nd,n,N);
+  GEN b6d3 = Fp_mul(b6,d3,N), g,gp1,gm1, C,D;
+  B8 = addii5(muliu(n4,3), mulii(b2n2d,n), mulii(muliu(b4,3), n2d2),
+              mulii(muliu(b6d3,3), n), mulii(b8,d4));
+  B6 = addii4(muliu(n3,4), mulii(b2nd,n),
+              shifti(mulii(b4,Fp_mul(n,d2,N)), 1),
+              b6d3);
+  B4 = addii3(muliu(n2,6), b2nd,  mulii(b4,d2));
+
+  B4 = modii(B4,N);
+  B6 = modii(B6,N);
+  B8 = modii(B8,N);
+
+  g4 = Fp_sub(sqri(B6), mulii(B4,B8), N);
+  T = Fp_sqr(B6,N);
+
+  g = rellg(H, m, T,g4,B8, N);
+  gp1 = rellg(H, addiu(m,1), T,g4,B8, N);
+  gm1 = rellg(H, subiu(m,1), T,g4,B8, N);
+  C = Fp_sqr(g, N);
+  D = Fp_mul(gp1,gm1, N);
+
+  if(mpodd(m))
+  {
+    n = Fp_sub(mulii(C,n), mulii(D,B6), N);
+    d = Fp_mul(C,d, N);
+  }
+  else
+  {
+    n = Fp_sub(Fp_mul(Fp_mul(B6,C,N), n, N), D, N);
+    d = Fp_mul(Fp_mul(C,d,N), B6, N);
+  }
+  return gerepilecopy(av, mkvec2(n,d));
+}
+/* given [n,d2], x = n/d2 (coprime, d2 = d^2), p | den,
+ * return t = -x/y + O(p^v) */
+static GEN
+tfromx(GEN e, GEN x, GEN p, long v, GEN N, GEN *pd)
+{
+  GEN n = gel(x,1), d2 = gel(x,2), d;
+  GEN a1, a3, b2, b4, b6, B, C, d4, d6, Y;
+  if (!signe(n)) { *pd = gen_1; return zeropadic(p, v); }
+  a1 = ell_get_a1(e);
+  b2 = ell_get_b2(e);
+  a3 = ell_get_a3(e);
+  b4 = ell_get_b4(e);
+  b6 = ell_get_b6(e);
+  d = Qp_sqrt(cvtop(d2, p, v - Z_pval(d2,p)));
+  if (!d) pari_err_BUG("ellpadicheight");
+  /* Solve Y^2 = 4n^3 + b2 n^2 d2+ 2b4 n d2^2 + b6 d2^3,
+   * Y = 2y + a1 n d + a3 d^3 */
+  d4 = Fp_sqr(d2, N);
+  d6 = Fp_mul(d4, d2, N);
+  B = gmul(d, Fp_add(mulii(a1,n), mulii(a3,d2), N));
+  C = mkpoln(4, utoipos(4), Fp_mul(b2, d2, N),
+                Fp_mul(shifti(b4,1), d4, N),
+                Fp_mul(b6,d6,N));
+  C = FpX_eval(C, n, N);
+  if (!signe(C))
+    Y = zeropadic(p, v >> 1);
+  else
+    Y = Qp_sqrt(cvtop(C, p, v - Z_pval(C,p)));
+  if (!Y) pari_err_BUG("ellpadicheight");
+  *pd = d;
+  return gdiv(gmulgs(gmul(n,d), -2), gsub(Y,B));
+}
+
+/* return minimal i s.t. -v_p(j+1) - log_p(j-1) + (j+1)*t >= v for all j>=i */
+static long
+logsigma_prec(GEN p, long v, long t)
+{
+  double log2p = dbllog2(p);
+  long j, i = ceil((v - t) / (t - 2*LOG2/(3*log2p)) + 0.01);
+  if (equaliu(p,2) && i < 5) i = 5;
+  /* guaranteed to work, now optimize */
+  for (j = i-1; j >= 2; j--)
+  {
+    if (- u_pval(j+1,p) - log2(j-1)/log2p + (j+1)*t + 0.01 < v) break;
+    i = j;
+  }
+  if (j == 1)
+  {
+    if (- equaliu(p,2) + 2*t + 0.01 >= v) i = 1;
+  }
+  return i;
+}
+/* return minimal i s.t. -v_p(j+1) + (j+1)*t >= v for all j>=i */
+static long
+log_prec(GEN p, long v, long t)
+{
+  double log2p = dbllog2(p);
+  long j, i = ceil(v / (t - LOG2/(2*log2p)) + 0.01);
+  /* guaranteed to work, now optimize */
+  for (j = i-1; j >= 1; j--)
+  {
+    if (- u_pval(j+1,p) + (j+1)*t + 0.01 < v) break;
+    i = j;
+  }
+  return i;
+}
+
+static GEN
+parse_p(GEN p, GEN *ab)
+{
+  *ab = NULL;
+  switch(typ(p))
+  {
+    case t_INT: break;
+    case t_VEC:
+      if (lg(p) != 3) pari_err_TYPE("ellpadicheight",p);
+      *ab = gel(p,2);
+      if (typ(*ab) != t_VEC || lg(*ab) != 3) pari_err_TYPE("ellpadicheight",p);
+      p = gel(p,1);
+  }
+  if (cmpis(p,2) < 0) pari_err_PRIME("ellpadicheight",p);
+  return p;
+}
+
+static GEN
+precp_fix(GEN h, long v)
+{ return (precp(h) > v)? gprec(h,v): h; }
+
+GEN
+ellpadicheight(GEN e, GEN p, long v0, GEN P)
+{
+  pari_sp av = avma;
+  GEN N, H, h, t, ch, g, E, x, n, d, D, ls, lt, S, a,b, ab;
+  long v, vd;
+  int is2;
+  checkellpt(P);
+  if (v0<=0) pari_err_DOMAIN("ellpadicheight","precision","<=",gen_0,stoi(v0));
+  checkell_Q(e);
+  p = parse_p(p, &ab);
+  if (ellorder_Q(e,P)) return ab? gen_0: mkvec2(gen_0,gen_0);
+  E = ellanal_globalred(e, &ch);
+  if (E != e) P = ellchangepoint(P, ch);
+  S = ellnonsingularmultiple(E, P);
+  P = gel(S,1);
+  g = gel(S,2);
+  v = v0 + 2*Z_pval(g, p);
+  is2 = equaliu(p,2);
+  if (is2) v += 2;
+  x = gel(P,1);
+  n = numer(x);
+  d = denom(x);
+  x = mkvec2(n, d);
+  vd = Z_pval(d, p);
+  if (!vd)
+  { /* P not in kernel of reduction mod p */
+    GEN m, X, Pp, Ep = ellinit_Fp(E, p);
+    long w = v+2;
+    if (!Ep) pari_err(e_MISC,"ellpadicheight: bad reduction");
+    Pp = RgV_to_FpV(P, p);
+    m = ellorder(Ep, Pp, NULL);
+    g = mulii(g,m);
+    for(;;)
+    {
+      N = powiu(p, w);
+      X = xmP(E, x, m, N);
+      d = gel(X,2);
+      if (!signe(d))
+        w <<= 1;
+      else
+      {
+        vd = Z_pval(d, p);
+        if (w >= v+2*vd + is2) break;
+        w = v+2*vd + is2;
+      }
+    }
+    x = X;
+  }
+  /* we will want t mod p^(v+vd) because of t/D in H later, and
+   * we lose p^vd in tfromx because of sqrt(d) (p^(vd+1) if p=2)*/
+  v += 2*vd + is2;
+  N = powiu(p,v);
+  t = tfromx(E, x, p, v, N, &D); /* D^2=denom(x)=x[2] */
+  S = ellformallogsigma_t(E, logsigma_prec(p, v-vd, valp(t)) + 1);
+  ls = ser2rfrac_i(gel(S,1)); /* log_p (sigma(T)/T) */
+  lt = ser2rfrac_i(gel(S,2)); /* log_E (T) */
+  /* evaluate our formal power series at t */
+  H = gadd(poleval(ls, t), glog(gdiv(t, D), 0));
+  h = gsqr(poleval(lt, t));
+  g = sqri(g);
+  a = gdiv(gmulgs(H,-2), g);
+  b = gdiv(gneg(h), g);
+  if (E != e)
+  {
+    GEN u = gel(ch,1), r = gel(ch,2);
+    a = gdiv(gadd(a, gmul(r,b)), u);
+    b = gmul(u,b);
+  }
+  H = mkvec2(a,b);
+  if (ab)
+  {
+    H = RgV_dotproduct(H, ab);
+    H = precp_fix(H,v0);
+  }
+  else
+  {
+    gel(H,1) = precp_fix(gel(H,1),v0);
+    gel(H,2) = precp_fix(gel(H,2),v0);
+  }
+  return gerepilecopy(av, H);
+}
+
+GEN
+ellpadiclog(GEN E, GEN p, long n, GEN P)
+{
+  pari_sp av = avma;
+  long vt;
+  GEN t, x, y, L;
+  checkellpt(P);
+  if (ell_is_inf(P)) return gen_0;
+  x = gel(P,1);
+  y = gel(P,2); t = gneg(gdiv(x,y));
+  vt = gvaluation(t, p); /* can be a t_INT, t_FRAC or t_PADIC */
+  if (vt <= 0)
+    pari_err_DOMAIN("ellpadiclog","P","not in the kernel of reduction at",p,P);
+  L = ser2rfrac_i(ellformallog(E, log_prec(p, n, vt) + 1, 0));
+  return gerepileupto(av, poleval(L, cvtop(t, p, n)));
+}
+
+/* s2 = (b_2-E_2)/12 */
+GEN
+ellpadics2(GEN E, GEN p, long n)
+{
+  pari_sp av = avma;
+  GEN sqrtD, D, l, F, a,b,d, ap;
+  ulong pp;
+  if (typ(p) != t_INT) pari_err_TYPE("ellpadics2",p);
+  if (cmpis(p,2) < 0) pari_err_PRIME("ellpadics2",p);
+  pp = itou_or_0(p);
+  F = ellpadicfrobenius(E, itou(p), n);
+  a = gcoeff(F,1,1);
+  b = gcoeff(F,1,2);
+  d = gcoeff(F,2,2); ap = gadd(a,d);
+  if(valp(ap) > 0) pari_err_DOMAIN("ellpadics2","E","is supersingular at", p,E);
+  if (pp == 2 || (pp <= 13 && n == 1)) /* 2sqrt(p) > p/2: ambiguity */
+    ap = ellap(E,p);
+  else
+  { /* either 2sqrt(p) < p/2 or n > 1 and 2sqrt(p) < p^2/2 (since p!=2) */
+    GEN q = cmpiu(p,13) <= 0? sqri(p): p;
+    ap = padic_to_Fp(ap, q);
+    ap = Fp_center(ap,q,shifti(q,-1));
+  }
+  D = subii(sqri(ap), shifti(p,2));
+  if (equaliu(p,2)) n++;
+  sqrtD = Zp_sqrtlift(D, ap, p, n); /* congruent to ap mod p */
+  l = gmul2n(gadd(ap, cvtop(sqrtD,p,n)), -1); /*unit eigenvalue of F*/
+  return gerepileupto(av, gdiv(b, gsub(l, a))); /* slope of eigenvector */
+}
+
+GEN
+zell(GEN e, GEN z, long prec)
+{
+  pari_sp av = avma;
+  GEN t;
+  long s;
+
+  checkell(e); checkellpt(z);
+  switch(ell_get_type(e))
+  {
+    case t_ELL_Qp:
+      prec = minss(ellQp_get_prec(e), padicprec_relative(z));
+      return zellQp(e, z, prec);
+    case t_ELL_Q: break;
+    case t_ELL_Rg: break;
+    default: pari_err_TYPE("ellpointtoz", e);
+  }
+  (void)ellR_omega(e, prec); /* type checking */
+  if (ell_is_inf(z)) return gen_0;
+  s = ellR_get_sign(e);
+  if (s && typ(gel(z,1))!=t_COMPLEX && typ(gel(z,2))!=t_COMPLEX)
+    t = (s < 0)? zellrealneg(e,z,prec): zellrealpos(e,z,prec);
+  else
+    t = zellcx(e,z,prec);
+  return gerepileupto(av,t);
+}
+
+enum period_type { t_PER_W, t_PER_WETA, t_PER_ELL };
+/* normalization / argument reduction for ellptic functions */
+typedef struct {
+  enum period_type type;
+  GEN in; /* original input */
+  GEN w1,w2,tau; /* original basis for L = <w1,w2> = w2 <1,tau> */
+  GEN W1,W2,Tau; /* new basis for L = <W1,W2> = W2 <1,tau> */
+  GEN a,b,c,d; /* t_INT; tau in F = h/Sl2, tau = g.t, g=[a,b;c,d] in SL(2,Z) */
+  GEN z,Z; /* z/w2 defined mod <1,tau>, Z = z + x*tau + y reduced mod <1,tau> */
+  GEN x,y; /* t_INT */
+  int swap; /* 1 if we swapped w1 and w2 */
+  int some_q_is_real; /* exp(2iPi g.tau) for some g \in SL(2,Z) */
+  int some_z_is_real; /* z + xw1 + yw2 is real for some x,y \in Z */
+  int some_z_is_pure_imag; /* z + xw1 + yw2 = it, t \in R */
+  int q_is_real; /* exp(2iPi tau) \in R */
+  int abs_u_is_1; /* |exp(2iPi Z)| = 1 */
+  long prec; /* precision(Z) */
+} ellred_t;
+
+/* compute g in SL_2(Z), g.t is in the usual
+   fundamental domain. Internal function no check, no garbage. */
+static void
+set_gamma(GEN t, GEN *pa, GEN *pb, GEN *pc, GEN *pd)
+{
+  GEN a, b, c, d, run = dbltor(1. - 1e-8);
+  pari_sp av = avma;
+
+  a = d = gen_1;
+  b = c = gen_0;
+  for(;;)
+  {
+    GEN m, n = ground(real_i(t));
+    if (signe(n))
+    { /* apply T^n */
+      t = gsub(t,n);
+      a = subii(a, mulii(n,c));
+      b = subii(b, mulii(n,d));
+    }
+    m = cxnorm(t); if (gcmp(m,run) > 0) break;
+    t = gneg_i(gdiv(gconj(t), m)); /* apply S */
+    togglesign_safe(&c); swap(a,c);
+    togglesign_safe(&d); swap(b,d);
+    if (gc_needed(av, 1)) {
+      if (DEBUGMEM>1) pari_warn(warnmem, "redimagsl2");
+      gerepileall(av, 5, &t, &a,&b,&c,&d);
+    }
+  }
+  *pa = a;
+  *pb = b;
+  *pc = c;
+  *pd = d;
+}
+/* Im t > 0. Return U.t in PSl2(Z)'s standard fundamental domain.
+ * Set *pU to U. */
+GEN
+redtausl2(GEN t, GEN *pU)
+{
+  pari_sp av = avma;
+  GEN U, a,b,c,d;
+  set_gamma(t, &a, &b, &c, &d);
+  U = mkmat2(mkcol2(a,c), mkcol2(b,d));
+  t = gdiv(gadd(gmul(a,t), b),
+           gadd(gmul(c,t), d));
+  gerepileall(av, 2, &t, &U);
+  *pU = U; return t;
+}
+
+/* swap w1, w2 so that Im(t := w1/w2) > 0. Set tau = representative of t in
+ * the standard fundamental domain, and g in Sl_2, such that tau = g.t */
+static void
+red_modSL2(ellred_t *T, long prec)
+{
+  long s, p;
+  T->tau = gdiv(T->w1,T->w2);
+  if (isexactzero(real_i(T->tau))) T->some_q_is_real = 1;
+  s = gsigne(imag_i(T->tau));
+  if (!s) pari_err_DOMAIN("elliptic function", "det(w1,w2)", "=", gen_0,
+                          mkvec2(T->w1,T->w2));
+  T->swap = (s < 0);
+  if (T->swap) { swap(T->w1, T->w2); T->tau = ginv(T->tau); }
+  set_gamma(T->tau, &T->a, &T->b, &T->c, &T->d);
+  /* update lattice */
+  T->W1 = gadd(gmul(T->a,T->w1), gmul(T->b,T->w2));
+  T->W2 = gadd(gmul(T->c,T->w1), gmul(T->d,T->w2));
+  T->Tau = gdiv(T->W1, T->W2);
+  if (isexactzero(real_i(T->Tau))) T->some_q_is_real = T->q_is_real = 1;
+  p = precision(T->Tau); if (!p) p = prec;
+  T->prec = p;
+}
+static void
+reduce_z(GEN z, ellred_t *T)
+{
+  long p;
+  GEN Z;
+  T->abs_u_is_1 = 0;
+  T->some_z_is_real = 0;
+  T->some_z_is_pure_imag = 0;
   switch(typ(z))
   {
     case t_INT: case t_REAL: case t_FRAC: case t_COMPLEX: break;
@@ -2099,7 +2835,7 @@ check_real(GEN q)
 static GEN
 trueE(GEN tau, long k, long prec)
 {
-  pari_sp lim, av;
+  pari_sp av;
   GEN p1, q, y, qn;
   long n = 1;
 
@@ -2107,14 +2843,14 @@ trueE(GEN tau, long k, long prec)
   q = expIxy(Pi2n(1, prec), tau, prec);
   q = check_real(q);
   y = gen_0;
-  av = avma; lim = stack_lim(av,2); qn = gen_1;
+  av = avma; qn = gen_1;
   for(;; n++)
   { /* compute y := sum_{n>0} n^(k-1) q^n / (1-q^n) */
     qn = gmul(q,qn);
     p1 = gdiv(gmul(powuu(n,k-1),qn), gsubsg(1,qn));
     if (gequal0(p1) || gexpo(p1) <= - prec2nbits(prec) - 5) break;
     y = gadd(y, p1);
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"elleisnum");
       gerepileall(av, 2, &y,&qn);
@@ -2219,7 +2955,7 @@ ellperiods(GEN w, long flag, long prec)
 
 /* 2Pi Im(z)/log(2) */
 static double
-get_toadd(GEN z) { return (2*PI/LOG2)*gtodouble(imag_i(z)); }
+get_toadd(GEN z) { return (2*M_PI/LOG2)*gtodouble(imag_i(z)); }
 
 /* computes the numerical value of wp(z | L), L = om1 Z + om2 Z
  * return NULL if z in L.  If flall=1, compute also wp' */
@@ -2227,7 +2963,7 @@ static GEN
 ellwpnum_all(GEN e, GEN z, long flall, long prec)
 {
   long toadd;
-  pari_sp av = avma, lim, av1;
+  pari_sp av = avma, av1;
   GEN pi2, q, u, y, yp, u1, u2, qn;
   ellred_t T;
   int simple_case;
@@ -2250,7 +2986,7 @@ ellwpnum_all(GEN e, GEN z, long flall, long prec)
   yp = flall? gdiv(gaddsg(1,u), gmul(u1,u2)): NULL;
   toadd = (long)ceil(get_toadd(T.Z));
 
-  av1 = avma; lim = stack_lim(av1,1); qn = q;
+  av1 = avma; qn = q;
   for(;;)
   { /* y += u q^n [ 1/(1-q^n u)^2 + 1/(q^n-u)^2 ] - 2q^n /(1-q^n)^2 */
     /* analogous formula for yp */
@@ -2278,7 +3014,7 @@ ellwpnum_all(GEN e, GEN z, long flall, long prec)
 
     qn = gmul(q,qn);
     if (gexpo(qn) <= - prec2nbits(prec) - 5 - toadd) break;
-    if (low_stack(lim, stack_lim(av1,1)))
+    if (gc_needed(av1,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"ellwp");
       gerepileall(av1, flall? 3: 2, &y, &qn, &yp);
@@ -2450,7 +3186,7 @@ ellzeta(GEN w, GEN z, long prec0)
   if (!simple_case)/* otherwise |u|=1 and all terms in sum are 0 */
   {
     long toadd = (long)ceil(get_toadd(T.Z));
-    pari_sp av1 = avma, lim = stack_lim(av1,1);
+    pari_sp av1 = avma;
     GEN qn;
     for (qn = q;;)
     { /* y += sum q^n ( u/(u*q^n - 1) + 1/(u - q^n) ) */
@@ -2458,7 +3194,7 @@ ellzeta(GEN w, GEN z, long prec0)
       y = gadd(y, gmul(qn,p1));
       qn = gmul(q,qn);
       if (gexpo(qn) <= - prec2nbits(prec) - 5 - toadd) break;
-      if (low_stack(lim, stack_lim(av1,1)))
+      if (gc_needed(av1,1))
       {
         if(DEBUGMEM>1) pari_warn(warnmem,"ellzeta");
         gerepileall(av1,2, &y,&qn);
@@ -2482,7 +3218,7 @@ GEN
 ellsigma(GEN w, GEN z, long flag, long prec0)
 {
   long toadd, prec, n;
-  pari_sp av = avma, lim, av1;
+  pari_sp av = avma, av1;
   GEN zinit, pi, pi2, q, q8, qn2, qn, y, y1, uinv, et, etnew;
   GEN u, uhalf, urn, urninv;
   ellred_t T;
@@ -2525,7 +3261,7 @@ ellsigma(GEN w, GEN z, long flag, long prec0)
   q = gpowgs(q8,8);
   u = gneg_i(u); uinv = ginv(u);
   y = gen_0;
-  av1 = avma; lim = stack_lim(av1,1);
+  av1 = avma;
   qn = q; qn2 = gen_1;
   urn = uhalf; urninv = ginv(uhalf);
   for(n=0;;n++)
@@ -2536,7 +3272,7 @@ ellsigma(GEN w, GEN z, long flag, long prec0)
     qn  = gmul(q,qn);
     urn = gmul(urn,u);
     urninv = gmul(urninv,uinv);
-    if (low_stack(lim, stack_lim(av1,1)))
+    if (gc_needed(av1,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"ellsigma");
       gerepileall(av1,5, &y,&qn,&qn2,&urn,&urninv);
@@ -2584,7 +3320,7 @@ pointell(GEN e, GEN z, long prec)
   v = ellwpnum_all(e,z,1,prec);
   if (!v) { avma = av; return ellinf(); }
   gel(v,1) = gsub(gel(v,1), gdivgs(ell_get_b2(e),12));
-  gel(v,2) = gsub(gel(v,2), gmul2n(ellLHS0(e,gel(v,1)),-1));
+  gel(v,2) = gsub(gel(v,2), gmul2n(ec_h_evalx(e,gel(v,1)),-1));
   return gerepilecopy(av, v);
 }
 
@@ -2648,7 +3384,7 @@ localred_p_get_f(GEN e, GEN p)
   return (nuD - nuj) % 12 ? 2: 1;
 }
 #endif
-/* Here p > 3. e assumed integral, minim = 1 if we only want a minimal model */
+/* p > 3, e integral */
 static GEN
 localred_p(GEN e, GEN p)
 {
@@ -2679,7 +3415,7 @@ localred_p(GEN e, GEN p)
     }
     r = negi( diviuexact(r, 3) );
 
-    t = negi(ellLHS0_i(e,r));
+    t = negi(Zec_h_evalx(e,r));
     if (mpodd(t)) t = addii(t, mulii(pk, p2k));
     t = shifti(t, -1);
 
@@ -2929,53 +3665,250 @@ localred(GEN e, GEN p)
   }
 }
 
-GEN
-elllocalred(GEN e, GEN p)
+/* Given J an ideal in HNF coprime to 2 and z algebraic integer,
+ * return b algebraic integer such that z + 2b in  J */
+static GEN
+approx_mod2(GEN J, GEN z)
 {
-  pari_sp av = avma;
-  checkell_Q(e);
-  if (typ(ell_get_disc(e)) != t_INT)
-    pari_err_TYPE("elllocalred [not an integral curve]",e);
-  if (typ(p) != t_INT) pari_err_TYPE("elllocalred [prime]",p);
-  if (signe(p) <= 0) pari_err_PRIME("elllocalred",p);
-  return gerepileupto(av, localred(e, p));
+  GEN b = z;
+  long i;
+  if (typ(b) == t_INT)
+  {
+    if (mpodd(b)) b = addii(b, gcoeff(J,1,1));
+    return shifti(negi(b),-1);
+  }
+  for (i = lg(J)-1; i >= 1; i--)
+  {
+    if (mpodd(gel(b,i))) b = ZC_add(b, gel(J,i));
+  }
+  return gshift(ZC_neg(b), -1);
 }
 
-/* Return an integral model for e / Q. Set v = NULL (already integral)
- * or the variable change [u,0,0,0], u = 1/t, t > 1 integer making e integral */
+/* Given J an ideal in HNF coprime to 3 and z algebraic integer,
+ * return b algebraic integer such that z + 3b in  J */
 static GEN
-ellintegralmodel(GEN e, GEN *pv)
+approx_mod3(GEN J, GEN z)
 {
-  GEN a = cgetg(6,t_VEC), t, u, L;
-  long i, l, k;
-
-  L = cgetg(1, t_VEC);
-  for (i = 1; i < 6; i++)
+  GEN b = z;
+  long i;
+  if (typ(b) == t_INT)
   {
-    GEN c = gel(e,i);
-    gel(a,i) = c;
-    switch(typ(c))
+    long s = smodis(b,3);
+    if (s)
     {
-      case t_INT: break;
-      case t_FRAC: /* partial factorization */
-        L = shallowconcat(L, gel(Z_factor_limit(gel(c,2), 0),1));
-        break;
-      default: pari_err_TYPE("ellintegralmodel [not a rational curve]",e);
+      GEN Jz = gcoeff(J,1,1);
+      if (smodis(Jz, 3) == s)
+        b = subii(b, Jz);
+      else
+        b = addii(b, Jz);
     }
+    return diviiexact(b, stoi(-3));
   }
-  /* a = [a1, a2, a3, a4, a6] */
-  l = lg(L); if (l == 1) { if (pv) *pv = NULL; return e; }
-  L = ZV_sort_uniq(L);
-  l = lg(L);
-
-  t = gen_1;
-  for (k = 1; k < l; k++)
+  for (i = lg(J)-1; i >= 1; i--)
   {
-    GEN p = gel(L,k);
-    long n = 0, m;
-    for (i = 1; i < 6; i++)
-      if (!gequal0(gel(a,i)))
-      {
+    long s = smodis(gel(b,i), 3);
+    if (!s) continue;
+    if (smodis(gcoeff(J,i,i), 3) == s)
+      b = ZC_sub(b, gel(J,i));
+    else
+      b = ZC_add(b, gel(J,i));
+  }
+  return ZC_Z_divexact(b, stoi(-3));
+}
+
+/* Local reduction, residual characteristic >= 5. E/nf, P prid
+* Output: f, kod, [u,r,s,t], c */
+static GEN
+nflocalred_p(GEN e, GEN P)
+{
+  GEN nf = ellnf_get_nf(e), T,p, modP = nf_to_Fq_init(nf,&P,&T,&p);
+  long c, f, vc4, vc6, vD, kod, m;
+  GEN ch, c4, c6, D, z, pi, piinv;
+
+  c4 = ell_get_c4(e);
+  c6 = ell_get_c6(e);
+  D = ell_get_disc(e);
+  vc4= nfval(nf,c4,P);
+  vc6= nfval(nf,c6,P);
+  vD = nfval(nf,D,P);
+  m = minss(vc4/4, vc6/6);
+  piinv = pr_get_tau(P);
+  if (typ(piinv) == t_MAT) piinv = gel(piinv,1);
+  piinv = gdiv(piinv, p); /* v_P(piinv) = -1, v_Q(piinv) >= 0, Q!=P */
+  pi = nfinv(nf, piinv); /* local uniformizer */
+
+  if(m <= 0) ch = init_ch();
+  else
+  { /* model not minimal */
+    GEN r,s,t, a1,a2,a3, u,ui,ui2,ui4,ui6,ui12;
+    u = nfpow_u(nf,pi,m);
+    ui = nfpow_u(nf,piinv,m);
+    ui2 = nfsqr(nf,ui);
+    ui4 = nfsqr(nf,ui2);
+    ui6 = nfmul(nf,ui2,ui4);
+    ui12 = nfsqr(nf,ui6);
+    c4 = nfmul(nf,c4,ui4); vc4-= 4*m;
+    c6 = nfmul(nf,c6,ui6); vc6-= 6*m;
+    D = nfmul(nf,D,ui12);  vD -= 12*m;
+    a1 = nf_to_scalar_or_basis(nf, ell_get_a1(e));
+    a2 = nf_to_scalar_or_basis(nf, ell_get_a2(e));
+    a3 = nf_to_scalar_or_basis(nf, ell_get_a3(e));
+    s = approx_mod2(idealpow(nf,P,stoi(m)),   a1);
+    r = gsub(a2, nfmul(nf,s,gadd(a1,s)));
+    r = approx_mod3(idealpow(nf,P,stoi(2*m)), r);
+    t = gadd(a3, nfmul(nf,r,a1));
+    t = approx_mod2(idealpow(nf,P,stoi(3*m)), t);
+    ch = mkvec4(u,r,s,t);
+  }
+
+  kod = 0; c = 1;
+  /* minimal at P */
+  if (3*vc4 < vD)
+  { /* v(j) < 0 */
+    if (vc4==0)
+    { /* v(c4) = v(c6) = 0, multiplicative reduction */
+      f = 1; kod = 4+vD;
+      z = Fq_neg(nf_to_Fq(nf,c6,modP), T,p);
+      if (Fq_issquare(z,T,p))
+        c = vD;/* split */
+      else
+        c = odd(vD)?1 : 2; /* non-split */
+    }
+    else
+    { /* v(c4) = 2, v(c6) = 3, potentially multiplicative */
+      GEN Du;
+      f = 2; kod = 2-vD;
+      (void)nfvalrem(nf, D, P, &Du);
+      z = nf_to_Fq(nf, Du, modP);
+      if(odd(vD))
+      {
+        GEN c6u;
+        (void)nfvalrem(nf, c6, P, &c6u);
+        c6u = nf_to_Fq(nf, c6u, modP);
+        z = Fq_mul(z, c6u, T,p);
+      }
+      c = Fq_issquare(z,T,p)? 4: 2;
+    }
+  }
+  else
+  { /* v(j) >= 0 */
+    f = vD? 2: 0;
+    switch(vD)
+    {
+      GEN piinv2, piinv3, piinv4, w;
+      case 0: kod = 0; c = 1; break;
+      case 2: kod = 2; c = 1; break;
+      case 3: kod = 3; c = 2; break;
+      case 4: kod = 4;
+        z = nfmul(nf,c6,nfsqr(nf,piinv));
+        z = nf_to_Fq(nf, z, modP);
+        z = Fq_Fp_mul(z,stoi(-6),T,p);
+        c = Fq_issquare(z,T,p)? 3: 1;
+        break;
+      case 6: kod = -1;
+        piinv2 = nfsqr(nf,piinv);
+        piinv3 = nfmul(nf,piinv,piinv2);
+        z = nfmul(nf,c4,piinv2); z = nf_to_Fq(nf, z, modP);
+        z = Fq_Fp_mul(z,stoi(-3), T,p);
+        w = nfmul(nf,c6,piinv3); w = nf_to_Fq(nf, w, modP);
+        w = Fq_Fp_mul(w,gen_m2, T,p);
+        c = 1 + FqX_nbroots(mkpoln(4, gen_1,gen_0,z,w), T,p);
+        break;
+      case 8: kod = -4;
+        piinv4 = nfpow_u(nf,piinv,4);
+        z = nfmul(nf,c6,piinv4); z = nf_to_Fq(nf, z, modP);
+        z = Fq_Fp_mul(z,stoi(-6),T,p);
+        c = Fq_issquare(z,T,p)? 3: 1;
+        break;
+      case 9: kod = -3; c = 2; break;
+      case 10: kod = -2; c = 1; break;
+    }
+  }
+  return localred_result(f,kod,c,ch);
+}
+static GEN
+nflocalred(GEN e, GEN  pr)
+{
+  GEN p = pr_get_p(pr);
+  if (cmpiu(p, 3) <= 0) pari_err_IMPL("nflocalred (p < 5)");
+  return nflocalred_p(e,pr);
+}
+
+GEN
+elllocalred(GEN e, GEN p)
+{
+  pari_sp av = avma;
+  checkell(e);
+  switch(ell_get_type(e))
+  {
+    case t_ELL_Q:
+      if (typ(ell_get_disc(e)) != t_INT)
+        pari_err_TYPE("elllocalred [not an integral curve]",e);
+      if (typ(p) != t_INT) pari_err_TYPE("elllocalred [prime]",p);
+      if (signe(p) <= 0) pari_err_PRIME("elllocalred",p);
+      return gerepileupto(av, localred(e, p));
+    default: pari_err_TYPE("elllocalred", e);
+    case t_ELL_NF:
+      checkprid(p);
+      return gerepileupto(av, nflocalred(e, p));
+  }
+}
+
+/* typ(c) = t_INT or t_FRAC */
+static GEN
+handle_Q(GEN c, GEN *pd)
+{
+  *pd = (typ(c) == t_INT)? NULL: gel(c,2);
+  return c;
+}
+static GEN
+handle_coeff(GEN nf, GEN c, GEN *pd)
+{
+  *pd = NULL;
+  switch(typ(c))
+  {
+    case t_INT: *pd = NULL; return c;
+    case t_FRAC: *pd = gel(c,2); return c;
+    case t_POL: case t_POLMOD: case t_COL:
+      if (nf)
+      {
+        c = nf_to_scalar_or_basis(nf,c);
+        return handle_Q(Q_content(c), pd);
+      }
+    default: pari_err_TYPE("ellintegralmodel",c);
+      return NULL;
+  }
+}
+/* Return an integral model for e / Q. Set v = NULL (already integral)
+ * or the variable change [u,0,0,0], u = 1/t, t > 1 integer making e integral */
+GEN
+ellintegralmodel(GEN e, GEN *pv)
+{
+  GEN a = cgetg(6,t_VEC), t, u, L, nf;
+  long i, l, k;
+
+  nf = (ell_get_type(e) == t_ELL_NF)?checknf(ellnf_get_nf(e)): NULL;
+  L = cgetg(1, t_VEC);
+  for (i = 1; i < 6; i++)
+  {
+    GEN d;
+    gel(a,i) = handle_coeff(nf, gel(e,i), &d);
+    if (d) /* partial factorization of denominator */
+      L = shallowconcat(L, gel(Z_factor_limit(d, 0),1));
+  }
+  /* a = [a1, a2, a3, a4, a6] */
+  l = lg(L); if (l == 1) { if (pv) *pv = NULL; return e; }
+  L = ZV_sort_uniq(L);
+  l = lg(L);
+
+  t = gen_1;
+  for (k = 1; k < l; k++)
+  {
+    GEN p = gel(L,k);
+    long n = 0, m;
+    for (i = 1; i < 6; i++)
+      if (!gequal0(gel(a,i)))
+      {
         long r = (i == 5)? 6: i; /* a5 is missing */
         m = r * n + Q_pval(gel(a,i), p);
         while (m < 0) { n++; m += r; }
@@ -3107,7 +4040,7 @@ min_get_v(ellmin_t *M, GEN E)
   GEN r, s, t;
   r = diviuexact(subii(mulis(M->u2,M->b2), ell_get_b2(E)), 12);
   s = shifti(subii(M->a1? M->u: gen_0, ell_get_a1(E)), -1);
-  t = shifti(subii(M->a3? M->u3: gen_0, ellLHS0(E,r)), -1);
+  t = shifti(subii(M->a3? M->u3: gen_0, ec_h_evalx(E,r)), -1);
   return mkvec4(M->u,r,s,t);
 }
 
@@ -3616,6 +4549,7 @@ ellrootno_2(GEN e)
   if (d) { /* not minimal */
     ellmin_t M;
     min_set_2(&M, e, d);
+    min_set_D(&M, e);
     e = min_to_ell(&M, e);
   }
   val_init(e, 2,64,&v4,&u, &v6,&v, &vD,&D1);
@@ -3712,6 +4646,7 @@ ellrootno_3(GEN e)
     ellmin_t M;
     min_set_3(&M, e, d);
     min_set_a(&M);
+    min_set_D(&M, e);
     e = min_to_ell(&M, e);
   }
   val_init(e, 3,81, &v4,&u, &v6,&v, &vD,&D1);
@@ -3872,15 +4807,15 @@ ellrootno(GEN e, GEN p)
 /**                                                                **/
 /********************************************************************/
 
-/* assume e has good reduction mod p */
-static long
-ellap_small_goodred(int CM, GEN E, ulong p)
+/* assume p does not divide disc E */
+long
+ellap_CM_fast(GEN E, ulong p, long CM)
 {
   ulong a4, a6;
   if (p == 2) return 3 - cardmod2(E);
   if (p == 3) return 4 - cardmod3(E);
   Fl_ell_to_a4a6(E, p, &a4, &a6);
-  return CM? Fl_elltrace_CM(CM, a4, a6, p): Fl_elltrace(a4, a6, p);
+  return Fl_elltrace_CM(CM, a4, a6, p);
 }
 
 static void
@@ -3894,11 +4829,11 @@ checkell_int(GEN e)
       typ(ell_get_a6(e)) != t_INT) pari_err_TYPE("anellsmall [not an integral model]",e);
 }
 
-static int
-ell_get_CM(GEN e)
+long
+ellQ_get_CM(GEN e)
 {
   GEN j = ell_get_j(e);
-  int CM = 0;
+  long CM = 0;
   if (typ(j) == t_INT) switch(itos_or_0(j))
   {
     case 0:
@@ -3927,7 +4862,7 @@ anellsmall(GEN e, long n0)
   pari_sp av;
   ulong p, m, SQRTn, n = (ulong)n0;
   GEN an, D;
-  int CM;
+  long CM;
 
   checkell_int(e);
   if (n0 <= 0) return cgetg(1,t_VEC);
@@ -3935,7 +4870,7 @@ anellsmall(GEN e, long n0)
     pari_err_IMPL( stack_sprintf("ellan for n >= %lu", LGBITS) );
   SQRTn = (ulong)sqrt(n);
   D = ell_get_disc(e);
-  CM = ell_get_CM(e);
+  CM = ellQ_get_CM(e);
 
   an = cgetg(n+1,t_VECSMALL); an[1] = 1;
   av = avma;
@@ -3970,7 +4905,7 @@ anellsmall(GEN e, long n0)
     }
     else /* good reduction */
     {
-      ap = ellap_small_goodred(CM, e, p);
+      ap = ellap_CM_fast(e, p, CM);
 GOOD_RED:
       if (p <= SQRTn) {
         ulong pk, oldpk = 1;
@@ -4073,7 +5008,7 @@ ellQ_get_Nfa(GEN e, GEN *N, GEN *faN)
 GEN
 elllseries(GEN e, GEN s, GEN A, long prec)
 {
-  pari_sp av = avma, av1, lim;
+  pari_sp av = avma, av1;
   ulong l, n;
   long eps, flun;
   GEN z, cg, v, cga, cgb, s2, K, gs, N;
@@ -4105,7 +5040,7 @@ elllseries(GEN e, GEN s, GEN A, long prec)
   s2 = K = NULL; /* gcc -Wall */
   if (!flun) { s2 = gsubsg(2,s); K = gpow(cg, gsubgs(gmul2n(s,1),2),prec); }
   z = gen_0;
-  av1 = avma; lim = stack_lim(av1,1);
+  av1 = avma;
   for (n = 1; n <= l; n++)
   {
     GEN p1, an, gn = utoipos(n), ns;
@@ -4123,7 +5058,7 @@ elllseries(GEN e, GEN s, GEN A, long prec)
       p1 = gadd(p1, p2);
     }
     z = gadd(z, gmul(p1, an));
-    if (low_stack(lim, stack_lim(av1,1)))
+    if (gc_needed(av1,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"lseriesell");
       z = gerepilecopy(av1,z);
@@ -4138,80 +5073,9 @@ elllseries(GEN e, GEN s, GEN A, long prec)
 /**                                                                **/
 /********************************************************************/
 
-/* h' := h_oo(a) + 1/2 log(denom(a)) */
-static GEN
-hell(GEN e, GEN a, long prec)
-{
-  long n;
-  pari_sp av = avma;
-  GEN pi2 = Pi2n(1, prec);
-  GEN om = ellR_omega(e,prec), w1 = gel(om,1), w2 = gel(om,2);
-  GEN p1, y, z, q, pi2surw, qn, ps;
-
-  pi2surw = gdiv(pi2, w1);
-  z = gmul(real_i(zell(e,a,prec)), pi2surw);
-  q = real_i( expIxy(mpneg(pi2surw), w2, prec) );
-  y = mpsin(z); qn = gen_1; ps = gneg_i(q);
-  for (n = 3; ; n += 2)
-  {
-    qn = gmul(qn, ps);
-    ps = gmul(ps, q);
-    y = gadd(y, gmul(qn, gsin(gmulsg(n,z),prec)));
-    if (gexpo(qn) < -prec2nbits(prec)) break;
-  }
-  p1 = gmul(gsqr(gdiv(gmul2n(y,1), d_ellLHS(e,a))), pi2surw);
-  p1 = gsqr(gsqr(gdiv(p1, gsqr(gsqr(denom(gel(a,1)))))));
-  p1 = gdiv(gmul(p1,q), ell_get_disc(e));
-  p1 = gmul2n(glog(gabs(p1,prec),prec), -5);
-  return gerepileupto(av, gneg(p1));
-}
-
 static GEN
 Q_numer(GEN x) { return typ(x) == t_INT? x: gel(x,1); }
 
-/* h' := h_oo(x) + 1/2 log(denom(x)) */
-static GEN
-hells(GEN e, GEN Q, long prec)
-{
-  GEN b2 = ell_get_b2(e);
-  GEN b4 = ell_get_b4(e);
-  GEN b6 = ell_get_b6(e);
-  GEN b8 = ell_get_b8(e);
-  GEN x = gel(Q,1), w, z, t, mu, b42, b62;
-  long n, lim;
-
-  mu = gmul2n(glog(Q_numer(x),prec),-1);
-  t = ginv(gtofp(x, prec));
-  b42 = gmul2n(b4,1);
-  b62 = gmul2n(b6,1);
-  lim = 15 + prec2nbits(prec);
-  for (n = 3; n < lim; n += 2)
-  {
-    /* 4 + b2 t + 2b4 t^2 + b6 t^3 */
-    w = gmul(t, gaddsg(4, gmul(t, gadd(b2, gmul(t, gadd(b42, gmul(t, b6)))))));
-    /* 1 - (b4 t^2 + 2b6 t^3 + b8 t^4) */
-    z = gsubsg(1, gmul(gsqr(t), gadd(b4, gmul(t, gadd(b62, gmul(t, b8))))));
-    mu = gadd(mu, gmul2n(glog(z,prec), -n));
-    t = gdiv(w, z);
-  }
-  return mu;
-}
-
-static GEN
-hell2(GEN e, GEN x, long prec)
-{
-  GEN e3, ro, r;
-  pari_sp av = avma;
-
-  if (ell_is_inf(x)) return gen_0;
-  ro= ellR_roots(e, prec);
-  e3 = (ellR_get_sign(e) < 0)? gel(ro,1): gel(ro,3);
-  r = addis(gfloor(e3),-1);
-  e = coordch_r(e, r);
-  x = ellchangepoint_r(x, r);
-  return gerepileupto(av, hells(e, x, prec));
-}
-
 /* one root of X^2 - t X + c */
 static GEN
 quad_root(GEN t, GEN c, long prec)
@@ -4224,16 +5088,14 @@ quad_root(GEN t, GEN c, long prec)
 static GEN
 exphellagm(GEN e, GEN z, int flag, long prec)
 {
-  GEN x_a, a, b, e1, r, V = cgetg(1, t_VEC), x = gel(z,1);
+  GEN x_a, ab, a, b, e1, r, V = cgetg(1, t_VEC), x = gel(z,1);
   long n, ex = 5-prec2nbits(prec), p = prec+EXTRAPRECWORD;
 
   if (typ(x) == t_REAL && realprec(x) < p) x = gprec_w(x, p);
-  e1 = ellR_root(e, p);
-  {
-    GEN ab = ellR_ab(e, p);
-    a = gel(ab, 1);
-    b = gel(ab, 2);
-  }
+  ab = ellR_ab(e, p);
+  a = gel(ab, 1);
+  b = gel(ab, 2);
+  e1= gel(obj_check(e,R_ROOTS), 1); /* use maximal accuracy, don't truncate */
   x = gsub(x, e1);
   x = quad_root(gadd(x,b), gmul(a,x), prec);
 
@@ -4280,21 +5142,9 @@ ellR_on_neutral(GEN E, GEN P, long prec)
   return gcmp(x, e1) >= 0;
 }
 
-/* exp( 4h_oo(z) ) */
+/* hoo + 1/2 log(den(x)) */
 static GEN
-exp4hellagm(GEN E, GEN z, long prec)
-{
-  if (!ellR_on_neutral(E, z, prec))
-  {
-    GEN eh = exphellagm(E, elladd(E, z,z), 0, prec);
-    /* h_oo(2P) = 4h_oo(P) - log |2y + a1x + a3| */
-    return gmul(eh, gabs(d_ellLHS(E, z), prec));
-  }
-  return exphellagm(E, z, 1, prec);
-}
-
-GEN
-ellheightoo(GEN E, GEN z, long prec)
+hoo_aux(GEN E, GEN z, GEN d, long prec)
 {
   pari_sp av = avma;
   GEN h;
@@ -4303,25 +5153,45 @@ ellheightoo(GEN E, GEN z, long prec)
   {
     GEN eh = exphellagm(E, elladd(E, z,z), 0, prec);
     /* h_oo(2P) = 4h_oo(P) - log |2y + a1x + a3| */
-    h = gmul(eh, gabs(d_ellLHS(E, z), prec));
+    h = gmul(eh, gabs(ec_dmFdy_evalQ(E, z), prec));
   }
   else
     h = exphellagm(E, z, 1, prec);
+  if (!is_pm1(d)) h = gmul(h, sqri(d));
   return gerepileuptoleaf(av, gmul2n(mplog(h), -2));
 }
+GEN
+ellheightoo(GEN E, GEN z, long prec) { return hoo_aux(E, z, gen_1, prec); }
+
+static GEN
+_hell(GEN E, GEN p, long n, GEN P)
+{ return p? ellpadicheight(E,p,n, P): ellheight(E,P,n); }
+static GEN
+ellheightpairing(GEN E, GEN p, long n, GEN P, GEN Q)
+{
+  pari_sp av = avma;
+  GEN a = _hell(E,p,n, elladd(E,P,Q));
+  GEN b = _hell(E,p,n, ellsub(E,P,Q));
+  return gerepileupto(av, gmul2n(gsub(a,b), -2));
+}
+GEN
+ellheight0(GEN e, GEN a, GEN b, long n)
+{ return b? ellheightpairing(e,NULL,n, a,b): ellheight(e,a,n); }
+GEN
+ellpadicheight0(GEN e, GEN p, long n, GEN P, GEN Q)
+{ return Q? ellheightpairing(e,p,n, P,Q): ellpadicheight(e,p,n, P); }
 
 GEN
-ellheight0(GEN e, GEN a, long flag, long prec)
+ellheight(GEN e, GEN a, long prec)
 {
-  long i, tx = typ(a), lx;
+  long i, lx;
   pari_sp av = avma;
   GEN Lp, x, y, z, phi2, psi2, psi3;
   GEN v, S, b2, b4, b6, b8, a1, a2, a4, c4, D;
 
-  if (flag > 2 || flag < 0) pari_err_FLAG("ellheight");
-  checkell_Q(e); if (!is_matvec_t(tx)) pari_err_TYPE("ellheight",a);
-  lx = lg(a); if (lx==1) return cgetg(1,tx);
-  tx = typ(gel(a,1));
+  checkell_Q(e);
+  checkellpt(a);
+  if (ell_is_inf(a)) return gen_0;
   if ((S = obj_check(e, Q_MINIMALMODEL)))
   { /* switch to minimal model if needed */
     if (lg(S) != 2)
@@ -4336,29 +5206,10 @@ ellheight0(GEN e, GEN a, long flag, long prec)
     e = ellminimalmodel_i(e, &v);
     a = ellchangepoint(a, v);
   }
-  if (is_matvec_t(tx))
-  {
-    z = cgetg(lx,tx);
-    for (i=1; i<lx; i++) gel(z,i) = ellheight0(e,gel(a,i),flag,prec);
-    return z;
-  }
-  if (ell_is_inf(a)) return gen_0;
   if (!oncurve(e,a))
     pari_err_DOMAIN("ellheight", "point", "not on", strtoGENstr("E"),a);
-  psi2 = Q_numer(d_ellLHS(e,a));
+  psi2 = Q_numer(ec_dmFdy_evalQ(e,a));
   if (!signe(psi2)) { avma = av; return gen_0; }
-  switch(flag)
-  {
-    case 0:  z = hell2(e,a,prec); break; /* Tate 4^n */
-    case 1:  z = hell(e,a,prec);  break; /* Silverman's log(sigma) */
-    default:
-    {
-      GEN d = denom(gel(a,1));
-      z = exp4hellagm(e,a,prec); /* = exp(4h_oo(a)), Mestre's AGM */
-      if (!is_pm1(d)) z = gmul(z, sqri(d));
-      z = gmul2n(mplog(z), -2); break;
-    }
-  }
   x = gel(a,1);
   y = gel(a,2);
   b2 = ell_get_b2(e);
@@ -4377,6 +5228,7 @@ ellheight0(GEN e, GEN a, long flag, long prec)
   );
   c4 = ell_get_c4(e);
   D = ell_get_disc(e);
+  z = hoo_aux(e,a,Q_denom(x),prec);  /* hoo(a) + log(den(x))/2 */
   Lp = gel(Z_factor(gcdii(psi2,phi2)),1);
   lx = lg(Lp);
   for (i=1; i<lx; i++)
@@ -4405,79 +5257,71 @@ ellheight0(GEN e, GEN a, long flag, long prec)
 }
 
 GEN
-ghell(GEN e, GEN a, long prec) { return ellheight0(e,a,2,prec); }
-
-GEN
-mathell(GEN e, GEN x, long prec)
+ellpadicheightmatrix(GEN e, GEN p, long n, GEN x)
 {
-  GEN y, h, pdiag;
-  long lx = lg(x),i,j,tx=typ(x);
+  GEN y, D;
+  long lx = lg(x), i, j;
   pari_sp av = avma;
 
-  if (!is_vec_t(tx)) pari_err_TYPE("ellheightmatrix",x);
-  y = cgetg(lx,t_MAT); pdiag = new_chunk(lx);
+  if (!is_vec_t(typ(x))) pari_err_TYPE("ellheightmatrix",x);
+  D = cgetg(lx,t_VEC);
+  y = cgetg(lx,t_MAT);
   for (i=1; i<lx; i++)
   {
-    gel(pdiag,i) = ghell(e,gel(x,i),prec);
+    gel(D,i) = _hell(e,p,n, gel(x,i));
     gel(y,i) = cgetg(lx,t_COL);
   }
   for (i=1; i<lx; i++)
   {
-    gcoeff(y,i,i) = gel(pdiag,i);
+    gcoeff(y,i,i) = gel(D,i);
     for (j=i+1; j<lx; j++)
     {
-      h = ghell(e, elladd(e,gel(x,i),gel(x,j)), prec);
-      h = gsub(h, gadd(gel(pdiag,i),gel(pdiag,j)));
+      GEN h = _hell(e,p,n, elladd(e,gel(x,i),gel(x,j)));
+      h = gsub(h, gadd(gel(D,i),gel(D,j)));
       gcoeff(y,j,i) = gcoeff(y,i,j) = gmul2n(h, -1);
     }
   }
   return gerepilecopy(av,y);
 }
+GEN
+ellheightmatrix(GEN E, GEN x, long n)
+{ return ellpadicheightmatrix(E,NULL,n, x); }
 
+/* Q an actual point, P a point or vector/matrix of points */
 static GEN
-bilhells(GEN e, GEN z1, GEN z2, GEN h2, long prec)
+bilhell_i(GEN E, GEN P, GEN Q, GEN p, long n)
 {
-  long lz1=lg(z1), tx, i;
-  pari_sp av = avma;
-  GEN y,p1,p2;
-
-  if (lz1==1) return cgetg(1,typ(z1));
-
-  tx = typ(gel(z1,1));
-  if (!is_matvec_t(tx))
+  long l = lg(P);
+  if (l==1) return cgetg(1,typ(P));
+  if (!is_matvec_t( typ(gel(P,1)) )) return ellheightpairing(E,p,n,P,Q);
+  else
   {
-    p1 = ghell(e, elladd(e,z1,z2),prec);
-    p2 = gadd(h2, ghell(e,z1,prec));
-    return gerepileupto(av, gmul2n(gsub(p1,p2), -1));
+    GEN y = cgetg(l, typ(P));
+    long i;
+    for (i=1; i<l; i++) gel(y,i) = bilhell_i(E,gel(P,i),Q,p,n);
+    return y;
   }
-  y = cgetg(lz1, typ(z1));
-  for (i=1; i<lz1; i++) gel(y,i) = bilhells(e,gel(z1,i),z2,h2,prec);
-  return y;
 }
-
-GEN
-bilhell(GEN e, GEN z1, GEN z2, long prec)
+static GEN
+ellpadicbil(GEN E, GEN P, GEN Q, GEN p, long n)
 {
-  GEN p1, h2;
-  long tz1 = typ(z1), tz2 = typ(z2);
-  pari_sp av = avma;
-
-  if (!is_matvec_t(tz1)) pari_err_TYPE("ellbil",z1);
-  if (!is_matvec_t(tz2)) pari_err_TYPE("ellbil",z2);
-  if (lg(z1)==1) return cgetg(1,tz1);
-  if (lg(z2)==1) return cgetg(1,tz2);
-
-  tz1 = typ(gel(z1,1));
-  tz2 = typ(gel(z2,1));
-  if (is_matvec_t(tz2))
+  long t1 = typ(P), t2 = typ(Q);
+  if (!is_matvec_t(t1)) pari_err_TYPE("ellbil",P);
+  if (!is_matvec_t(t2)) pari_err_TYPE("ellbil",Q);
+  if (lg(P)==1) return cgetg(1,t1);
+  if (lg(Q)==1) return cgetg(1,t2);
+  t2 = typ(gel(Q,1));
+  if (is_matvec_t(t2))
   {
-    if (is_matvec_t(tz1)) pari_err_TYPE("bilhell",z1);
-    p1 = z1; z1 = z2; z2 = p1;
+    t1 = typ(gel(P,1));
+    if (is_matvec_t(t1)) pari_err_TYPE("bilhell",P);
+    return bilhell_i(E,Q,P, p,n);
   }
-  h2 = ghell(e,z2,prec);
-  return gerepileupto(av, bilhells(e,z1,z2,h2,prec));
+  return bilhell_i(E,P,Q, p,n);
 }
-
+GEN
+bilhell(GEN E, GEN P, GEN Q, long n)
+{ return ellpadicbil(E,P,Q, NULL, n); }
 /********************************************************************/
 /**                                                                **/
 /**                    Modular Parametrization                     **/
@@ -4565,7 +5409,7 @@ elltaniyama(GEN e, long prec)
     gel(X,n+2) = gerepileupto(av2, s1);
   }
   w = gmul(d,derivser(x)); setvalp(w, valp(w)+1);
-  w = gsub(w, ellLHS0(e,x));
+  w = gsub(w, ec_h_evalx(e,x));
   c = cgetg(3,t_VEC);
   gel(c,1) = gcopy(x);
   gel(c,2) = gmul2n(w,-1); return gerepileupto(av, c);
@@ -4576,75 +5420,6 @@ elltaniyama(GEN e, long prec)
 /**                       TORSION POINTS (over Q)                  **/
 /**                                                                **/
 /********************************************************************/
-static int
-smaller_x(GEN p, GEN q)
-{
-  int s = absi_cmp(denom(p), denom(q));
-  return (s<0 || (s==0 && absi_cmp(numer(p),numer(q)) < 0));
-}
-
-/* best generator in cycle of length k */
-static GEN
-best_in_cycle(GEN e, GEN p, long k)
-{
-  GEN p0 = p,q = p;
-  long i;
-
-  for (i=2; i+i<k; i++)
-  {
-    q = elladd(e,q,p0);
-    if (ugcd(i,k)==1 && smaller_x(gel(q,1), gel(p,1))) p = q;
-  }
-  return (gsigne(d_ellLHS(e,p)) < 0)? ellneg_i(e,p): p;
-}
-
-/* <p,q> = E_tors, possibly NULL (= oo), p,q independent unless NULL
- * order p = k, order q = 2 unless NULL */
-static GEN
-tors(GEN e, long k, GEN p, GEN q, GEN v)
-{
-  GEN r;
-  if (q)
-  {
-    long n = k>>1;
-    GEN p1, best = q, np = ellmul_Z(e,p,utoipos(n));
-    if (n % 2 && smaller_x(gel(np,1), gel(best,1))) best = np;
-    p1 = elladd(e,q,np);
-    if (smaller_x(gel(p1,1), gel(best,1))) q = p1;
-    else if (best == np) { p = elladd(e,p,q); q = np; }
-    p = best_in_cycle(e,p,k);
-    if (v)
-    {
-      p = ellchangepointinv(p,v);
-      q = ellchangepointinv(q,v);
-    }
-    r = cgetg(4,t_VEC);
-    gel(r,1) = utoipos(2*k);
-    gel(r,2) = mkvec2(utoipos(k), gen_2);
-    gel(r,3) = mkvec2copy(p, q);
-  }
-  else
-  {
-    if (p)
-    {
-      p = best_in_cycle(e,p,k);
-      if (v) p = ellchangepointinv(p,v);
-      r = cgetg(4,t_VEC);
-      gel(r,1) = utoipos(k);
-      gel(r,2) = mkvec( gel(r,1) );
-      gel(r,3) = mkvec( gcopy(p) );
-    }
-    else
-    {
-      r = cgetg(4,t_VEC);
-      gel(r,1) = gen_1;
-      gel(r,2) = cgetg(1,t_VEC);
-      gel(r,3) = cgetg(1,t_VEC);
-    }
-  }
-  return r;
-}
-
 static GEN
 doellff_get_o(GEN E)
 {
@@ -4653,7 +5428,7 @@ doellff_get_o(GEN E)
 }
 GEN
 ellff_get_o(GEN E)
-{ return obj_checkbuild(E, FF_O, &doellff_get_o); };
+{ return obj_checkbuild(E, FF_O, &doellff_get_o); }
 
 GEN
 elllog(GEN E, GEN a, GEN g, GEN o)
@@ -4675,494 +5450,6 @@ elllog(GEN E, GEN a, GEN g, GEN o)
   return gerepileuptoint(av, r);
 }
 
-/* assume e is defined over Q (use Mazur's theorem) */
-static long
-_orderell(GEN E, GEN P)
-{
-  pari_sp av = avma;
-  GEN tmp, p, a4, dx, dy, d4, d6, D, Pp, Q;
-  forprime_t T;
-  ulong pp;
-  long k;
-  if (ell_is_inf(P)) return 1;
-
-  dx = Q_denom(gel(P,1));
-  dy = Q_denom(gel(P,2));
-  if (ell_is_integral(E)) /* integral model, try Nagell Lutz */
-    if (cmpiu(dx, 4) > 0 || cmpiu(dy, 8) > 0) return 0;
-
-  d4 = Q_denom(ell_get_c4(E));
-  d6 = Q_denom(ell_get_c6(E));
-  D = ell_get_disc (E);
-  /* choose not too small prime p dividing neither a coefficient of the
-     short Weierstrass form nor of P and leading to good reduction      */
-
-  u_forprime_init(&T, 100003, ULONG_MAX);
-  while ( (pp = u_forprime_next(&T)) )
-    if (Rg_to_Fl(d4, pp) && Rg_to_Fl(d6, pp) && Rg_to_Fl(D, pp)
-     && Rg_to_Fl(dx, pp) && Rg_to_Fl(dy, pp)) break;
-
-  /* transform E into short Weierstrass form Ep modulo p
-     and P to Pp on Ep */
-  p = utoipos(pp);
-  tmp = ell_to_a4a6_bc(E, p);
-  a4 = gel(tmp, 1);
-  Pp = FpE_changepointinv(RgV_to_FpV(P, p), gel(tmp,3), p);
-
-  /* check whether the order of Pp on Ep is <= 12 */
-  for (Q = FpE_dbl(Pp, a4, p), k = 2;
-       !ell_is_inf(Q) && k <= 12;
-       Q = FpE_add(Q, Pp, a4, p), k++) /* empty */;
-
-  if (k != 13)
-    /* check over Q; one could also run more tests modulo primes */
-    for (Q = elladd(E, P, P), k = 2;
-        !ell_is_inf(Q) && k <= 12;
-        Q = elladd(E, Q, P), k++) /* empty */;
-
-  avma = av;
-  return (k == 13 ? 0 : k);
-}
-
-GEN
-ellorder(GEN E, GEN P, GEN o)
-{
-  pari_sp av = avma;
-  GEN fg, r, E0 = E;
-  checkell(E); checkellpt(P);
-  if (ell_is_inf(P)) return gen_1;
-  if (ell_get_type(E)==t_ELL_Q)
-  {
-    GEN p = NULL;
-    if (is_rational_t(typ(gel(P,1))) && is_rational_t(typ(gel(P,2))))
-      return utoi( _orderell(E, P) );
-    if (RgV_is_FpV(P,&p) && p)
-    {
-      E = ellinit(E,p,0);
-      if (lg(E)==1) pari_err_IMPL("ellorder for curve with singular reduction");
-    }
-  }
-  checkell_Fq(E);
-  fg = ellff_get_field(E);
-  if (!o) o = ellff_get_o(E);
-  if (typ(fg)==t_FFELT)
-    r = FF_ellorder(E, P, o);
-  else
-  {
-    GEN p = fg, e = ellff_get_a4a6(E);
-    GEN Pp = FpE_changepointinv(RgE_to_FpE(P,p), gel(e,3), p);
-    r = FpE_order(Pp, o, gel(e,1), p);
-  }
-  if (E != E0) obj_free(E);
-  return gerepileuptoint(av, r);
-}
-
-GEN
-orderell(GEN e, GEN z) { return ellorder(e,z,NULL); }
-
-/* Using Lutz-Nagell */
-
-/* p in Z[X] of degree 3. Return vector of x/4, x integral root of p */
-static GEN
-ratroot(GEN p)
-{
-  GEN L, a, ld;
-  long i, t, v = ZX_valrem(p, &p);
-
-  if (v == 3) return ellinf();
-  if (v == 2) return mkvec2(gen_0, gmul2n(negi(gel(p,2)), -2));
-
-  L = cgetg(4,t_VEC); t = 1;
-  if (v == 1) gel(L,t++) = gen_0;
-  ld = divisors(gel(p,2));
-  for (i=1; i<lg(ld); i++)
-  {
-    a = gel(ld,i);
-    if (!signe(poleval(p,a))) gel(L,t++) = gmul2n(a, -2);
-    a = negi(a);
-    if (!signe(poleval(p,a))) gel(L,t++) = gmul2n(a, -2);
-  }
-  setlg(L,t); return L;
-}
-
-static int
-is_new_torsion(GEN e, GEN v, GEN p, long t2) {
-  GEN pk = p, pkprec = NULL;
-  long k,l;
-
-  for (k=2; k<=6; k++)
-  {
-    pk = elladd(e,pk,p); /* = [k] p */
-    if (ell_is_inf(pk)) return 1;
-
-    for (l=2; l<=t2; l++)
-      if (gequal(gel(pk,1),gmael(v,l,1))) return 1;
-
-    if (pkprec && k<=5)
-      if (gequal(gel(pk,1),gel(pkprec,1))) return 1;
-    pkprec=pk;
-  }
-  return 0;
-}
-
-static GEN
-nagelllutz(GEN e)
-{
-  GEN ld, pol, p1, lr, r, v, w2, w3;
-  long i, j, nlr, t, t2, k, k2;
-  pari_sp av=avma;
-
-  e = ellintegralmodel(e, &v);
-  pol = RgX_rescale(RHSpol(e,NULL), utoipos(4));
-  r = cgetg(17, t_VEC);
-  gel(r,1) = ellinf();
-  lr = ratroot(pol); nlr=lg(lr)-1;
-  for (t=1,i=1; i<=nlr; i++)
-  {
-    GEN x = gel(lr,i), y = gmul2n(gneg(ellLHS0(e,x)), -1);
-    gel(r,++t) = mkvec2(x, y);
-  }
-  ld = absi_factor(gmul2n(ell_get_disc(e), 4));
-  p1 = gel(ld,2); k = lg(p1);
-  for (i=1; i<k; i++) gel(p1,i) = shifti(gel(p1,i), -1);
-  ld = divisors(ld);
-  for (t2=t,j=1; j<lg(ld); j++)
-  {
-    GEN d = gel(ld,j);
-    lr = ratroot(ZX_Z_sub(pol, shifti(sqri(d), 6)));
-    for (i=1; i<lg(lr); i++)
-    {
-      GEN x = gel(lr,i), y = gmul2n(gsub(d, ellLHS0(e,x)), -1);
-      p1 = mkvec2(x, y);
-      if (is_new_torsion(e,r,p1,t2))
-      {
-        gel(r,++t) = p1;
-        gel(r,++t) = mkvec2(x, gsub(y, d));
-      }
-    }
-  }
-  if (t == 1) { avma = av; return tors(e,1,NULL,NULL,v); }
-
-  if (nlr < 3)
-  {
-    w2 = mkvec( utoipos(t) );
-    for (k=2; k<=t; k++)
-      if (_orderell(e,gel(r,k)) == t) break;
-    if (k>t) pari_err_BUG("elltors (bug1)");
-
-    w3 = mkvec( gel(r,k) );
-  }
-  else
-  {
-    if (t&3) pari_err_BUG("elltors (bug2)");
-    t2 = t>>1;
-    w2 = mkvec2(utoipos(t2), gen_2);
-    for (k=2; k<=t; k++)
-      if (_orderell(e,gel(r,k)) == t2) break;
-    if (k>t) pari_err_BUG("elltors (bug3)");
-
-    p1 = ellmul_Z(e,gel(r,k),utoipos(t>>2));
-    k2 = (!ell_is_inf(p1) && gequal(gel(r,2),p1))? 3: 2;
-    w3 = mkvec2(gel(r,k), gel(r,k2));
-  }
-  if (v)
-  {
-    gel(v,1) = ginv(gel(v,1));
-    w3 = ellchangepoint(w3,v);
-  }
-  return gerepilecopy(av, mkvec3(utoipos(t), w2,w3));
-}
-
-/* Using Doud's algorithm */
-
-/* finds a bound for #E_tor */
-static long
-torsbound(GEN e)
-{
-  GEN D = ell_get_disc(e);
-  pari_sp av = avma, av2;
-  long m, b, bold, nb;
-  forprime_t S;
-  int CM = ell_get_CM(e);
-  nb = expi(D) >> 3;
-  /* nb = number of primes to try ~ 1 prime every 8 bits in D */
-  b = bold = 5040; /* = 2^4 * 3^2 * 5 * 7 */
-  m = 0;
-  (void)u_forprime_init(&S, 3, ULONG_MAX);
-  av2 = avma;
-  while (m < nb || (b > 12 && b != 16))
-  {
-    ulong p = u_forprime_next(&S);
-    if (!p) pari_err_BUG("torsbound [ran out of primes]");
-    if (!umodiu(D, p)) continue;
-
-    b = ugcd(b, p+1 - ellap_small_goodred(CM, e, p));
-    avma = av2;
-    if (b == 1) break;
-    if (b == bold) m++; else { bold = b; m = 0; }
-  }
-  avma = av; return b;
-}
-
-static GEN
-myround(GEN x, long *e)
-{
-  GEN y = grndtoi(x,e);
-  if (*e > -5 && prec2nbits(gprecision(x)) < gexpo(y) - 10)
-    pari_err_PREC("elltors");
-  return y;
-}
-
-/* E the curve, w in C/Lambda ~ E of order n, returns q = pointell(w) as a
- * rational point on the curve, or NULL if q is not rational. */
-static GEN
-torspnt(GEN E, GEN w, long n, long prec)
-{
-  GEN p = cgetg(3,t_VEC), q = pointell(E, w, prec);
-  long e;
-  gel(p,1) = gmul2n(myround(gmul2n(gel(q,1),2), &e),-2);
-  if (e > -5 || typ(gel(p,1)) == t_COMPLEX) return NULL;
-  gel(p,2) = gmul2n(myround(gmul2n(gel(q,2),3), &e),-3);
-  if (e > -5 || typ(gel(p,2)) == t_COMPLEX) return NULL;
-  return (oncurve(E,p)
-      && ell_is_inf(ellmul_Z(E,p,utoipos(n)))
-      && _orderell(E,p) == n)? p: NULL;
-}
-
-static GEN
-elltors_doud(GEN e)
-{
-  long B, i, ord, prec, k = 1;
-  pari_sp av=avma;
-  GEN v,w,w1,w22,w1j,w12,p,tor1,tor2;
-  GEN om;
-
-  e = ellintegralmodel(e, &v);
-  B = torsbound(e); /* #E_tor | B */
-  if (B == 1) { avma = av; return tors(e,1,NULL,NULL, v); }
-
-  /* prec >= size of sqrt(D) */
-  prec = DEFAULTPREC + ((lgefint(ell_get_disc(e))-2) >> 1);
-  om = ellR_omega(e, prec);
-  w1 = gel(om,1);
-  w22 = gmul2n(gel(om,2),-1);
-  if (B % 4)
-  { /* cyclic of order 1, p, 2p, p <= 5 */
-    p = NULL;
-    for (i=10; i>1; i--)
-    {
-      if (B%i != 0) continue;
-      w1j = gdivgs(w1,i);
-      p = torspnt(e,w1j,i,prec);
-      if (!p && i%2==0)
-      {
-        p = torspnt(e,gadd(w22,w1j),i,prec);
-        if (!p) p = torspnt(e,gadd(w22,gmul2n(w1j,1)),i,prec);
-      }
-      if (p) { k = i; break; }
-    }
-    return gerepileupto(av, tors(e,k,p,NULL, v));
-  }
-
-  ord = 0; tor1 = tor2 = NULL;
-  w12 = gmul2n(w1,-1);
-  if ((p = torspnt(e,w12,2,prec))) { tor1 = p; ord++; }
-  w = w22;
-  if ((p = torspnt(e,w,2,prec))) { tor2 = p; ord += 2; }
-  if (!ord)
-  {
-    w = gadd(w12,w22);
-    if ((p = torspnt(e,w,2,prec))) { tor2 = p; ord += 2; }
-  }
-  p = NULL;
-  switch(ord)
-  {
-    case 0: /* no point of order 2 */
-      for (i=9; i>1; i-=2)
-      {
-        if (B%i != 0) continue;
-        w1j = gdivgs(w1,i);
-        p = torspnt(e,w1j,i,prec);
-        if (p) { k = i; break; }
-      }
-      break;
-
-    case 1: /* 1 point of order 2: w1 / 2 */
-      for (i=12; i>2; i-=2)
-      {
-        if (B%i != 0) continue;
-        w1j = gdivgs(w1,i);
-        p = torspnt(e,w1j,i,prec);
-        if (!p && i%4==0) p = torspnt(e,gadd(w22,w1j),i,prec);
-        if (p) { k = i; break; }
-      }
-      if (!p) { p = tor1; k = 2; }
-      break;
-
-    case 2: /* 1 point of order 2: w = w2/2 or (w1+w2)/2 */
-      for (i=5; i>1; i-=2)
-      {
-        if (B%i != 0) continue;
-        w1j = gdivgs(w1,i);
-        p = torspnt(e,gadd(w,w1j),2*i,prec);
-        if (p) { k = 2*i; break; }
-      }
-      if (!p) { p = tor2; k = 2; }
-      tor2 = NULL; break;
-
-    case 3: /* 2 points of order 2: w1/2 and w2/2 */
-      for (i=8; i>2; i-=2)
-      {
-        if (B%(2*i) != 0) continue;
-        w1j = gdivgs(w1,i);
-        p = torspnt(e,w1j,i,prec);
-        if (p) { k = i; break; }
-      }
-      if (!p) { p = tor1; k = 2; }
-      break;
-  }
-  return gerepileupto(av, tors(e,k,p,tor2, v));
-}
-
-/* return a rational point of order pk = p^k on E, or NULL if E(Q)[k] = O.
- * *fk is either NULL (pk = 4 or prime) or elldivpol(p^(k-1)).
- * Set *fk to elldivpol(p^k) */
-static GEN
-tpoint(GEN E, long pk, GEN *fk)
-{
-  GEN f = elldivpol(E,pk,0), g = *fk, v;
-  long i, l;
-  *fk = f;
-  if (g) f = RgX_div(f, g);
-  v = nfrootsQ(f); l = lg(v);
-  for (i = 1; i < l; i++)
-  {
-    GEN x = gel(v,i);
-    GEN y = ellordinate_i(E,x,0);
-    if (lg(y) != 1) return mkvec2(x,gel(y,1));
-  }
-  return NULL;
-}
-/* return E(Q)[2] */
-static GEN
-t2points(GEN E, GEN *f2)
-{
-  long i, l;
-  GEN v;
-  *f2 = RHSpol(E,NULL);
-  v = nfrootsQ(*f2); l = lg(v);
-  for (i = 1; i < l; i++)
-  {
-    GEN x = gel(v,i);
-    GEN y = ellordinate_i(E,x,0);
-    if (lg(y) != 1) gel(v,i) = mkvec2(x,gel(y,1));
-  }
-  return v;
-}
-
-static GEN
-elltors_divpol(GEN E)
-{
-  GEN T2 = NULL, p, P, Q, v;
-  long v2, r2, B;
-
-  E = ellintegralmodel(E, &v);
-  B = torsbound(E); /* #E_tor | B */
-  if (B == 1) return tors(E,1,NULL,NULL, v);
-  v2 = vals(B); /* bound for v_2(point order) */
-  B >>= v2;
-  p = const_vec(9, NULL);
-  r2 = 0;
-  if (v2) {
-    GEN f;
-    T2 = t2points(E, &f);
-    switch(lg(T2)-1)
-    {
-      case 0:  v2 = 0; break;
-      case 1:  r2 = 1; if (v2 == 4) v2 = 3; break;
-      default: r2 = 2; v2--; break; /* 3 */
-    }
-    if (v2) gel(p,2) = gel(T2,1);
-    /* f = f_2 */
-    if (v2 > 1) { gel(p,4) = tpoint(E,4, &f); if (!gel(p,4)) v2 = 1; }
-    /* if (v2>1) now f = f4 */
-    if (v2 > 2) { gel(p,8) = tpoint(E,8, &f); if (!gel(p,8)) v2 = 2; }
-  }
-  B <<= v2;
-  if (B % 3 == 0) {
-    GEN f3 = NULL;
-    gel(p,3) = tpoint(E,3,&f3);
-    if (!gel(p,3)) B /= (B%9)? 3: 9;
-    if (gel(p,3) && B % 9 == 0)
-    {
-      gel(p,9) = tpoint(E,9,&f3);
-      if (!gel(p,9)) B /= 3;
-    }
-  }
-  if (B % 5 == 0) {
-    GEN junk = NULL;
-    gel(p,5) = tpoint(E,5,&junk);
-    if (!gel(p,5)) B /= 5;
-  }
-  if (B % 7 == 0) {
-    GEN junk = NULL;
-    gel(p,7) = tpoint(E,7,&junk);
-    if (!gel(p,7)) B /= 7;
-  }
-  /* B is the exponent of E_tors(Q), r2 is the rank of its 2-Sylow,
-   * for i > 1, p[i] is a point of order i if one exists and i is a prime power
-   * and NULL otherwise */
-  if (r2 == 2) /* 2 cyclic factors */
-  { /* C2 x C2 */
-    if (B == 2) return tors(E,2, gel(T2,1), gel(T2,2), v);
-    else if (B == 6)
-    { /* C2 x C6 */
-      P = elladd(E, gel(p,3), gel(T2,1));
-      Q = gel(T2,2);
-    }
-    else
-    { /* C2 x C4 or C2 x C8 */
-      P = gel(p, B);
-      Q = gel(T2,2);
-      if (gequal(Q, ellmul(E, P, utoipos(B>>1)))) Q = gel(T2,1);
-    }
-  }
-  else /* cyclic */
-  {
-    Q = NULL;
-    if (v2)
-    {
-      if (B>>v2 == 1)
-        P = gel(p, B);
-      else
-        P = elladd(E, gel(p, B>>v2), gel(p,1<<v2));
-    }
-    else P = gel(p, B);
-  }
-  return tors(E,B, P, Q, v);
-}
-GEN
-elltors(GEN e)
-{
-  pari_sp av = avma;
-  checkell_Q(e);
-  return gerepileupto(av, elltors_divpol(e));
-}
-
-GEN
-elltors0(GEN e, long flag)
-{
-  checkell_Q(e);
-  switch(flag)
-  {
-    case 0: return elltors(e);
-    case 1: return nagelllutz(e);
-    case 2: return elltors_doud(e);
-    default: pari_err_FLAG("elltors");
-  }
-  return NULL; /* not reached */
-}
-
 GEN
 ellweilpairing(GEN E, GEN P, GEN Q, GEN m)
 {
@@ -5201,18 +5488,18 @@ elltatepairing(GEN E, GEN P, GEN Q, GEN m)
   }
 }
 
-/* E/Q, return cardinal including the (possible) ramified point */
+/* E/Q, return cardinality including the (possible) ramified point */
 static GEN
-ellcard_ram(GEN E, GEN p)
+ellcard_ram(GEN E, GEN p, int *good_red)
 {
   GEN a4, a6, D = Rg_to_Fp(ell_get_disc(E), p);
   if (!signe(D))
   {
     pari_sp av = avma;
-    int good_red;
-    GEN ap = is_minimal_ap(E, p, &good_red);
+    GEN ap = is_minimal_ap(E, p, good_red);
     return gerepileuptoint(av, subii(addiu(p,1), ap));
   }
+  *good_red = 1;
   if (equaliu(p,2)) return utoi(cardmod2(E));
   if (equaliu(p,3)) return utoi(cardmod3(E));
   ell_to_a4a6(E,p,&a4,&a6);
@@ -5223,10 +5510,15 @@ static GEN
 checkellp(GEN E, GEN p, const char *s)
 {
   GEN q;
-  if (p)
+  if (p) switch(typ(p))
   {
-    if (typ(p)!=t_INT) pari_err_TYPE(s,p);
-    if (cmpis(p, 2) < 0) pari_err_DOMAIN(s,"p", "<", gen_2, p);
+    case t_INT:
+      if (cmpis(p, 2) < 0) pari_err_DOMAIN(s,"p", "<", gen_2, p);
+      break;
+    case t_VEC:
+      q = get_prid(p);
+      if (q) { p = q; break; }
+    default: pari_err_TYPE(s,p);
   }
   checkell(E);
   switch(ell_get_type(E))
@@ -5241,6 +5533,7 @@ checkellp(GEN E, GEN p, const char *s)
       q = ellff_get_p(E);
       if (p && !equalii(p, q)) pari_err_TYPE(s,p);
       return q;
+    case t_ELL_NF:
     case t_ELL_Q:
       if (p) return p;
     default:
@@ -5254,6 +5547,7 @@ ellap(GEN E, GEN p)
 {
   pari_sp av = avma;
   GEN q, card;
+  int goodred;
   p = checkellp(E, p, "ellap");
   switch(ell_get_type(E))
   {
@@ -5264,7 +5558,7 @@ ellap(GEN E, GEN p)
     q = FF_q(ellff_get_field(E)); card = ellff_get_card(E);
     break;
   case t_ELL_Q:
-    q = p; card = ellcard_ram(E, p);
+    q = p; card = ellcard_ram(E, p, &goodred);
     break;
   default:
     pari_err_TYPE("ellap",E);
@@ -5301,9 +5595,9 @@ ellcard(GEN E, GEN p)
   case t_ELL_Q:
     {
       pari_sp av = avma;
-      GEN N = ellcard_ram(E, p);
-      GEN D = Rg_to_Fp(ell_get_disc(E), p);
-      if (!signe(D)) N = subis(N, 1); /* remove singular point */
+      int goodred;
+      GEN N = ellcard_ram(E, p, &goodred);
+      if (!goodred) N = subis(N, 1); /* remove singular point */
       return gerepileuptoint(av, N);
     }
   default:
@@ -5515,6 +5809,63 @@ ellfromj(GEN j)
   return ellfromj_simple(j);
 }
 
+/********************************************************************/
+/**                                                                **/
+/**                       IS SUPERSINGULAR                         **/
+/**                                                                **/
+/********************************************************************/
+
+int
+elljissupersingular(GEN x)
+{
+  pari_sp av = avma;
+  int res;
+
+  if (typ(x) == t_INTMOD) {
+    GEN p = gel(x, 1);
+    GEN j = gel(x, 2);
+    res = Fp_elljissupersingular(j, p);
+  } else if (typ(x) == t_FFELT) {
+    GEN j = FF_to_FpXQ_i(x);
+    GEN p = FF_p_i(x);
+    GEN T = FF_mod(x);
+    res = FpXQ_elljissupersingular(j, T, p);
+  } else {
+    pari_err_TYPE("elljissupersingular", x);
+    return 0; /*NOT REACHED*/
+  }
+  avma = av;
+  return res;
+}
+
+int
+ellissupersingular(GEN E, GEN p)
+{
+  if (typ(E)!=t_VEC && !p)
+    return elljissupersingular(E);
+  p = checkellp(E, p, "ellissupersingular");
+  switch(ell_get_type(E))
+  {
+  case t_ELL_Fp:
+  case t_ELL_Fq:
+      return elljissupersingular(ell_get_j(E));
+    break;
+  case t_ELL_Q:
+    {
+      pari_sp av = avma;
+      GEN j = ell_get_j(E);
+      int res;
+      if (typ(j)==t_FRAC && dvdii(gel(j,2), p)) return 0;
+      res = Fp_elljissupersingular(Rg_to_Fp(j, p), p);
+      avma = av; return res;
+    }
+    break;
+  default:
+    pari_err_TYPE("ellissupersingular",E);
+  }
+  return 0; /* Not reached */
+}
+
 /* n <= 4, N is the characteristic of the base ring or NULL (char 0) */
 static GEN
 elldivpol4(GEN e, GEN N, long n, long v)
@@ -5530,12 +5881,12 @@ elldivpol4(GEN e, GEN N, long n, long v)
   {
     GEN b10 = gsub(gmul(b2, b8), gmul(b4, b6));
     GEN b12 = gsub(gmul(b8, b4), gsqr(b6));
-    res = mkpoln(7, N? modsi(2, N): gen_2,b2,gmulsg(5,b4),gmulsg(10,b6),gmulsg(10,b8),b10,b12);
+    res = mkpoln(7, N? modsi(2,N): gen_2,b2,gmulsg(5,b4),gmulsg(10,b6),gmulsg(10,b8),b10,b12);
   }
   setvarn(res, v); return res;
 }
 
-/* T = (2y + a1x + a3)^2 modulo the curve equation. Store elldivpol(e,n,v)
+/* T = (2y + a1x + a3)^4 modulo the curve equation. Store elldivpol(e,n,v)
  * in t[n]. N is the caracteristic of the base ring or NULL (char 0) */
 static GEN
 elldivpol0(GEN e, GEN t, GEN N, GEN T, long n, long v)
@@ -5571,7 +5922,7 @@ GEN
 elldivpol(GEN e, long n, long v)
 {
   pari_sp av = avma;
-  GEN ret, D, N;
+  GEN f, D, N;
   checkell(e); D = ell_get_disc(e);
   if (v==-1) v = 0;
   if (varncmp(gvar(D), v) <= 0) pari_err_PRIORITY("elldivpol", e, "<=", v);
@@ -5579,16 +5930,76 @@ elldivpol(GEN e, long n, long v)
   if (!signe(N)) N = NULL;
   if (n<0) n = -n;
   if (n==1 || n==3)
-    ret = elldivpol4(e, N, n, v);
+    f = elldivpol4(e, N, n, v);
   else
   {
-    GEN d2 = RHSpol(e, N); /* (2y + a1x + 3)^2 mod E */
+    GEN d2 = ec_bmodel(e); /* (2y + a1x + 3)^2 mod E */
     setvarn(d2,v);
+    if (N && !mod2(N)) { gel(d2,5) = modsi(4,N); d2 = normalizepol(d2); }
     if (n <= 4)
-      ret = elldivpol4(e, N, n, v);
+      f = elldivpol4(e, N, n, v);
     else
-      ret = elldivpol0(e, const_vec(n,NULL), N,RgX_sqr(d2), n, v);
-    if (n%2==0) ret = RgX_mul(ret, d2);
+      f = elldivpol0(e, const_vec(n,NULL), N,RgX_sqr(d2), n, v);
+    if (n%2==0) f = RgX_mul(f, d2);
   }
-  return gerepilecopy(av, ret);
+  return gerepilecopy(av, f);
+}
+
+/* return [phi_n, (psi_n)^2] such that x[nP] = phi_n / (psi_n)^2 */
+GEN
+ellxn(GEN e, long n, long v)
+{
+  pari_sp av = avma;
+  GEN d2, D, N, A, B;
+  checkell(e); D = ell_get_disc(e);
+  if (v==-1) v = 0;
+  if (varncmp(gvar(D), v) <= 0) pari_err_PRIORITY("elldivpol", e, "<=", v);
+  N = characteristic(D);
+  if (!signe(N)) N = NULL;
+  if (n < 0) n = -n;
+  d2 = ec_bmodel(e); /* (2y + a1x + 3)^2 mod E */
+  setvarn(d2,v);
+  if (N && !mod2(N)) { gel(d2,5) = modsi(4,N); d2 = normalizepol(d2); }
+  if (n == 0)
+  {
+    A = pol_0(v);
+    B = pol_0(v);
+  }
+  else if (n == 1)
+  {
+    A = pol_1(v);
+    B = pol_x(v);
+  }
+  else if (n == 2)
+  {
+    GEN b4 = ell_get_b4(e);
+    GEN b6 = ell_get_b6(e);
+    GEN b8 = ell_get_b8(e);
+    A = d2;
+    /* phi_2 = x^4 - b4*x^2 - 2b6*x - b8 */
+    B = mkpoln(5, gen_1, gen_0, gneg(b4), gmul2n(gneg(b6),1), gneg(b8));
+    setvarn(B,v);
+  }
+  else
+  {
+    GEN t = const_vec(n+1,NULL), T = RgX_sqr(d2);
+    GEN f = elldivpol0(e, t, N, T, n, v); /* f_n / d2^(n odd)*/
+    GEN g = elldivpol0(e, t, N, T, n-1, v); /* f_{n-1} / d2^(n even) */
+    GEN h = elldivpol0(e, t, N, T, n+1, v); /* f_{n+1} / d2^(n even) */
+    GEN f2 = RgX_sqr(f), u = RgX_mul(g,h);
+    if (!odd(n))
+      A = RgX_mul(f2, d2);
+    else
+    { A = f2; u = RgX_mul(u,d2); }
+    /* A = psi_n^2, u = psi_{n-1} psi_{n+1} */
+    B = RgX_sub(RgX_mulXn(A,1), u);
+  }
+  return gerepilecopy(av, mkvec2(B,A));
+}
+
+GEN
+ellpadicfrobenius(GEN E, ulong p, long n)
+{
+  checkell_Q(E);
+  return hyperellpadicfrobenius(ec_bmodel(E), p, n);
 }
diff --git a/src/basemath/ellisog.c b/src/basemath/ellisog.c
new file mode 100644
index 0000000..de6cc1b
--- /dev/null
+++ b/src/basemath/ellisog.c
@@ -0,0 +1,564 @@
+/* Copyright (C) 2014 The PARI group.
+
+This file is part of the PARI/GP package.
+
+PARI/GP 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. It is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY WHATSOEVER.
+
+Check the License for details. You should have received a copy of it, along
+with the package; see the file 'COPYING'. If not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+#include "pari.h"
+
+/* Return 1 if the point Q is a Weierstrass (2-torsion) point of the
+ * curve E, return 0 otherwise */
+static long
+ellisweierstrasspoint(GEN E, GEN Q)
+{ return ell_is_inf(Q) || gequal0(ec_dmFdy_evalQ(E, Q)); }
+
+
+/* Given an elliptic curve E = [a1, a2, a3, a4, a6] and t,w in the ring of
+ * definition of E, return the curve
+ *  E' = [a1, a2, a3, a4 - 5t, a6 - (E.b2 t + 7w)] */
+static GEN
+make_velu_curve(GEN E, GEN t, GEN w)
+{
+  GEN A4, A6, a1 = ell_get_a1(E), a2 = ell_get_a2(E), a3 = ell_get_a3(E);
+  A4 = gsub(ell_get_a4(E), gmulsg(5L, t));
+  A6 = gsub(ell_get_a6(E), gadd(gmul(ell_get_b2(E), t), gmulsg(7L, w)));
+  return mkvec5(a1,a2,a3,A4,A6);
+}
+
+/* If phi = (f(x)/h(x)^2, g(x,y)/h(x)^3) is an isogeny, return the
+ * variables x and y in a vecsmall */
+INLINE GEN
+get_isog_vars(GEN phi)
+{
+  long vx = varn(gel(phi, 1));
+  long vy = varn(gel(phi, 2));
+  if (vy == vx) vy = varn(leading_term(gel(phi, 2)));
+  return mkvecsmall2(vx, vy);
+}
+
+INLINE GEN
+substvec(GEN target, GEN vars, GEN in)
+{
+  long nvars = lg(vars) - 1, i;
+  GEN res = target;
+  for (i = 1; i <= nvars; ++i)
+    res = gsubst(res, vars[i], gel(in, i));
+  return res;
+}
+/* Given isogenies F:E' -> E and G:E'' -> E', return the composite
+ * isogeny F o G:E'' -> E */
+static GEN
+ellcompisog(GEN F, GEN G)
+{
+  pari_sp av = avma;
+  GEN Gh, Gh2, Gh3, f, g, h, z, numz, denz, denz2, in, comp;
+
+  checkellisog(F);
+  checkellisog(G);
+  Gh = gel(G,3); Gh2 = gsqr(Gh); Gh3 = gmul(Gh, Gh2);
+  in = mkvec2(gdiv(gel(G,1), Gh2), gdiv(gel(G,2), Gh3));
+  comp = substvec(F, get_isog_vars(F), in);
+  f = gel(comp,1);
+  g = gel(comp,2);
+  z = gel(comp,3); numz = numer(z); denz = denom(z);
+  if (!issquareall(denom(f), &h))
+    pari_err_BUG("ellcompisog (denominator of composite abscissa not square)");
+  h  = RgX_mul(h, numz);
+  h = RgX_Rg_div(h, leading_term(h));
+
+  denz2 = gsqr(denz);
+  f = RgX_mul(numer(f), denz2);
+  g = RgX_mul(numer(g), gmul(denz,denz2));
+  return gerepilecopy(av, mkvec3(f,g,h));
+}
+
+/* Given an isogeny phi from ellisogeny() and a point P in the domain of phi,
+ * return phi(P) */
+GEN
+ellisogenyapply(GEN phi, GEN P)
+{
+  pari_sp ltop = avma;
+  GEN f, g, h, img_f, img_g, img_h, img_h2, img_h3, img, vars, tmp;
+  long vx, vy;
+  if (lg(P) == 4) return ellcompisog(phi,P);
+  checkellisog(phi);
+  checkellpt(P);
+  if (ell_is_inf(P)) return ellinf();
+  f = gel(phi, 1);
+  g = gel(phi, 2);
+  h = gel(phi, 3);
+  vars = get_isog_vars(phi);
+  vx = vars[1];
+  vy = vars[2];
+  img_h = poleval(h, gel(P, 1));
+  if (gequal0(img_h)) { avma = ltop; return ellinf(); }
+
+  img_h2 = gsqr(img_h);
+  img_h3 = gmul(img_h, img_h2);
+  img_f = poleval(f, gel(P, 1));
+  /* FIXME: This calculation of g is perhaps not as efficient as it could be */
+  tmp = gsubst(g, vx, gel(P, 1));
+  img_g = gsubst(tmp, vy, gel(P, 2));
+  img = cgetg(3, t_VEC);
+  gel(img, 1) = gdiv(img_f, img_h2);
+  gel(img, 2) = gdiv(img_g, img_h3);
+  return gerepileupto(ltop, img);
+}
+
+/* isog = [f, g, h] = [x, y, 1] = identity */
+static GEN
+isog_identity(long vx, long vy)
+{ return mkvec3(pol_x(vx), pol_x(vy), pol_1(vx)); }
+
+/* Returns an updated value for isog based (primarily) on tQ and uQ. Used to
+ * iteratively compute the isogeny corresponding to a subgroup generated by a
+ * given point. Ref: Equation 8 in Velu's paper.
+ * isog = NULL codes the identity */
+static GEN
+update_isogeny_polys(GEN isog, GEN E, GEN Q, GEN tQ, GEN uQ, long vx, long vy)
+{
+  pari_sp ltop = avma, av;
+  GEN xQ = gel(Q, 1), yQ = gel(Q, 2);
+  GEN rt = deg1pol_shallow(gen_1, gneg(xQ), vx);
+  GEN a1 = ell_get_a1(E), a3 = ell_get_a3(E);
+
+  GEN gQx = ec_dFdx_evalQ(E, Q);
+  GEN gQy = ec_dFdy_evalQ(E, Q);
+  GEN tmp1, tmp2, tmp3, tmp4, f, g, h, rt_sqr, res;
+
+  /* g -= uQ * (2 * y + E.a1 * x + E.a3)
+   *   + tQ * rt * (E.a1 * rt + y - yQ)
+   *   + rt * (E.a1 * uQ - gQx * gQy) */
+  av = avma;
+  tmp1 = gmul(uQ, gadd(deg1pol_shallow(gen_2, gen_0, vy),
+                       deg1pol_shallow(a1, a3, vx)));
+  tmp1 = gerepileupto(av, tmp1);
+  av = avma;
+  tmp2 = gmul(tQ, gadd(gmul(a1, rt),
+                       deg1pol_shallow(gen_1, gneg(yQ), vy)));
+  tmp2 = gerepileupto(av, tmp2);
+  av = avma;
+  tmp3 = gsub(gmul(a1, uQ), gmul(gQx, gQy));
+  tmp3 = gerepileupto(av, tmp3);
+
+  if (!isog) isog = isog_identity(vx,vy);
+  f = gel(isog, 1);
+  g = gel(isog, 2);
+  h = gel(isog, 3);
+  rt_sqr = gsqr(rt);
+  res = cgetg(4, t_VEC);
+  av = avma;
+  tmp4 = gdiv(gadd(gmul(tQ, rt), uQ), rt_sqr);
+  gel(res, 1) = gerepileupto(av, gadd(f, tmp4));
+  av = avma;
+  tmp4 = gadd(tmp1, gmul(rt, gadd(tmp2, tmp3)));
+  gel(res, 2) = gerepileupto(av, gsub(g, gdiv(tmp4, gmul(rt, rt_sqr))));
+  av = avma;
+  gel(res, 3) = gerepileupto(av, gmul(h, rt));
+  return gerepileupto(ltop, res);
+}
+
+/* Given a point P on E, return the curve E/<P> and, if only_image is zero,
+ * the isogeny pi: E -> E/<P>. The variables vx and vy are used to describe
+ * the isogeny (ignored if only_image is zero) */
+static GEN
+isogeny_from_kernel_point(GEN E, GEN P, int only_image, long vx, long vy)
+{
+  pari_sp av = avma;
+  GEN isog, EE, f, g, h, h2, h3;
+  GEN Q = P, t = gen_0, w = gen_0;
+  long c;
+  if (!oncurve(E,P))
+    pari_err_DOMAIN("isogeny_from_kernel_point", "point", "not on", E, P);
+  if (ell_is_inf(P))
+  {
+    if (only_image) return E;
+    return mkvec2(E, isog_identity(vx,vy));
+  }
+
+  isog = NULL; c = 1;
+  for (;;)
+  {
+    GEN tQ, xQ = gel(Q,1), uQ = ec_2divpol_evalx(E, xQ);
+    int stop = 0;
+    if (ellisweierstrasspoint(E,Q))
+    { /* ord(P)=2c; take Q=[c]P into consideration and stop */
+      tQ = ec_dFdx_evalQ(E, Q);
+      stop = 1;
+    }
+    else
+      tQ = ec_half_deriv_2divpol_evalx(E, xQ);
+    t = gadd(t, tQ);
+    w = gadd(w, gadd(uQ, gmul(tQ, xQ)));
+    if (!only_image) isog = update_isogeny_polys(isog, E, Q,tQ,uQ, vx,vy);
+    if (stop) break;
+
+    Q = elladd(E, P, Q);
+    ++c;
+    /* IF x([c]P) = x([c-1]P) THEN [c]P = -[c-1]P and [2c-1]P = 0 */
+    if (gequal(gel(Q,1), xQ)) break;
+    if (gc_needed(av,1))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"isogeny_from_kernel_point");
+      gerepileall(av, isog? 4: 3, &Q, &t, &w, &isog);
+    }
+  }
+
+  EE = make_velu_curve(E, t, w);
+  if (only_image) return EE;
+
+  if (!isog) isog = isog_identity(vx,vy);
+  f = gel(isog, 1);
+  g = gel(isog, 2);
+  if ( ! (typ(f) == t_RFRAC && typ(g) == t_RFRAC))
+    pari_err_BUG("isogeny_from_kernel_point (f or g has wrong type)");
+
+  /* Clean up the isogeny polynomials f, g and h so that the isogeny
+   * is given by (x,y) -> (f(x)/h(x)^2, g(x,y)/h(x)^3) */
+  h = gel(isog, 3);
+  h2 = gsqr(h);
+  h3 = gmul(h, h2);
+  f = gmul(f, h2);
+  g = gmul(g, h3);
+  if (typ(f) != t_POL || typ(g) != t_POL)
+    pari_err_BUG("isogeny_from_kernel_point (wrong denominator)");
+  return mkvec2(EE, mkvec3(f,g, gel(isog,3)));
+}
+
+/* Given a t_POL x^n - s1 x^{n-1} + s2 x^{n-2} - s3 x^{n-3} + ...
+ * return the first three power sums (Newton's identities):
+ *   p1 = s1
+ *   p2 = s1^2 - 2 s2
+ *   p3 = (s1^2 - 3 s2) s1 + 3 s3 */
+static void
+first_three_power_sums(GEN pol, GEN *p1, GEN *p2, GEN *p3)
+{
+  long d = degpol(pol);
+  GEN s1, s2, ms3;
+
+  *p1 = s1 = gneg(RgX_coeff(pol, d-1));
+
+  s2 = RgX_coeff(pol, d-2);
+  *p2 = gsub(gsqr(s1), gmulsg(2L, s2));
+
+  ms3 = RgX_coeff(pol, d-3);
+  *p3 = gadd(gmul(s1, gsub(*p2, s2)), gmulsg(-3L, ms3));
+}
+
+
+/* Let E and a t_POL h of degree 1 or 3 whose roots are 2-torsion points on E.
+ * - if only_image != 0, return [t, w] used to compute the equation of the
+ *   quotient by the given 2-torsion points
+ * - else return [t,w, f,g,h], along with the contributions f, g and
+ *   h to the isogeny giving the quotient by h. Variables vx and vy are used
+ *   to create f, g and h, or ignored if only_image is zero */
+
+/* deg h = 1; 2-torsion contribution from Weierstrass point */
+static GEN
+contrib_weierstrass_pt(GEN E, GEN h, long only_image, long vx, long vy)
+{
+  GEN p = ellbasechar(E);
+  GEN a1 = ell_get_a1(E);
+  GEN a3 = ell_get_a3(E);
+  GEN x0 = gneg(constant_term(h)); /* h = x - x0 */
+  GEN b = gadd(gmul(a1,x0), a3);
+  GEN y0, Q, t, w, t1, t2, f, g;
+
+  if (!equalis(p, 2L)) /* char(k) != 2 ==> y0 = -b/2 */
+    y0 = gmul2n(gneg(b), -1);
+  else
+  { /* char(k) = 2 ==> y0 = sqrt(f(x0)) where E is y^2 + h(x) = f(x). */
+    if (!gequal0(b)) pari_err_BUG("two_torsion_contrib (a1*x0+a3 != 0)");
+    y0 = gsqrt(ec_f_evalx(E, x0), 0);
+  }
+  Q = mkvec2(x0, y0);
+  t = ec_dFdx_evalQ(E, Q);
+  w = gmul(x0, t);
+  if (only_image) return mkvec2(t,w);
+
+  /* Compute isogeny, f = (x - x0) * t */
+  f = deg1pol_shallow(t, gmul(t, gneg(x0)), vx);
+
+  /* g = (x - x0) * t * (a1 * (x - x0) + (y - y0)) */
+  t1 = deg1pol_shallow(a1, gmul(a1, gneg(x0)), vx);
+  t2 = deg1pol_shallow(gen_1, gneg(y0), vy);
+  g = gmul(f, gadd(t1, t2));
+  return mkvec5(t, w, f, g, h);
+}
+/* deg h =3; full 2-torsion contribution. NB: assume h is monic; base field
+ * characteristic is odd or zero (cannot happen in char 2).*/
+static GEN
+contrib_full_tors(GEN E, GEN h, long only_image, long vx, long vy)
+{
+  GEN p1, p2, p3, half_b2, half_b4, t, w, f, g;
+  first_three_power_sums(h, &p1,&p2,&p3);
+  half_b2 = gmul2n(ell_get_b2(E), -1);
+  half_b4 = gmul2n(ell_get_b4(E), -1);
+
+  /* t = 3*(p2 + b4/2) + p1 * b2/2 */
+  t = gadd(gmulsg(3L, gadd(p2, half_b4)), gmul(p1, half_b2));
+
+  /* w = 3 * p3 + p2 * b2/2 + p1 * b4/2 */
+  w = gadd(gmulsg(3L, p3), gadd(gmul(p2, half_b2),
+                                gmul(p1, half_b4)));
+  if (only_image) return mkvec2(t,w);
+
+  /* Compute isogeny */
+  {
+    GEN a1 = ell_get_a1(E), a3 = ell_get_a3(E), t1, t2;
+    GEN s1 = gneg(RgX_coeff(h, 2));
+    GEN dh = RgX_deriv(h);
+    GEN psi2xy = gadd(deg1pol_shallow(a1, a3, vx),
+                      deg1pol_shallow(gen_2, gen_0, vy));
+
+    /* f = -3 (3 x + b2/2 + s1) h + (3 x^2 + (b2/2) x + (b4/2)) h'*/
+    t1 = RgX_mul(h, gmulsg(-3, deg1pol(stoi(3), gadd(half_b2, s1), vx)));
+    t2 = mkpoln(3, stoi(3), half_b2, half_b4);
+    setvarn(t2, vx);
+    t2 = RgX_mul(dh, t2);
+    f = RgX_add(t1, t2);
+
+    /* 2g = psi2xy * (f'*h - f*h') - (a1*f + a3*h) * h; */
+    t1 = RgX_sub(RgX_mul(RgX_deriv(f), h), RgX_mul(f, dh));
+    t2 = RgX_mul(h, RgX_add(RgX_Rg_mul(f, a1), RgX_Rg_mul(h, a3)));
+    g = RgX_divs(gsub(gmul(psi2xy, t1), t2), 2L);
+
+    f = RgX_mul(f, h);
+    g = RgX_mul(g, h);
+  }
+  return mkvec5(t, w, f, g, h);
+}
+
+/* Given E and a t_POL T whose roots define a subgroup G of E, return the factor
+ * of T that corresponds to the 2-torsion points E[2] \cap G in G */
+INLINE GEN
+two_torsion_part(GEN E, GEN T)
+{ return RgX_gcd(T, elldivpol(E, 2, varn(T))); }
+
+/* Return the jth Hasse derivative of the polynomial f = \sum_{i=0}^n a_i x^i,
+ * i.e. \sum_{i=j}^n a_i \binom{i}{j} x^{i-j}. It is a derivation even when the
+ * coefficient ring has positive characteristic */
+static GEN
+derivhasse(GEN f, ulong j)
+{
+  ulong i, d = degpol(f);
+  GEN df;
+  if (gequal0(f) || d == 0) return pol_0(varn(f));
+  if (j == 0) return gcopy(f);
+  df = cgetg(2 + (d-j+1), t_POL);
+  df[1] = f[1];
+  for (i = j; i <= d; ++i) gel(df, i-j+2) = gmul(binomialuu(i,j), gel(f, i+2));
+  return normalizepol(df);
+}
+
+static GEN
+non_two_torsion_abscissa(GEN E, GEN h0, GEN x)
+{
+  GEN mp1, dh0, ddh0, t, u, t1, t2, t3;
+  long m = degpol(h0);
+  mp1 = gel(h0, m + 1); /* negative of first power sum */
+  dh0 = RgX_deriv(h0);
+  ddh0 = RgX_deriv(dh0);
+  t = ec_2divpol_evalx(E, x);
+  u = ec_half_deriv_2divpol_evalx(E, x);
+  t1 = RgX_sub(RgX_sqr(dh0), RgX_mul(ddh0, h0));
+  t2 = RgX_mul(u, RgX_mul(h0, dh0));
+  t3 = RgX_mul(RgX_sqr(h0),
+               deg1pol_shallow(stoi(2*m), gmulsg(2L, mp1), varn(x)));
+  /* t * (dh0^2 - ddh0*h0) - u*dh0*h0 + (2*m*x - 2*s1) * h0^2); */
+  return RgX_add(RgX_sub(RgX_mul(t, t1), t2), t3);
+}
+
+static GEN
+isog_abscissa(GEN E, GEN kerp, GEN h0, GEN x, GEN two_tors)
+{
+  GEN f0, f2, h2, t1, t2, t3;
+  f0 = (degpol(h0) > 0)? non_two_torsion_abscissa(E, h0, x): pol_0(varn(x));
+  f2 = gel(two_tors, 3);
+  h2 = gel(two_tors, 5);
+
+  /* Combine f0 and f2 into the final abcissa of the isogeny. */
+  t1 = RgX_mul(x, RgX_sqr(kerp));
+  t2 = RgX_mul(f2, RgX_sqr(h0));
+  t3 = RgX_mul(f0, RgX_sqr(h2));
+  /* x * kerp^2 + f2 * h0^2 + f0 * h2^2 */
+  return RgX_add(t1, RgX_add(t2, t3));
+}
+
+static GEN
+non_two_torsion_ordinate_char_not2(GEN E, GEN f, GEN h, GEN psi2)
+{
+  GEN a1 = ell_get_a1(E), a3 = ell_get_a3(E);
+  GEN df = RgX_deriv(f), dh = RgX_deriv(h);
+  /* g = df * h * psi2/2 - f * dh * psi2
+   *   - (E.a1 * f + E.a3 * h^2) * h/2 */
+  GEN t1 = RgX_mul(df, RgX_mul(h, RgX_divs(psi2, 2L)));
+  GEN t2 = RgX_mul(f, RgX_mul(dh, psi2));
+  GEN t3 = RgX_mul(RgX_divs(h, 2L),
+                   RgX_add(RgX_Rg_mul(f, a1), RgX_Rg_mul(RgX_sqr(h), a3)));
+  return RgX_sub(RgX_sub(t1, t2), t3);
+}
+
+/* h = kerq */
+static GEN
+non_two_torsion_ordinate_char2(GEN E, GEN h, GEN x, GEN y)
+{
+  GEN a1 = ell_get_a1(E), a3 = ell_get_a3(E), a4 = ell_get_a4(E);
+  GEN b2 = ell_get_b2(E), b4 = ell_get_b4(E), b6 = ell_get_b6(E);
+  GEN h2, dh, dh2, ddh, D2h, D2dh, H, psi2, u, t, alpha;
+  GEN p1, t1, t2, t3, t4;
+  long m, vx = varn(x);
+
+  h2 = RgX_sqr(h);
+  dh = RgX_deriv(h);
+  dh2 = RgX_sqr(dh);
+  ddh = RgX_deriv(dh);
+  H = RgX_sub(dh2, RgX_mul(h, ddh));
+  D2h = derivhasse(h, 2);
+  D2dh = derivhasse(dh, 2);
+  psi2 = deg1pol_shallow(a1, a3, vx);
+  u = mkpoln(3, b2, gen_0, b6);
+  setvarn(u, vx);
+  t = deg1pol_shallow(b2, b4, vx);
+  alpha = mkpoln(4, a1, a3, gmul(a1, a4), gmul(a3, a4));
+  setvarn(alpha, vx);
+  m = degpol(h);
+  p1 = RgX_coeff(h, m-1); /* first power sum */
+
+  t1 = gmul(gadd(gmul(a1, p1), gmulgs(a3, m)), RgX_mul(h,h2));
+
+  t2 = gmul(a1, gadd(gmul(a1, gadd(y, psi2)), RgX_add(RgX_Rg_add(RgX_sqr(x), a4), t)));
+  t2 = gmul(t2, gmul(dh, h2));
+
+  t3 = gadd(gmul(y, t), RgX_add(alpha, RgX_Rg_mul(u, a1)));
+  t3 = gmul(t3, RgX_mul(h, H));
+
+  t4 = gmul(u, psi2);
+  t4 = gmul(t4, RgX_sub(RgX_sub(RgX_mul(h2, D2dh), RgX_mul(dh, H)),
+                        RgX_mul(h, RgX_mul(dh, D2h))));
+
+  return gadd(t1, gadd(t2, gadd(t3, t4)));
+}
+
+static GEN
+isog_ordinate(GEN E, GEN kerp, GEN kerq, GEN x, GEN y, GEN two_tors, GEN f)
+{
+  GEN g;
+  if (! equalis(ellbasechar(E), 2L)) {
+    /* FIXME: We don't use (hence don't need to calculate)
+     * g2 = gel(two_tors, 4) when char(k) != 2. */
+    GEN psi2 = ec_dmFdy_evalQ(E, mkvec2(x, y));
+    g = non_two_torsion_ordinate_char_not2(E, f, kerp, psi2);
+  } else {
+    GEN h2 = gel(two_tors, 5);
+    GEN g2 = gmul(gel(two_tors, 4), RgX_mul(kerq, RgX_sqr(kerq)));
+    GEN g0 = non_two_torsion_ordinate_char2(E, kerq, x, y);
+    g0 = gmul(g0, RgX_mul(h2, RgX_sqr(h2)));
+    g = gsub(gmul(y, RgX_mul(kerp, RgX_sqr(kerp))), gadd(g2, g0));
+  }
+  return g;
+}
+
+/* Given an elliptic curve E and a polynomial kerp whose roots give the
+ * x-coordinates of a subgroup G of E, return the curve E/G and,
+ * if only_image is zero, the isogeny pi:E -> E/G. Variables vx and vy are
+ * used to describe the isogeny (and are ignored if only_image is zero). */
+static GEN
+isogeny_from_kernel_poly(GEN E, GEN kerp, long only_image, long vx, long vy)
+{
+  long m;
+  GEN b2 = ell_get_b2(E), b4 = ell_get_b4(E), b6 = ell_get_b6(E);
+  GEN p1, p2, p3, x, y, f, g, two_tors, EE, t, w;
+  GEN kerh = two_torsion_part(E, kerp);
+  GEN kerq = RgX_divrem(kerp, kerh, ONLY_DIVIDES);
+  if (!kerq) pari_err_BUG("isogeny_from_kernel_poly");
+  /* isogeny degree: 2*degpol(kerp)+1-degpol(kerh) */
+  m = degpol(kerq);
+
+  kerp = RgX_Rg_div(kerp, leading_term(kerp));
+  kerq = RgX_Rg_div(kerq, leading_term(kerq));
+  kerh = RgX_Rg_div(kerh, leading_term(kerh));
+  switch(degpol(kerh))
+  {
+  case 0:
+    two_tors = mkvec5(gen_0, gen_0, pol_0(vx), pol_0(vx), pol_1(vx));
+    break;
+  case 1:
+    two_tors = contrib_weierstrass_pt(E, kerh, only_image,vx,vy);
+    break;
+  case 3:
+    two_tors = contrib_full_tors(E, kerh, only_image,vx,vy);
+    break;
+  default:
+    two_tors = NULL;
+    pari_err_DOMAIN("isogeny_from_kernel_poly", "kernel polynomial",
+                    "does not define a subgroup of", E, kerp);
+  }
+  first_three_power_sums(kerq,&p1,&p2,&p3);
+  x = pol_x(vx);
+  y = pol_x(vy);
+
+  /* t = 6 * p2 + b2 * p1 + m * b4, */
+  t = gadd(gmulsg(6L, p2), gadd(gmul(b2, p1), gmulsg(m, b4)));
+
+  /* w = 10 * p3 + 2 * b2 * p2 + 3 * b4 * p1 + m * b6, */
+  w = gadd(gmulsg(10L, p3),
+           gadd(gmul(gmulsg(2L, b2), p2),
+                gadd(gmul(gmulsg(3L, b4), p1), gmulsg(m, b6))));
+
+  EE = make_velu_curve(E, gadd(t, gel(two_tors, 1)),
+                          gadd(w, gel(two_tors, 2)));
+  if (only_image) return EE;
+
+  f = isog_abscissa(E, kerp, kerq, x, two_tors);
+  g = isog_ordinate(E, kerp, kerq, x, y, two_tors, f);
+  return mkvec2(EE, mkvec3(f,g,kerp));
+}
+
+/* Given an elliptic curve E and a subgroup G of E, return the curve
+ * E/G and, if only_image is zero, the isogeny corresponding
+ * to the canonical surjection pi:E -> E/G. The variables vx and
+ * vy are used to describe the isogeny (and are ignored if
+ * only_image is zero). The subgroup G may be given either as
+ * a generating point P on E or as a polynomial kerp whose roots are
+ * the x-coordinates of the points in G */
+GEN
+ellisogeny(GEN E, GEN G, long only_image, long vx, long vy)
+{
+  pari_sp av = avma;
+  GEN j, z;
+  checkell(E);j = ell_get_j(E);
+  if (vx < 0) vx = 0;
+  if (vy < 0) vy = 1;
+  if (varncmp(vx, vy) >= 0) pari_err_PRIORITY("ellisogeny", pol_x(vx), "<=", vy);
+  if (varncmp(vy, gvar(j)) >= 0) pari_err_PRIORITY("ellisogeny", j, ">=", vy);
+  switch(typ(G))
+  {
+  case t_VEC:
+    checkellpt(G);
+    if (!ell_is_inf(G))
+    {
+      GEN x =  gel(G,1), y = gel(G,2);
+      if (varncmp(vy, gvar(x)) >= 0) pari_err_PRIORITY("ellisogeny", x, ">=", vy);
+      if (varncmp(vy, gvar(y)) >= 0) pari_err_PRIORITY("ellisogeny", y, ">=", vy);
+    }
+    z = isogeny_from_kernel_point(E, G, only_image, vx, vy);
+    break;
+  case t_POL:
+    if (varncmp(vy, gvar(constant_term(G))) >= 0)
+      pari_err_PRIORITY("ellisogeny", constant_term(G), ">=", vy);
+    z = isogeny_from_kernel_poly(E, G, only_image, vx, vy);
+    break;
+  default:
+    z = NULL;
+    pari_err_TYPE("ellisogeny", G);
+  }
+  return gerepilecopy(av, z);
+}
diff --git a/src/basemath/ellpadicL.c b/src/basemath/ellpadicL.c
new file mode 100644
index 0000000..7e539ce
--- /dev/null
+++ b/src/basemath/ellpadicL.c
@@ -0,0 +1,179 @@
+/* $Id$
+
+Copyright (C) 2011  The PARI group.
+
+This file is part of the PARI/GP package.
+
+PARI/GP 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. It is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY WHATSOEVER.
+
+Check the License for details. You should have received a copy of it, along
+with the package; see the file 'COPYING'. If not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "pari.h"
+#include "paripriv.h"
+
+/** Batch p-adic logarithms **/
+
+/* a/b mod q */
+static GEN
+divmodulo(GEN a, ulong b, ulong p, GEN q)
+{
+  long v = u_lvalrem(b, p, &b);
+  if (v) a = divis(a, upowuu(p,v));
+  /* a/b is now a p-integer */
+  return Fp_div(a, utoipos(b), q);
+}
+
+/* to compute log_p(a) mod q = p^n, p < 2^31 */
+static GEN
+initQplog(long p, GEN q, long n)
+{
+  long i, nn, nt;
+  GEN a, C;
+  for(nn = n, nt = n + 1; nn >= p; nn /= p) nt++;
+  if (p == 2)
+    while(3 * (nt - 1) > u_lval(nt-1, p) + n) nt--;
+  else
+    while(nt > u_lval(nt-1, p) + n) nt--;
+
+  C = cgetg(nt, t_VEC);
+  /* [ (-1)^k-1 p^k / (k*(p-1)) ] k=1..nt
+   * [ (-1)^k-1 2^3k / (2*k) ]    k=1..nt if p = 2*/
+  for(i = 1, a = utoipos(p); i < nt; i++, a = mulis(a, -p))
+    gel(C,i) = divmodulo(a, i * (p==2? 2: p-1), p, q);
+  return C;
+}
+
+/* compute log_p(a), 'a' a p-unit, C = initQplog(p,q,n), q = p^n */
+static GEN
+logp(GEN C, GEN a, ulong p, GEN q)
+{
+  long i, nt = lg(C);
+  ulong av = avma;
+  GEN b, res;
+
+  if (p == 2)
+    b = Fp_sqr(modii(a,q), q);
+  else
+    b = Fp_powu(a, p-1, q);
+  /* now b = 1 mod p, compute (b-1) / p = euclidean quotient */
+  b = divis(b, p);
+  res = Fp_mul(b, gel(C,nt-1), q);
+  for(i = nt-2; i > 0; i--)
+    res = Fp_mul(addii(res, gel(C,i)), b, q);
+  return gerepileuptoint(av, res);
+}
+
+/** p-adic L function **/
+
+/* W an msinit, xpm the normalized modylar symbol attached to E/Q, D > 0.
+ * Assume |D p^m| < MAX_ULONG, m > 0 */
+static GEN
+loopLpn(GEN W, GEN xpm, ulong D, ulong p, long m, long R, GEN q)
+{
+  pari_sp av;
+  ulong a;
+  GEN q1 = diviuexact(q,p);
+  GEN Dq1= mului(D,q1), Dq = muliu(Dq1,p);
+  GEN u = gen_0, u1 = gen_0, nc = icopy(gen_1);
+  GEN c = mkfrac(nc, Dq), c1 = mkfrac(nc, Dq1);
+  GEN C = R? initQplog(p, q, m): NULL;
+  ulong A = itou(shifti(Dq,-1));
+
+  av = avma;
+  for (a = 1; a <= A; a++)
+  {
+    GEN logpR, x,x1;
+    long s;
+    if (a % p == 0 || !(s = krouu(D,a))) continue;
+    nc[2] = (long)a;
+    x = Q_xpm(W,xpm, c); /* xpm(a / Dq) */
+    x1= Q_xpm(W,xpm, c1);/* xpm(a / D(q/p)) */
+    if (!signe(x) && !signe(x1)) continue;
+    if (R)
+    {
+      logpR = logp(C, nc, p, q);
+      if (R != 1) logpR = Fp_powu(logpR, R, q);
+      x = mulii(x, logpR);
+      x1= mulii(x1,logpR);
+    }
+    if (s < 0) { u = subii(u, x); u1= subii(u1,x1); }
+    else       { u = addii(u, x); u1= addii(u1,x1); }
+    if (gc_needed(av,2))
+    {
+      if (DEBUGMEM>1) pari_warn(warnmem,"loopLp: a = %ld / %ld",a,A);
+      gerepileall(av, 2, &u,&u1);
+    }
+  }
+  return mkvec2(u,u1);
+}
+
+/* p \nmid ap, return unit root of x^2 - ap*x + p, accuracy p^n */
+static GEN
+unit_eigenvalue(GEN ap, GEN p, long n)
+{
+  GEN sqrtD, D = subii(sqri(ap), shifti(p,2));
+  if (equaliu(p,2)) n++;
+  sqrtD = Zp_sqrtlift(D, ap, p, n); /* congruent to ap mod p */
+  return gmul2n(gadd(ap, cvtop(sqrtD,p,n)), -1);
+}
+
+/* TODO: C corresponds to Teichmuller, currently allways NULL */
+GEN
+ellpadicL(GEN E, GEN pp, long n, long r, GEN DD, GEN C)
+{
+  pari_sp av = avma;
+  GEN ap, scale, L, W, xpm;
+  ulong p, D;
+
+  if (DD && !Z_isfundamental(DD))
+    pari_err_DOMAIN("ellpadicL", "isfundamental(D)", "=", gen_0, DD);
+  if (DD && signe(DD) <= 0) pari_err_DOMAIN("ellpadicL", "D", "<=", gen_0, DD);
+  if (typ(pp) != t_INT) pari_err_TYPE("ellpadicL",pp);
+  if (cmpis(pp,2) < 0) pari_err_PRIME("ellpadicL",pp);
+  if (n <= 0) pari_err_DOMAIN("ellpadicL","precision","<=",gen_0,stoi(n));
+  if (r < 0) pari_err_DOMAIN("ellpadicL","r","<",gen_0,stoi(r));
+
+  (void)C; /* TODO */
+  W = msfromell(E, 1);
+  xpm = gel(W,2);
+  W = gel(W,1);
+  p = itou(pp);
+  D = DD? itou(DD): 1;
+
+  xpm = Q_primitive_part(xpm,&scale);
+  if (!scale) scale = gen_1;
+  n -= Q_pval(scale, pp);
+  scale = cvtop(scale, pp, n);
+
+  ap = ellap(E,pp);
+  if (umodiu(ap,p))
+  { /* ordinary */
+    long N = n+2;
+    GEN pn = powuu(p, N);
+    GEN u,v, uv = loopLpn(W,xpm, D, p,N,r,pn); /* correct mod p^n */
+    GEN al = ginv( unit_eigenvalue(ap, pp, n) );
+    al = gel(al,4); /* lift to Z */
+    u = modii(gel(uv,1), pn);
+    v = modii(gel(uv,2), pn);
+    L = Fp_sub(u, Fp_mul(al,v,pn), pn);
+    L = Fp_mul(L, Fp_powu(al, N, pn), pn);
+    if (!signe(L)) L = zeropadic_shallow(pp, n);
+  }
+  else
+  { /* supersingular */
+    GEN _0 = zeropadic_shallow(pp, n);
+    long N = signe(ap)? 2*n+3: 2*n+1;
+    GEN uv = loopLpn(W,xpm, D, p,N,r,powiu(pp,N)), u = gel(uv,1), v = gel(uv,2);
+    GEN M = mkmat2(mkcol2(gen_0, gen_m1), gdivgs(mkcol2(gen_1,ap),p));
+    L = RgV_RgM_mul(mkvec2(u,gdivgs(v,-p)), gpowgs(M,N));
+    u = gadd(gel(L,1), _0);
+    v = gadd(gel(L,2), _0);
+    L = mkvec2(u,v);
+  }
+  return gerepileupto(av, gmul(L, gmul2n(scale,1)));
+}
diff --git a/src/basemath/elltors.c b/src/basemath/elltors.c
new file mode 100644
index 0000000..605c780
--- /dev/null
+++ b/src/basemath/elltors.c
@@ -0,0 +1,709 @@
+/* Copyright (C) 2000  The PARI group.
+
+This file is part of the PARI/GP package.
+
+PARI/GP 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. It is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY WHATSOEVER.
+
+Check the License for details. You should have received a copy of it, along
+with the package; see the file 'COPYING'. If not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+/********************************************************************/
+/**                                                                **/
+/**         TORSION OF ELLIPTIC CURVES over NUMBER FIELDS          **/
+/**                                                                **/
+/********************************************************************/
+#include "pari.h"
+#include "paripriv.h"
+static int
+smaller_x(GEN p, GEN q)
+{
+  int s = absi_cmp(denom(p), denom(q));
+  return (s<0 || (s==0 && absi_cmp(numer(p),numer(q)) < 0));
+}
+
+/* best generator in cycle of length k */
+static GEN
+best_in_cycle(GEN e, GEN p, long k)
+{
+  GEN p0 = p,q = p;
+  long i;
+
+  for (i=2; i+i<k; i++)
+  {
+    q = elladd(e,q,p0);
+    if (ugcd(i,k)==1 && smaller_x(gel(q,1), gel(p,1))) p = q;
+  }
+  return (gsigne(ec_dmFdy_evalQ(e,p)) < 0)? ellneg(e,p): p;
+}
+
+/* <p,q> = E_tors, possibly NULL (= oo), p,q independent unless NULL
+ * order p = k, order q = 2 unless NULL */
+static GEN
+tors(GEN e, long k, GEN p, GEN q, GEN v)
+{
+  GEN r;
+  if (q)
+  {
+    long n = k>>1;
+    GEN p1, best = q, np = ellmul(e,p,utoipos(n));
+    if (n % 2 && smaller_x(gel(np,1), gel(best,1))) best = np;
+    p1 = elladd(e,q,np);
+    if (smaller_x(gel(p1,1), gel(best,1))) q = p1;
+    else if (best == np) { p = elladd(e,p,q); q = np; }
+    p = best_in_cycle(e,p,k);
+    if (v)
+    {
+      p = ellchangepointinv(p,v);
+      q = ellchangepointinv(q,v);
+    }
+    r = cgetg(4,t_VEC);
+    gel(r,1) = utoipos(2*k);
+    gel(r,2) = mkvec2(utoipos(k), gen_2);
+    gel(r,3) = mkvec2copy(p, q);
+  }
+  else
+  {
+    if (p)
+    {
+      p = best_in_cycle(e,p,k);
+      if (v) p = ellchangepointinv(p,v);
+      r = cgetg(4,t_VEC);
+      gel(r,1) = utoipos(k);
+      gel(r,2) = mkvec( gel(r,1) );
+      gel(r,3) = mkvec( gcopy(p) );
+    }
+    else
+    {
+      r = cgetg(4,t_VEC);
+      gel(r,1) = gen_1;
+      gel(r,2) = cgetg(1,t_VEC);
+      gel(r,3) = cgetg(1,t_VEC);
+    }
+  }
+  return r;
+}
+
+/* Finds a multiplicative upper bound for #E_tor; assume integral model */
+static long
+torsbound(GEN e)
+{
+  GEN D = ell_get_disc(e);
+  pari_sp av = avma, av2;
+  long m, b, bold, nb;
+  forprime_t S;
+  long CM = ellQ_get_CM(e);
+  nb = expi(D) >> 3;
+  /* nb = number of primes to try ~ 1 prime every 8 bits in D */
+  b = bold = 5040; /* = 2^4 * 3^2 * 5 * 7 */
+  m = 0;
+  /* p > 2 has good reduction => E(Q) injects in E(Fp) */
+  (void)u_forprime_init(&S, 3, ULONG_MAX);
+  av2 = avma;
+  while (m < nb || (b > 12 && b != 16))
+  {
+    ulong p = u_forprime_next(&S);
+    if (!p) pari_err_BUG("torsbound [ran out of primes]");
+    if (!umodiu(D, p)) continue;
+
+    b = ugcd(b, p+1 - ellap_CM_fast(e,p,CM));
+    avma = av2;
+    if (b == 1) break;
+    if (b == bold) m++; else { bold = b; m = 0; }
+  }
+  avma = av; return b;
+}
+
+/* return a rational point of order pk = p^k on E, or NULL if E(Q)[k] = O.
+ * *fk is either NULL (pk = 4 or prime) or elldivpol(p^(k-1)).
+ * Set *fk to elldivpol(p^k) */
+static GEN
+tpoint(GEN E, long pk, GEN *fk)
+{
+  GEN f = elldivpol(E,pk,0), g = *fk, v;
+  long i, l;
+  *fk = f;
+  if (g) f = RgX_div(f, g);
+  v = nfrootsQ(f); l = lg(v);
+  for (i = 1; i < l; i++)
+  {
+    GEN x = gel(v,i);
+    GEN y = ellordinate(E,x,0);
+    if (lg(y) != 1) return mkvec2(x,gel(y,1));
+  }
+  return NULL;
+}
+/* return E(Q)[2] */
+static GEN
+t2points(GEN E, GEN *f2)
+{
+  long i, l;
+  GEN v;
+  *f2 = ec_bmodel(E);
+  v = nfrootsQ(*f2); l = lg(v);
+  for (i = 1; i < l; i++)
+  {
+    GEN x = gel(v,i);
+    GEN y = ellordinate(E,x,0);
+    if (lg(y) != 1) gel(v,i) = mkvec2(x,gel(y,1));
+  }
+  return v;
+}
+
+static GEN
+elltors_divpol(GEN E)
+{
+  GEN T2 = NULL, p, P, Q, v;
+  long v2, r2, B;
+
+  E = ellintegralmodel(E, &v);
+  B = torsbound(E); /* #E_tor | B */
+  if (B == 1) return tors(E,1,NULL,NULL, v);
+  v2 = vals(B); /* bound for v_2(point order) */
+  B >>= v2;
+  p = const_vec(9, NULL);
+  r2 = 0;
+  if (v2) {
+    GEN f;
+    T2 = t2points(E, &f);
+    switch(lg(T2)-1)
+    {
+      case 0:  v2 = 0; break;
+      case 1:  r2 = 1; if (v2 == 4) v2 = 3; break;
+      default: r2 = 2; v2--; break; /* 3 */
+    }
+    if (v2) gel(p,2) = gel(T2,1);
+    /* f = f_2 */
+    if (v2 > 1) { gel(p,4) = tpoint(E,4, &f); if (!gel(p,4)) v2 = 1; }
+    /* if (v2>1) now f = f4 */
+    if (v2 > 2) { gel(p,8) = tpoint(E,8, &f); if (!gel(p,8)) v2 = 2; }
+  }
+  B <<= v2;
+  if (B % 3 == 0) {
+    GEN f3 = NULL;
+    gel(p,3) = tpoint(E,3,&f3);
+    if (!gel(p,3)) B /= (B%9)? 3: 9;
+    if (gel(p,3) && B % 9 == 0)
+    {
+      gel(p,9) = tpoint(E,9,&f3);
+      if (!gel(p,9)) B /= 3;
+    }
+  }
+  if (B % 5 == 0) {
+    GEN junk = NULL;
+    gel(p,5) = tpoint(E,5,&junk);
+    if (!gel(p,5)) B /= 5;
+  }
+  if (B % 7 == 0) {
+    GEN junk = NULL;
+    gel(p,7) = tpoint(E,7,&junk);
+    if (!gel(p,7)) B /= 7;
+  }
+  /* B is the exponent of E_tors(Q), r2 is the rank of its 2-Sylow,
+   * for i > 1, p[i] is a point of order i if one exists and i is a prime power
+   * and NULL otherwise */
+  if (r2 == 2) /* 2 cyclic factors */
+  { /* C2 x C2 */
+    if (B == 2) return tors(E,2, gel(T2,1), gel(T2,2), v);
+    else if (B == 6)
+    { /* C2 x C6 */
+      P = elladd(E, gel(p,3), gel(T2,1));
+      Q = gel(T2,2);
+    }
+    else
+    { /* C2 x C4 or C2 x C8 */
+      P = gel(p, B);
+      Q = gel(T2,2);
+      if (gequal(Q, ellmul(E, P, utoipos(B>>1)))) Q = gel(T2,1);
+    }
+  }
+  else /* cyclic */
+  {
+    Q = NULL;
+    if (v2)
+    {
+      if (B>>v2 == 1)
+        P = gel(p, B);
+      else
+        P = elladd(E, gel(p, B>>v2), gel(p,1<<v2));
+    }
+    else P = gel(p, B);
+  }
+  return tors(E,B, P, Q, v);
+}
+
+/* either return one prime of degree 1 above p or NULL (none or expensive) */
+static GEN
+primedec_deg1(GEN K, GEN p)
+{
+  GEN r, T, f = nf_get_index(K);
+  if (dvdii(f,p)) return NULL;
+  T = nf_get_pol(K);
+  r = FpX_oneroot(T, p); if (!r) return NULL;
+  r = deg1pol_shallow(gen_1, Fp_neg(r,p), varn(T));
+  return primedec_apply_kummer(K, r, 1, p);
+}
+
+/* Bound for the elementary divisors of the torsion group of elliptic curve
+ * Reduce the curve modulo some small good primes */
+static GEN
+nftorsbound(GEN E)
+{
+  pari_sp av;
+  long k = 0, g;
+  GEN B1 = gen_0, B2 = gen_0, K = ellnf_get_nf(E);
+  GEN D = ell_get_disc(E), ND = idealnorm(K,D);
+  forprime_t S;
+  if (typ(ND) == t_FRAC) ND = gel(ND,1);
+  ND = mulii(ND, Q_denom(vecslice(E,1,5)));
+  g = maxss(5, expi(ND) >> 3);
+  if (g > 20) g = 20;
+  /* P | p such that e(P/p) < p-1 => E(K) injects in E(k(P)) [otherwise
+   * we may lose some p-torsion]*/
+  (void)u_forprime_init(&S, 3, ULONG_MAX);
+  av = avma;
+  while (k < g) /* k = number of good primes already used */
+  {
+    ulong p = u_forprime_next(&S);
+    GEN P, gp;
+    long j, l;
+    if (!umodiu(ND,p)) continue;
+    gp = utoipos(p);
+    /* primes of degree 1 are easier and give smaller bounds */
+    if (typ(D) != t_POLMOD) /* E/Q */
+    {
+      P = primedec_deg1(K, gp); /* single P|p has all the information */
+      if (!P) continue;
+      P = mkvec(P);
+    }
+    else
+      P = idealprimedec_limit_f(K, utoipos(p), 1);
+    l = lg(P);
+    for (j = 1; j < l; j++,k++)
+    {
+      GEN Q = gel(P,j), EQ, cyc;
+      long n;
+      if ((ulong)pr_get_e(Q) >= p-1) continue;
+      EQ = ellinit(E,zkmodprinit(K,Q),0);
+      cyc = ellgroup(EQ, NULL);
+      n = lg(cyc)-1;
+      if (n == 0) return mkvec2(gen_1,gen_1);
+      B1 = gcdii(B1,gel(cyc,1));
+      B2 = (n == 1)? gen_1: gcdii(B2,gel(cyc,2));
+      obj_free(EQ);
+      /* division by 2 is cheap when it fails, no need to have a sharp bound */
+      if (Z_ispow2(B1)) return mkvec2(B1,B2);
+    }
+    if ((g & 15) == 0) gerepileall(av, 2, &B1, &B2);
+  }
+  if (cmpiu(B2, 2) > 0)
+  { /* if E(K) has full n-torsion then K contains the n-th roots of 1 */
+    GEN n = gel(rootsof1(K), 1);
+    B2 = gcdii(B2,n);
+  }
+  return mkvec2(B1,B2);
+}
+
+/* Checks whether the point P is divisible by n in E(K), where xn is
+ * [phi_n, psi_n^2]
+ * If true, returns a point Q such that nQ = P or -P. Else, returns NULL */
+static GEN
+nfellis_divisible_by(GEN E, GEN K, GEN P, GEN xn)
+{
+  GEN r, x = gel(P,1);
+  long i, l;
+  if (ell_is_inf(P)) return P;
+  r = nfroots(K, RgX_sub(RgX_Rg_mul(gel(xn,2), x), gel(xn,1)));
+  l = lg(r);
+  for(i=1; i<l; i++)
+  {
+    GEN a = gel(r,i), y = ellordinate(E,a,0);
+    if (lg(y) != 1) return mkvec2(a, gel(y,1));
+  }
+  return NULL;
+}
+
+long
+ellisdivisible(GEN E, GEN P, GEN n, GEN *pQ)
+{
+  pari_sp av = avma;
+  GEN xP, R, K = NULL, N = NULL;
+  long i, l;
+  checkell(E);
+  switch(ell_get_type(E))
+  {
+    case t_ELL_Q: break;
+    case t_ELL_NF: K = ellnf_get_nf(E); break;
+    default: pari_err_TYPE("ellisdivisible",E);
+  }
+  checkellpt(P);
+  switch(typ(n))
+  {
+    case t_INT:
+      N = n;
+      if (!isprime(absi(n)))
+      {
+        GEN f = absi_factor(n), LP = gel(f,1), LE = gel(f,2);
+        l = lg(LP);
+        for (i = 1; i < l; i++)
+        {
+          long j, e = itos(gel(LE,i));
+          GEN xp = ellxn(E,itos(gel(LP,i)),0);
+          for (j = 1; j <= e; j++)
+            if (!ellisdivisible(E, P, xp, &P)) { avma = av; return 0; }
+        }
+        if (pQ)
+        {
+          if (signe(n) < 0) P = ellneg(E, P);
+          *pQ = gerepilecopy(av,P);
+        }
+        else av = avma;
+        return 1;
+      }
+      n = ellxn(E, itou(n), 0);
+      break;
+    case t_VEC:
+      if (lg(n) == 3 && typ(gel(n,1)) == t_POL && typ(gel(n,2)) == t_POL) break;
+    default:
+      pari_err_TYPE("ellisdivisible",n);
+      break;
+  }
+  if (ell_is_inf(P)) { if (pQ) *pQ = ellinf(); return 1; }
+  if (!N) {
+    long d, d2 = degpol(gel(n,1));
+    if (d2 < 0)
+      N = gen_0;
+    else
+    {
+      if (!uissquareall(d2,(ulong*)&d)) pari_err_TYPE("ellisdivisible",n);
+      N = stoi(d);
+    }
+  }
+  if (!signe(N)) return 0;
+  xP = gel(P,1);
+  R = nfroots(K, RgX_sub(RgX_Rg_mul(gel(n,2), xP), gel(n,1)));
+  l = lg(R);
+  for(i=1; i<l; i++)
+  {
+    GEN Q,y, x = gel(R,i), a = ellordinate(E,x,0);
+    if (lg(a) == 1) continue;
+    y = gel(a,1);
+    Q = mkvec2(x,y);
+    if (!gequal(P,ellmul(E,Q,N))) Q = ellneg(E,Q); /* nQ = -P */
+    if (pQ) *pQ = gerepilecopy(av,Q); else avma = av;
+    return 1;
+  }
+  avma = av; return 0;
+}
+
+/* 2-torsion point of abcissa x */
+static GEN
+tor2(GEN E, GEN x) { return mkvec2(x, gmul2n(gneg(ec_h_evalx(E,x)), -1)); }
+
+static GEN
+ptor0()
+{ return mkvec2(mkvec(gen_1),cgetg(1,t_VEC)); }
+static GEN
+ptor1(long p, long n, GEN P)
+{ return mkvec2(mkvec(powuu(p,n)), mkvec(P)); }
+static GEN
+ptor2(long p, long n1, long n2, GEN P1, GEN P2)
+{ return mkvec2(mkvec2(powuu(p,n1), powuu(p,n2)), mkvec2(P1,P2)); }
+
+/* Computes the p-primary torsion in E(K). Assume that p is small, should use
+ * Weil pairing otherwise.
+ * N1, N2 = upper bounds on the integers n1 >= n2 such that
+ * E(K)[p^oo] = Z/p^n1 x Z/p^n2
+ * Returns [cyc,gen], where E(K)[p^oo] = sum Z/cyc[i] gen[i] */
+static GEN
+nfelltorsprimary(GEN E, long p, long N1, long N2, long v)
+{
+  GEN X, P1, P2, Q1, Q2, xp, K = ellnf_get_nf(E);
+  long n1, n2;
+
+  /* compute E[p] = < P1 > or < P1, P2 > */
+  P1 = P2 = ellinf();
+  X = nfroots(K, elldivpol(E,p,v));
+  if(lg(X) == 1) return ptor0();
+  if (p==2)
+  {
+    P1 = tor2(E, gel(X,1));
+    if (lg(X) > 2) P2 = tor2(E, gel(X,2)); /* E[2] = (Z/2Z)^2 */
+  }
+  else
+  {
+    long j, l = lg(X), nT, a;
+    GEN T = vectrunc_init(l);
+    for(j=1; j < l; j++)
+    {
+      GEN a = gel(X,j), Y = ellordinate(E,a,0);
+      if (lg(Y) != 1) vectrunc_append(T, mkvec2(a,gel(Y,1)));
+    }
+    nT = lg(T)-1;
+    if (!nT) return ptor0();
+    P1 = gel(T,1);
+    a = (p-1)/2;
+    if (nT != a)
+    { /* E[p] = (Z/pZ)^2 */
+      GEN Z = cgetg(a+1,t_VEC), Q1 = P1;
+      long k;
+      gel(Z,1) = Q1;
+      for (k=2; k <= a; k++) gel(Z,k) = elladd(E,Q1,P1);
+      gen_sort_inplace(Z, (void*)&cmp_universal, &cmp_nodata, NULL);
+      while (tablesearch(Z, gel(T,k), &cmp_universal)) k++;
+      P2 = gel(T,k);
+    }
+  }
+  xp = ellxn(E, p, v);
+
+  if (ell_is_inf(P2))
+  { /* E[p^oo] is cyclic, start from P1 and divide by p while possible */
+    for (n1 = 1; n1 < N1; n1++)
+    {
+      GEN Q = nfellis_divisible_by(E,K,P1,xp);
+      if (!Q) break;
+      P1 = Q;
+    }
+    return ptor1(p, n1, P1);
+  }
+
+  /* E[p] = (Z/pZ)^2, compute n2 and E[p^n2] */
+  Q1 = NULL;
+  for (n2 = 1; n2 < N2; n2++)
+  {
+    Q1 = nfellis_divisible_by(E,K,P1,xp);
+    Q2 = nfellis_divisible_by(E,K,P2,xp);
+    if (!Q1 || !Q2) break;
+    P1 = Q1;
+    P2 = Q2;
+  }
+
+  /* compute E[p^\infty] = < P1, P2 > */
+  n1 = n2;
+  if (n2 == N2)
+  {
+    if (N1 == N2) return ptor2(p, n2,n2, P1,P2);
+    Q1 = nfellis_divisible_by(E,K,P1,xp);
+  }
+  if (Q1) { P1 = Q1; n1++; }
+  else
+  {
+    Q2 = nfellis_divisible_by(E,K,P2,xp);
+    if (Q2) { P2 = P1; P1 = Q2; n1++; }
+    else
+    {
+      long k;
+      for (k = 1; k < p; k++)
+      {
+        P1 = elladd(E,P1,P2);
+        Q1 = nfellis_divisible_by(E,K,P1,xp);
+        if (Q1) { P1 = Q1; n1++; break; }
+      }
+      if (k == p) return ptor2(p, n2,n2, P1,P2);
+    }
+  }
+  /* P1,P2 of order p^n1,p^n2 with n1=n2+1.
+   * Keep trying to divide P1 + k P2 with 0 <= k < p by p */
+  while (n1 < N1)
+  {
+    Q1 = nfellis_divisible_by(E,K,P1,xp);
+    if (Q1) { P1 = Q1; n1++; }
+    else
+    {
+      long k;
+      for (k = 1; k < p; k++)
+      {
+        P1 = elladd(E,P1,P2);
+        Q1 = nfellis_divisible_by(E,K,P1,xp);
+        if (Q1) { P1 = Q1; n1++; break; }
+      }
+      if (k == p) break;
+    }
+  }
+  return ptor2(p, n1,n2, P1,P2);
+}
+
+/* Computes the torsion subgroup of E(K), as [order, cyc, gen] */
+static GEN
+ellnftors(GEN e)
+{
+  GEN B = nftorsbound(e), B1 = gel(B,1), B2 = gel(B,2), d1,d2, P1,P2;
+  GEN f = Z_factor(B1), P = gel(f,1), E = gel(f,2);
+  long i, l = lg(P), v = fetch_var_higher();
+
+  d1 = d2 = gen_1; P1 = P2 = ellinf();
+  for (i=1; i<l; i++)
+  {
+    long p = itos(gel(P,i)); /* Compute p-primary torsion */
+    long N1 = itos(gel(E,i)); /* >= n1 */
+    long N2 = Z_lval(B2,p); /* >= n2 */
+    GEN T = nfelltorsprimary(e, p, N1, N2, v), cyc = gel(T,1), gen = gel(T,2);
+    if (is_pm1(gel(cyc,1))) continue;
+    /* update generators P1,P2 and their respective orders d1,d2 */
+    P1 = elladd(e, P1, gel(gen,1)); d1 = mulii(d1, gel(cyc,1));
+    if (lg(cyc) > 2)
+    { P2 = elladd(e, P2, gel(gen,2)); d2 = mulii(d2, gel(cyc,2)); }
+  }
+  (void)delete_var();
+  if (is_pm1(d1)) return mkvec3(gen_1,cgetg(1,t_VEC),cgetg(1,t_VEC));
+  if (is_pm1(d2)) return mkvec3(d1, mkvec(d1), mkvec(P1));
+  return mkvec3(mulii(d1,d2), mkvec2(d1,d2), mkvec2(P1,P2));
+}
+
+GEN
+elltors(GEN e)
+{
+  pari_sp av = avma;
+  GEN t = NULL;
+  checkell(e);
+  switch(ell_get_type(e))
+  {
+    case t_ELL_Q:  t = elltors_divpol(e); break;
+    case t_ELL_NF: t = ellnftors(e); break;
+    case t_ELL_Fp:
+    case t_ELL_Fq: return ellgroup0(e,NULL,1);
+    default: pari_err_TYPE("elltors",e);
+  }
+  return gerepilecopy(av, t);
+}
+
+GEN
+elltors0(GEN e, long flag) { (void)flag; return elltors(e); }
+
+/********************************************************************/
+/**                                                                **/
+/**                ORDER OF POINTS over NUMBER FIELDS              **/
+/**                                                                **/
+/********************************************************************/
+/* E a t_ELL_Q (use Mazur's theorem) */
+long
+ellorder_Q(GEN E, GEN P)
+{
+  pari_sp av = avma;
+  GEN dx, dy, d4, d6, D, Pp, Q;
+  forprime_t S;
+  ulong a4, p;
+  long k;
+  if (ell_is_inf(P)) return 1;
+
+  dx = Q_denom(gel(P,1));
+  dy = Q_denom(gel(P,2));
+  if (ell_is_integral(E)) /* integral model, try Nagell Lutz */
+    if (cmpiu(dx, 4) > 0 || cmpiu(dy, 8) > 0) return 0;
+
+  d4 = Q_denom(ell_get_c4(E));
+  d6 = Q_denom(ell_get_c6(E));
+  D = ell_get_disc (E);
+  /* choose not too small prime p dividing neither a coefficient of the
+     short Weierstrass form nor of P and leading to good reduction */
+  u_forprime_init(&S, 100003, ULONG_MAX);
+  while ( (p = u_forprime_next(&S)) )
+    if (umodiu(d4, p) && umodiu(d6, p) && Rg_to_Fl(D, p)
+     && umodiu(dx, p) && umodiu(dy, p)) break;
+
+  /* transform E into short Weierstrass form Ep modulo p and P to Pp on Ep,
+   * check whether the order of Pp on Ep is <= 12 */
+  Pp = point_to_a4a6_Fl(E, P, p, &a4);
+  for (Q = Fle_dbl(Pp, a4, p), k = 2;
+       !ell_is_inf(Q) && k <= 12;
+       Q = Fle_add(Q, Pp, a4, p), k++) /* empty */;
+
+  if (k == 13) k = 0;
+  else
+  { /* check whether [k]P = O over Q. Save potentially costly last elladd */
+    GEN R;
+    Q = ellmul(E, P, utoipos(k>>1));
+    R = odd(k)? elladd(E, P,Q): Q;
+    if (!gequal(Q, ellneg(E,R))) k = 0;
+  }
+  avma = av; return k;
+}
+/* E a t_ELL_NF */
+static GEN
+ellorder_nf(GEN E, GEN P)
+{
+  GEN K = ellnf_get_nf(E), B;
+  pari_sp av = avma;
+  GEN dx, dy, d4, d6, D, ND, Ep, Pp, Q, gp, modpr, pr, T, k;
+  forprime_t S;
+  ulong a4, p;
+  if (ell_is_inf(P)) return gen_1;
+
+  B = gel(nftorsbound(E), 1);
+  dx = Q_denom(gel(P,1));
+  dy = Q_denom(gel(P,2));
+  d4 = Q_denom(ell_get_c4(E));
+  d6 = Q_denom(ell_get_c6(E));
+  D = ell_get_disc(E);
+  ND = idealnorm(K,D);
+  if (typ(ND) == t_FRAC) ND = gel(ND,1);
+
+  /* choose not too small prime p of degree 1 dividing neither a coefficient of
+   * the short Weierstrass form nor of P and leading to good reduction */
+  u_forprime_init(&S, 100003, ULONG_MAX);
+  while ( (p = u_forprime_next(&S)) )
+  {
+    if (!umodiu(d4, p) || !umodiu(d6, p) || !umodiu(ND, p)
+     || !umodiu(dx, p) || !umodiu(dy, p)) continue;
+    gp = utoipos(p);
+    pr = primedec_deg1(K, gp);
+    if (pr) break;
+  }
+
+  modpr = nf_to_Fq_init(K, &pr,&T,&gp);
+  Ep = ellinit(E, pr, 0);
+  Pp = nfV_to_FqV(P, K, modpr);
+
+  /* transform E into short Weierstrass form Ep modulo p and P to Pp on Ep,
+   * check whether the order of Pp on Ep divides B */
+  Pp = point_to_a4a6_Fl(Ep, Pp, p, &a4);
+  if (!ell_is_inf(Fle_mul(Pp, B, a4, p))) { avma = av; return gen_0; }
+  k = Fle_order(Pp, B, a4, p);
+  { /* check whether [k]P = O over K. Save potentially costly last elladd */
+    GEN R;
+    Q = ellmul(E, P, shifti(k,-1));
+    R = mod2(k)? elladd(E, P,Q): Q;
+    if (!gequal(Q, ellneg(E,R))) k = gen_0;
+  }
+  return gerepileuptoint(av, k);
+}
+
+GEN
+ellorder(GEN E, GEN P, GEN o)
+{
+  pari_sp av = avma;
+  GEN fg, r, E0 = E;
+  checkell(E); checkellpt(P);
+  if (ell_is_inf(P)) return gen_1;
+  if (ell_get_type(E)==t_ELL_Q)
+  {
+    GEN p = NULL;
+    if (is_rational_t(typ(gel(P,1))) && is_rational_t(typ(gel(P,2))))
+      return utoi( ellorder_Q(E, P) );
+    if (RgV_is_FpV(P,&p) && p)
+    {
+      E = ellinit(E,p,0);
+      if (lg(E)==1) pari_err_IMPL("ellorder for curve with singular reduction");
+    }
+  }
+  if (ell_get_type(E)==t_ELL_NF) return ellorder_nf(E, P);
+  checkell_Fq(E);
+  fg = ellff_get_field(E);
+  if (!o) o = ellff_get_o(E);
+  if (typ(fg)==t_FFELT)
+    r = FF_ellorder(E, P, o);
+  else
+  {
+    GEN p = fg, e = ellff_get_a4a6(E);
+    GEN Pp = FpE_changepointinv(RgE_to_FpE(P,p), gel(e,3), p);
+    r = FpE_order(Pp, o, gel(e,1), p);
+  }
+  if (E != E0) obj_free(E);
+  return gerepileuptoint(av, r);
+}
+
+GEN
+orderell(GEN e, GEN z) { return ellorder(e,z,NULL); }
diff --git a/src/basemath/galconj.c b/src/basemath/galconj.c
index 7452fcc..f0a6528 100644
--- a/src/basemath/galconj.c
+++ b/src/basemath/galconj.c
@@ -50,17 +50,8 @@ galoisconj1(GEN nf)
     gel(res,2) = pol_x(v);
     return res;
   }
-  if (v == 0)
-  {
-    long w = fetch_var();
-    if (nf) y = gsubst(nf, 0, pol_x(w));
-    else { y = leafcopy(x); setvarn(y, w); }
-  }
-  else
-  {
-    y = x;
-    x = leafcopy(x); setvarn(x, 0);
-  }
+  y = x;
+  x = leafcopy(x); setvarn(x, fetch_var_higher());
   z = nfroots(y, x); lz = lg(z);
   y = cgetg(lz, t_COL);
   for (i = 1; i < lz; i++)
@@ -69,7 +60,7 @@ galoisconj1(GEN nf)
     if (typ(t) == t_POL) setvarn(t, v);
     gel(y,i) = t;
   }
-  if (v == 0) delete_var();
+  (void)delete_var();
   return gerepileupto(av, y);
 }
 
@@ -254,7 +245,7 @@ vandermondeinverse(GEN L, GEN T, GEN den, GEN prep)
   for (i = 1; i <= n; i++)
   {
     P = RgX_Rg_div(RgX_div_by_X_x(T, gel(L,i), NULL), gel(prep,i));
-    gel(M,i) = RgX_to_RgV(P,n);
+    gel(M,i) = RgX_to_RgC(P,n);
   }
   return den? gerepileupto(ltop, gmul(den, M)): gerepilecopy(ltop, M);
 }
@@ -356,17 +347,19 @@ initgaloisborne(GEN T, GEN dn, long prec, GEN *ptL, GEN *ptprep, GEN *ptdis)
   *ptL = L; return den;
 }
 
-/* ||| M ||| with respect to || x ||_oo. Assume M square t_MAT */
+/* ||| M ||| with respect to || x ||_oo, M t_MAT */
 GEN
 matrixnorm(GEN M, long prec)
 {
-  long i,j, n = lg(M);
+  long i,j,m, l = lg(M);
   GEN B = real_0(prec);
 
-  for (i = 1; i < n; i++)
+  if (l == 1) return B;
+  m = lgcols(M);
+  for (i = 1; i < m; i++)
   {
     GEN z = gabs(gcoeff(M,i,1), prec);
-    for (j = 2; j < n; j++) z = gadd(z, gabs(gcoeff(M,i,j), prec));
+    for (j = 2; j < l; j++) z = gadd(z, gabs(gcoeff(M,i,j), prec));
     if (gcmp(z, B) > 0) B = z;
   }
   return B;
@@ -397,7 +390,7 @@ galoisborne(GEN T, GEN dn, struct galois_borne *gb, long d)
   gb->valabs = logint(shifti(borneabs,2), gb->l, NULL);
   gb->valabs = maxss(gb->valsol, gb->valabs);
   if (DEBUGLEVEL >= 4)
-    err_printf("GaloisConj:val1=%ld val2=%ld\n", gb->valsol, gb->valabs);
+    err_printf("GaloisConj: val1=%ld val2=%ld\n", gb->valsol, gb->valabs);
   avma = av2;
   gb->bornesol = gerepileuptoint(ltop, shifti(borneroots,1));
   if (DEBUGLEVEL >= 9)
@@ -460,9 +453,19 @@ poltopermtest(GEN f, struct galois_lift *gl, GEN pf)
   return 1;
 }
 
-static long
-monoratlift(GEN S, GEN q, GEN qm1old,struct galois_lift *gl, GEN frob)
+struct monoratlift
 {
+  struct galois_lift *gl;
+  GEN frob;
+  long early;
+};
+
+static int
+monoratlift(void *E, GEN S, GEN q)
+{
+  struct monoratlift *d = (struct monoratlift *) E;
+  struct galois_lift *gl = d->gl;
+  GEN qm1old = sqrti(shifti(q,-2));
   GEN tlift = FpX_ratlift(S,q,qm1old,qm1old,gl->den);
   if (tlift)
   {
@@ -473,9 +476,10 @@ monoratlift(GEN S, GEN q, GEN qm1old,struct galois_lift *gl, GEN frob)
       GEN N = gl->gb->ladicsol, N2 = shifti(N,-1);
       tlift = FpX_center(FpX_red(Q_muli_to_int(tlift, gl->den), N), N,N2);
     }
-    if (poltopermtest(tlift, gl, frob))
+    if (poltopermtest(tlift, gl, d->frob))
     {
       if(DEBUGLEVEL>=4) err_printf("MonomorphismLift: true early solution.\n");
+      d->early = 1;
       avma = ltop; return 1;
     }
     avma = ltop;
@@ -487,51 +491,18 @@ monoratlift(GEN S, GEN q, GEN qm1old,struct galois_lift *gl, GEN frob)
 static GEN
 monomorphismratlift(GEN P, GEN S, struct galois_lift *gl, GEN frob)
 {
-  pari_sp ltop, lbot;
-  GEN Q = gl->T, p = gl->p, qold = NULL, q = p;
-  GEN Sr, Spow, Wr = NULL, W, Prold = NULL, Pr, Qrold = NULL, Qr;
-  long e = gl->e, level = 1, rt;
-  ulong mask;
-  GEN *gptr[2];
   pari_timer ti;
-
-  if (DEBUGLEVEL == 1) timer_start(&ti);
-  rt = brent_kung_optpow(degpol(P), 4, 3);
-  mask = quadratic_prec_mask(e);
-  Pr = FpX_red(P,q);
-  Qr = (P==Q)? Pr: FpX_red(Q, q);/*A little speed up for automorphismlift*/
-  W = FpXQ_inv(FpX_FpXQ_eval(ZX_deriv(Pr),S, Qr,q), Qr,q);
-  gptr[0] = &S;
-  gptr[1] = &Wr;
-  for (;;)
-  {
-    if (DEBUGLEVEL>=2) { level = (level<<1) - (mask & 1); timer_start(&ti); }
-    q = sqri(q);
-    if (mask & 1) q = diviiexact(q, p);
-    mask >>= 1;
-    Pr = FpX_red(P, q);
-    Qr = (P==Q)? Pr: FpX_red(Q, q);/*A little speed up for automorphismlift*/
-    ltop = avma;
-    Sr = S;
-    Spow = FpXQ_powers(Sr, rt, Qr, q);
-    if (Wr)
-    {
-      W = FpXQ_mul(Wr, FpX_FpXQV_eval(ZX_deriv(Prold),FpXV_red(Spow,qold),Qrold,qold),
-                   Qrold,qold);
-      W = FpXQ_mul(Wr, Fp_FpX_sub(gen_2, W, qold), Qrold,qold);
-    }
-    Wr = W;
-    S = FpXQ_mul(Wr, FpX_FpXQV_eval(Pr, Spow, Qr, q),Qr,q);
-    lbot = avma;
-    S = FpX_sub(Sr, S, q);
-    if (DEBUGLEVEL >= 4) timer_printf(&ti, "MonomorphismLift: lift to prec %d",level);
-    if (mask == 1) break;
-    Wr = ZX_copy(Wr);
-    gerepilemanysp(ltop, lbot, gptr, 2);
-    if (qold && frob && monoratlift(S,q,diviiexact(qold,p),gl,frob)) return NULL;
-    qold = q; Prold = Pr; Qrold = Qr;
-  }
-  if (DEBUGLEVEL == 1) timer_printf(&ti, "monomorphismlift()");
+  if (DEBUGLEVEL >= 1) timer_start(&ti);
+  if (frob)
+  {
+    struct monoratlift d;
+    d.gl = gl; d.frob = frob; d.early = 0;
+    S = ZpX_ZpXQ_liftroot_ea(P,S,gl->T,gl->p, gl->e, (void*)&d, monoratlift);
+    S = d.early ? NULL: S;
+  }
+  else
+    S = ZpX_ZpXQ_liftroot(P,S,gl->T,gl->p, gl->e);
+  if (DEBUGLEVEL >= 1) timer_printf(&ti, "monomorphismlift()");
   return S;
 }
 
@@ -544,26 +515,12 @@ automorphismlift(GEN S, struct galois_lift *gl, GEN frob)
   return monomorphismratlift(gl->T, S, gl, frob);
 }
 
-/* Let P be a polynomial in Z[X] , p a prime number, S in Fp[X]/(Q) so
- * that T(S)=0 [p,T]. Lift S in S_0 so that T(S_0)=0 [Q,p^e]
- * Unclean stack */
-
-GEN
-monomorphismlift(GEN P, GEN S, GEN Q, GEN p, long e)
-{
-  struct galois_lift gl;
-  gl.T = Q;
-  gl.p = p;
-  gl.e = e;
-  return monomorphismratlift(P,S,&gl,NULL);
-}
-
 static GEN
 galoisdolift(struct galois_lift *gl, GEN frob)
 {
   pari_sp av = avma;
   GEN Tp = FpX_red(gl->T, gl->p);
-  GEN S = FpXQ_pow(pol_x(varn(Tp)), gl->p, Tp, gl->p);
+  GEN S = FpX_Frobenius(Tp, gl->p);
   return gerepileupto(av, automorphismlift(S, gl, frob));
 }
 
@@ -639,7 +596,7 @@ frobeniusliftall(GEN sg, long el, GEN *psi, struct galois_lift *gl,
   ltop2 = avma;
   NN = diviiexact(mpfact(m), mului(c, powiu(mpfact(d), c)));
   if (DEBUGLEVEL >= 4)
-    err_printf("GaloisConj:I will try %Ps permutations\n", NN);
+    err_printf("GaloisConj: I will try %Ps permutations\n", NN);
   N1=10000000;
   NQ=divis_rem(NN,N1,&R1);
   if (cmpiu(NQ,1000000000)>0)
@@ -735,7 +692,7 @@ inittest(GEN L, GEN M, GEN borne, GEN ladic, struct galois_test *td)
 {
   long i, n = lg(L)-1;
   GEN p = cgetg(n+1, t_VECSMALL);
-  if (DEBUGLEVEL >= 8) err_printf("GaloisConj:Init Test\n");
+  if (DEBUGLEVEL >= 8) err_printf("GaloisConj: Init Test\n");
   td->order = p;
   for (i = 1; i <= n-2; i++) p[i] = i+2;
   p[n-1] = 1; p[n] = 2;
@@ -847,13 +804,14 @@ testpermutation(GEN F, GEN B, GEN x, long s, long e, long cut,
     if (i == d) { i = 0; j++; }
   }
   NN = divis(powuu(b, c * (d - d/e)), cut);
-  if (DEBUGLEVEL>=4) err_printf("GaloisConj:I will try %Ps permutations\n", NN);
+  if (DEBUGLEVEL>=4) err_printf("GaloisConj: I will try %Ps permutations\n", NN);
   N1 = 1000000;
   NQ = divis_rem(NN,N1,&R1);
   if (cmpiu(NQ,100000000)>0)
   {
     avma = avm;
-    pari_warn(warner,"Combinatorics too hard : would need %Ps tests!\n I'll skip it but you will get a partial result...",NN);
+    pari_warn(warner,"Combinatorics too hard: would need %Ps tests!\n"
+                     "I'll skip it but you will get a partial result...",NN);
     return identity_perm(n);
   }
   N2 = itos(NQ);
@@ -919,7 +877,7 @@ testpermutation(GEN F, GEN B, GEN x, long s, long e, long cut,
           GEN nb = addis(mulss(l2,N1),l1);
           timer_printf(&ti, "testpermutation(%Ps)", nb);
           if (DEBUGLEVEL >= 2 && hop)
-            err_printf("GaloisConj:%d hop over %Ps iterations\n", hop, nb);
+            err_printf("GaloisConj: %d hop over %Ps iterations\n", hop, nb);
         }
         avma = av; return pf;
       }
@@ -930,7 +888,7 @@ testpermutation(GEN F, GEN B, GEN x, long s, long e, long cut,
   {
     timer_printf(&ti, "testpermutation(%Ps)", NN);
     if (DEBUGLEVEL >= 2 && hop)
-      err_printf("GaloisConj:%d hop over %Ps iterations\n", hop, NN);
+      err_printf("GaloisConj: %d hop over %Ps iterations\n", hop, NN);
   }
   avma = avm; return NULL;
 }
@@ -1140,7 +1098,7 @@ vandermondeinversemod(GEN L, GEN T, GEN den, GEN mod)
     z = Fp_inv(FpX_eval(Tp, gel(L,i),mod),mod);
     z = Fp_mul(den,z,mod);
     P = FpX_Fp_mul(FpX_div_by_X_x(T, gel(L,i), mod, NULL), z, mod);
-    gel(M,i) = gerepilecopy(av, RgX_to_RgV(P, n-1));
+    gel(M,i) = gerepilecopy(av, RgX_to_RgC(P, n-1));
   }
   gunclone(Tp); /*unclone*/
   return M;
@@ -1373,7 +1331,7 @@ a4galoisgen(struct galois_test *td)
   /* N = itos(gdiv(mpfact(n), mpfact(n >> 1))) >> (n >> 1); */
   /* n = 2k = 12; N = (2k)! / (k! * 2^k) = 10395 */
   N = 10395;
-  if (DEBUGLEVEL>=4) err_printf("A4GaloisConj:will test %ld permutations\n", N);
+  if (DEBUGLEVEL>=4) err_printf("A4GaloisConj: will test %ld permutations\n", N);
   uel(ar,4) = umael(MT,11,12);
   uel(ar,3) = uel(ar,4) + umael(MT,9,10);
   uel(ar,2) = uel(ar,3) + umael(MT,7,8);
@@ -1437,7 +1395,7 @@ a4galoisgen(struct galois_test *td)
   if (i == N) { avma = ltop; return gen_0; }
   /* N = itos(gdiv(mpfact(n >> 1), mpfact(n >> 2))) >> 1; */
   N = 60;
-  if (DEBUGLEVEL >= 4) err_printf("A4GaloisConj:sigma=%Ps \n", pft);
+  if (DEBUGLEVEL >= 4) err_printf("A4GaloisConj: sigma=%Ps \n", pft);
   for (k = 0; k < n; k += 4)
   {
     u[k+3] = t[k+3];
@@ -1497,13 +1455,13 @@ a4galoisgen(struct galois_test *td)
   if (i == N) { avma = ltop; return gen_0; }
   if (DEBUGLEVEL >= 1 && hop)
     err_printf("A4GaloisConj: %ld hop over %ld iterations\n", hop, N);
-  if (DEBUGLEVEL >= 4) err_printf("A4GaloisConj:tau=%Ps \n", pfu);
+  if (DEBUGLEVEL >= 4) err_printf("A4GaloisConj: tau=%Ps \n", pfu);
   avma = av2;
   orb = mkvec2(pft,pfu);
   O = vecperm_orbits(orb, 12);
   if (DEBUGLEVEL >= 4) {
-    err_printf("A4GaloisConj:orb=%Ps\n", orb);
-    err_printf("A4GaloisConj:O=%Ps \n", O);
+    err_printf("A4GaloisConj: orb=%Ps\n", orb);
+    err_printf("A4GaloisConj: O=%Ps \n", O);
   }
   av2 = avma;
   O1 = gel(O,1); O2 = gel(O,2); O3 = gel(O,3);
@@ -1536,7 +1494,7 @@ a4galoisgen(struct galois_test *td)
       {
         avma = av;
         if (DEBUGLEVEL >= 1)
-          err_printf("A4GaloisConj:%ld hop over %d iterations max\n",
+          err_printf("A4GaloisConj: %ld hop over %d iterations max\n",
                      hop, 10395 + 68);
         return res;
       }
@@ -1653,7 +1611,7 @@ s4galoisgen(struct galois_lift *gl)
     gel(misom,i) = cgetg(lg(Tmod), t_COL);
     gel(isom,i) = FpX_ffisom(gel(Tmod,1), gel(Tmod,i), p);
     if (DEBUGLEVEL >= 6)
-      err_printf("S4GaloisConj:Computing isomorphisms %d:%Ps\n", i,
+      err_printf("S4GaloisConj: Computing isomorphisms %d:%Ps\n", i,
                  gel(isom,i));
     gel(isominv,i) = FpXQ_ffisom_inv(gel(isom,i), gel(Tmod,i),p);
   }
@@ -1689,7 +1647,7 @@ s4galoisgen(struct galois_lift *gl)
           u3 = lincomb(gel(Bcoeff,sg[1]),gel(Bcoeff,sg[2]), pauto,j3);
           u3 = FpX_rem(FpX_add(u2, u3, Q), TQ,Q);
           if (DEBUGLEVEL >= 4)
-            err_printf("S4GaloisConj:Testing %d/3:%d/4:%d/4:%d/4:%Ps\n",
+            err_printf("S4GaloisConj: Testing %d/3:%d/4:%d/4:%d/4:%Ps\n",
                        i,j1,j2,j3, sg);
           if (s4test(u3, liftpow, gl, sigma))
           {
@@ -1703,8 +1661,8 @@ s4galoisgen(struct galois_lift *gl)
   }
   avma = ltop; return gen_0;
 suites4:
-  if (DEBUGLEVEL >= 4) err_printf("S4GaloisConj:sigma=%Ps\n", sigma);
-  if (DEBUGLEVEL >= 4) err_printf("S4GaloisConj:pj=%Ps\n", pj);
+  if (DEBUGLEVEL >= 4) err_printf("S4GaloisConj: sigma=%Ps\n", sigma);
+  if (DEBUGLEVEL >= 4) err_printf("S4GaloisConj: pj=%Ps\n", pj);
   avma = av;
   for (j = 1; j <= 3; j++)
   {
@@ -1732,7 +1690,7 @@ suites4:
           pj[4] = i;
           pj[5] = (i + pj[2] - pj[1]) & 3;
           if (DEBUGLEVEL >= 4)
-            err_printf("S4GaloisConj:Testing %d/3:%d/2:%d/2:%d/4:%Ps:%Ps\n",
+            err_printf("S4GaloisConj: Testing %d/3:%d/2:%d/2:%d/4:%Ps:%Ps\n",
                        j-1, w >> 1, l, i, sg, pj);
           u = ZX_add(lincomb(gel(Bcoeff,sg[1]),gel(Bcoeff,sg[3]), pauto,pj[4]),
                      lincomb(gel(Bcoeff,sg[2]),gel(Bcoeff,sg[4]), pauto,pj[5]));
@@ -1766,7 +1724,7 @@ suites4_2:
       u = FpX_add(u, lincomb(gel(Bcoeff,sg[3]), gel(Bcoeff,sg[6]), pauto, i),Q);
       u = FpX_rem(u, TQ, Q);
       if (DEBUGLEVEL >= 4)
-        err_printf("S4GaloisConj:Testing %d/8 %d:%d:%d\n", j,g,h,i);
+        err_printf("S4GaloisConj: Testing %d/8 %d:%d:%d\n", j,g,h,i);
       if (s4test(u, liftpow, gl, phi)) break;
       avma = av2;
     }
@@ -1830,11 +1788,12 @@ galoisfrobeniuslift(GEN T, GEN den, GEN L,  GEN Lden,
   struct galois_lift gl;
   long i, j, k, n = lg(L)-1, deg = 1, g = lg(gf->Tmod)-1;
   GEN F,Fp,Fe, aut, frob, ip = utoipos(gf->p), res = cgetg(lg(L), t_VECSMALL);
-  if (DEBUGLEVEL >= 4)
-    err_printf("GaloisConj:p=%ld deg=%ld fp=%ld\n", gf->p, deg, gf->fp);
   gf->psi = const_vecsmall(g,1);
   av2 = avma;
   initlift(T, den, ip, L, Lden, gb, &gl);
+  if (DEBUGLEVEL >= 4)
+    err_printf("GaloisConj: p=%ld e=%ld deg=%ld fp=%ld\n",
+                            gf->p, gl.e, deg, gf->fp);
   aut = galoisdolift(&gl, res);
   if (!aut || galoisfrobeniustest(aut,&gl,res))
   {
@@ -2015,7 +1974,7 @@ galoisgenfixedfield(GEN Tp, GEN Pmod, GEN V, GEN ip, struct galois_borne *gb)
     if (Pgb.valabs > gb->valabs)
     {
       if (DEBUGLEVEL>=4)
-        err_printf("GaloisConj:increase prec of p-adic roots of %ld.\n"
+        err_printf("GaloisConj: increase prec of p-adic roots of %ld.\n"
             ,Pgb.valabs-gb->valabs);
       PL = ZpX_liftroots(P,PL,gb->l,Pgb.valabs);
     }
@@ -2148,11 +2107,11 @@ galoisgen(GEN T, GEN L, GEN M, GEN den, struct galois_borne *gb,
 
   if (!ga->deg) return gen_0;
   x = varn(T);
-  if (DEBUGLEVEL >= 9) err_printf("GaloisConj:denominator:%Ps\n", den);
+  if (DEBUGLEVEL >= 9) err_printf("GaloisConj: denominator:%Ps\n", den);
   if (n == 12 && ga->ord==3 && !ga->p4)
   { /* A4 is very probable: test it first */
     pari_sp av = avma;
-    if (DEBUGLEVEL >= 4) err_printf("GaloisConj:Testing A4 first\n");
+    if (DEBUGLEVEL >= 4) err_printf("GaloisConj: Testing A4 first\n");
     inittest(L, M, gb->bornesol, gb->ladicsol, &td);
     PG = a4galoisgen(&td);
     freetest(&td);
@@ -2163,7 +2122,7 @@ galoisgen(GEN T, GEN L, GEN M, GEN den, struct galois_borne *gb,
   { /* S4 is very probable: test it first */
     pari_sp av = avma;
     struct galois_lift gl;
-    if (DEBUGLEVEL >= 4) err_printf("GaloisConj:Testing S4 first\n");
+    if (DEBUGLEVEL >= 4) err_printf("GaloisConj: Testing S4 first\n");
     initlift(T, den, stoi(ga->p4), L, makeLden(L,den,gb), gb, &gl);
     PG = s4galoisgen(&gl);
     if (PG != gen_0) return gerepileupto(ltop, PG);
@@ -2175,11 +2134,11 @@ galoisgen(GEN T, GEN L, GEN M, GEN den, struct galois_borne *gb,
   Tmod = gf.Tmod;
   O = perm_cycles(frob);
   deg = lg(gel(O,1))-1;
-  if (DEBUGLEVEL >= 9) err_printf("GaloisConj:Orbite:%Ps\n", O);
+  if (DEBUGLEVEL >= 9) err_printf("GaloisConj: Orbit:%Ps\n", O);
   if (deg == n)        /* cyclic */
     return gerepilecopy(ltop, mkvec2(mkvec(frob), mkvecsmall(deg)));
   sigma = permtopol(frob, L, M, den, gb->ladicabs, shifti(gb->ladicabs,-1), x);
-  if (DEBUGLEVEL >= 9) err_printf("GaloisConj:Frobenius:%Ps\n", sigma);
+  if (DEBUGLEVEL >= 9) err_printf("GaloisConj: Frobenius:%Ps\n", sigma);
   {
     pari_sp btop=avma;
     GEN V, Tp, Sp, Pmod;
@@ -2190,7 +2149,7 @@ galoisgen(GEN T, GEN L, GEN M, GEN den, struct galois_borne *gb,
     Pmod = fixedfieldfactmod(Sp,ip,Tmod);
     PG = galoisgenfixedfield(Tp, Pmod, V, ip, gb);
     if (PG == NULL) { avma = ltop; return gen_0; }
-    if (DEBUGLEVEL >= 4) err_printf("GaloisConj:Back to Earth:%Ps\n", PG);
+    if (DEBUGLEVEL >= 4) err_printf("GaloisConj: Back to Earth:%Ps\n", PG);
     PG=gerepilecopy(btop, PG);
   }
   inittest(L, M, gb->bornesol, gb->ladicsol, &td);
@@ -2207,7 +2166,7 @@ galoisgen(GEN T, GEN L, GEN M, GEN den, struct galois_borne *gb,
     if (!pf) { freetest(&td); avma = ltop; return gen_0; }
     gel(res1, j+1) = pf;
   }
-  if (DEBUGLEVEL >= 4) err_printf("GaloisConj:Fini!\n");
+  if (DEBUGLEVEL >= 4) err_printf("GaloisConj: Fini!\n");
   freetest(&td);
   return gerepileupto(ltop, res);
 }
@@ -2273,8 +2232,8 @@ galoisconj4_main(GEN T, GEN den, long flag)
   if (DEBUGLEVEL >= 1) timer_start(&ti);
   den = galoisborne(T, den, &gb, degpol(T));
   if (DEBUGLEVEL >= 1) timer_printf(&ti, "galoisborne()");
-  L = rootpadicfast(T, gb.l, gb.valabs);
-  if (DEBUGLEVEL >= 1) timer_printf(&ti, "rootpadicfast()");
+  L = ZpX_roots(T, gb.l, gb.valabs);
+  if (DEBUGLEVEL >= 1) timer_printf(&ti, "ZpX_roots");
   M = vandermondeinversemod(L, T, den, gb.ladicabs);
   if (DEBUGLEVEL >= 1) timer_printf(&ti, "vandermondeinversemod()");
   if (n == 1)
@@ -2285,7 +2244,7 @@ galoisconj4_main(GEN T, GEN den, long flag)
   }
   else
     G = galoisgen(T, L, M, den, &gb, &ga);
-  if (DEBUGLEVEL >= 6) err_printf("GaloisConj:%Ps\n", G);
+  if (DEBUGLEVEL >= 6) err_printf("GaloisConj: %Ps\n", G);
   if (G == gen_0) { avma = ltop; return gen_0; }
   if (DEBUGLEVEL >= 1) timer_start(&ti);
   if (flag)
@@ -2318,7 +2277,7 @@ numberofconjugates(GEN T, long pinit)
   nbmax = (n < 10)? 20: (n<<1) + 1;
   nbtest = 0;
 #if 0
-  c = sturm(T); c = ugcd(c, n - c); /* too costly: finite primes are cheaper */
+  c = ZX_sturm(T); c = ugcd(c, n-c); /* too costly: finite primes are cheaper */
 #else
   c = n;
 #endif
@@ -2361,7 +2320,7 @@ galoisconj4(GEN nf, GEN d)
 
 }
 
-/* d multipllicative bound for the automorphism's denominators */
+/* d multiplicative bound for the automorphism's denominators */
 GEN
 galoisconj(GEN nf, GEN d)
 {
@@ -2545,13 +2504,13 @@ galoisfixedfield(GEN gal, GEN perm, long flag, long y)
     if (Pgb.valabs > val)
     {
       if (DEBUGLEVEL>=4)
-        err_printf("GaloisConj:increase p-adic prec by %ld.\n", Pgb.valabs-val);
+        err_printf("GaloisConj: increase p-adic prec by %ld.\n", Pgb.valabs-val);
       PL = ZpX_liftroots(P, PL, Pgb.l, Pgb.valabs);
       L  = ZpX_liftroots(T, L, Pgb.l, Pgb.valabs);
       mod = Pgb.ladicabs; mod2 = shifti(mod,-1);
     }
     PM = vandermondeinversemod(PL, P, Pden, mod);
-    if (y < 0) y = fetch_user_var("y");
+    if (y < 0) y = 1;
     if (varncmp(y, vT) <= 0)
       pari_err_PRIORITY("galoisfixedfield", T, "<=", y);
     res = cgetg(4, t_VEC);
diff --git a/src/basemath/gen1.c b/src/basemath/gen1.c
index b5e653f..480a587 100644
--- a/src/basemath/gen1.c
+++ b/src/basemath/gen1.c
@@ -30,6 +30,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 else\
   gerepilecoeffssp((pari_sp)z, tetpil, z+1, 2); }
 
+static void
+warn_coercion(GEN x, GEN y, GEN z)
+{
+  if (DEBUGLEVEL)
+   pari_warn(warner,"coercing quotient rings; moduli %Ps and %Ps -> %Ps",x,y,z);
+}
+
 static long
 kro_quad(GEN x, GEN y)
 {
@@ -199,7 +206,7 @@ static GEN
 div_intmod_same(GEN z, GEN X, GEN x, GEN y)
 {
   if (lgefint(X) == 3) {
-    ulong m = (ulong)X[2], u = Fl_div(itou(x), itou(y), m);
+    ulong m = uel(X,2), u = Fl_div(itou(x), itou(y), m);
     avma = (pari_sp)z; gel(z,2) = utoi(u);
   }
   else
@@ -243,6 +250,7 @@ gred_rfrac_simple(GEN n, GEN d)
   }
 
   cd = content(d);
+  while (typ(n) == t_POL && !degpol(n)) n = gel(n,2);
   cn = (typ(n) == t_POL && varn(n) == varn(d))? content(n): n;
   if (!gequal1(cd)) {
     d = RgX_Rg_div(d,cd);
@@ -682,6 +690,7 @@ addsub_polmod(GEN X, GEN Y, GEN x, GEN y, GEN(*op)(GEN,GEN))
   if (vx==vy) {
     pari_sp av;
     gel(z,1) = RgX_gcd(X,Y); av = avma;
+    warn_coercion(X,Y,gel(z,1));
     gel(z,2) = gerepileupto(av, gmod(op(x, y), gel(z,1))); return z;
   }
   if (varncmp(vx, vy) < 0)
@@ -699,23 +708,12 @@ addsub_polmod_scal(GEN Y, GEN y, GEN x, GEN(*op)(GEN,GEN))
   gel(z,2) = op(y, x); return z;
 }
 
-/* check y[a..b-1] and set signe to 1 if one coeff is non-0, 0 otherwise
- * For t_POL and t_SER */
-static GEN
-NORMALIZE_i(GEN y, long a, long b)
-{
-  long i;
-  for (i = a; i < b; i++)
-    if (!gequal0(gel(y,i))) { setsigne(y, 1); return y; }
-  setsigne(y, 0); return y;
-}
 /* typ(y) == t_SER, x "scalar" [e.g object in lower variable] */
 static GEN
 add_ser_scal(GEN y, GEN x)
 {
-  long i, j, l, ly, vy;
-  pari_sp av;
-  GEN z, t;
+  long i, l, ly, vy;
+  GEN z;
 
   if (isrationalzero(x)) return gcopy(y);
   ly = lg(y);
@@ -728,47 +726,54 @@ add_ser_scal(GEN y, GEN x)
     for (i = 2; i <= 1-l; i++) gel(z,i) = gcopy(gel(y,i));
     gel(z,i) = gadd(x,gel(y,i)); i++;
     for (     ; i < ly; i++)   gel(z,i) = gcopy(gel(y,i));
-    return NORMALIZE_i(z, 2, ly);
+    return z;
   }
   vy = varn(y);
   if (l > 0)
   {
-    ly += l; y -= l; z = cgetg(ly,t_SER);
-    z[1] = evalsigne(1) | _evalvalp(0) | evalvarn(vy);
-    gel(z,2) = gcopy(x);
+    if (ser_isexactzero(y))
+      return scalarser(ly == 2? x: gadd(x,gel(y,2)), vy, l);
+    y -= l; ly += l;
+    z = cgetg(ly,t_SER);
+    x = gcopy(x);
     for (i=3; i<=l+1; i++) gel(z,i) = gen_0;
-    for (   ; i < ly; i++) gel(z,i) = gcopy(gel(y,i));
-    if (gequal0(x)) return normalize(z);
-    return z;
   }
-  /* l = 0, ly >= 3, !isrationalzero(x) */
-  av = avma; z = cgetg(ly,t_SER);
-  x = gadd(x, gel(y,2));
-  if (!isrationalzero(x))
-  {
-    z[1] = evalsigne(1) | _evalvalp(0) | evalvarn(vy);
-    gel(z,2) = x;
-    for (i=3; i<ly; i++) gel(z,i) = gcopy(gel(y,i));
-    if (gequal0(x)) return normalize(z);
-    return z;
+  else
+  { /* l = 0, ly >= 3. Also OK if ser_isexactzero(y) */
+    z = cgetg(ly,t_SER);
+    x = gadd(x, gel(y,2));
+    i = 3;
   }
-  avma = av; /* first coeff is rational 0 */
-  i = 3;
-  while (i<ly && isrationalzero(gel(y,i))) i++;
-  if (i == ly) return zeroser(vy, ly-2);
-  t = gel(y,i);
-  while (i<ly && isexactzero(gel(y,i))) i++;
-  if (i == ly)
-  {
-    z = cgetg(3, t_SER);
-    z[1] = evalsigne(0) | _evalvalp(i-2) | evalvarn(vy);
-    gel(z,2) = gcopy(t); return gerepileupto(av, z);
+  for (; i<ly; i++) gel(z,i) = gcopy(gel(y,i));
+  gel(z,2) = x;
+  z[1] = evalsigne(1) | _evalvalp(0) | evalvarn(vy);
+  return gequal0(x)? normalize(z): z;
+}
+static long
+serprec(GEN x) { return ser_isexactzero(x)? 2: lg(x); }
+/* x,y t_SER in the same variable: x+y */
+static GEN
+ser_add(GEN x, GEN y)
+{
+  long i, lx,ly, n = valp(y) - valp(x);
+  GEN z;
+  if (n < 0) { n = -n; swap(x,y); }
+  /* valp(x) <= valp(y) */
+  lx = serprec(x);
+  if (lx == 2) /* don't lose type information */
+    return scalarser(gadd(RgX_get_0(x), RgX_get_0(y)), varn(x), valp(x));
+  ly = serprec(y) + n; if (lx < ly) ly = lx;
+  if (n)
+  {
+    if (n+2 > lx) return gcopy(x);
+    z = cgetg(ly,t_SER);
+    for (i=2; i<=n+1; i++) gel(z,i) = gcopy(gel(x,i));
+    for (   ; i < ly; i++) gel(z,i) = gadd(gel(x,i),gel(y,i-n));
+  } else {
+    z = cgetg(ly,t_SER);
+    for (i=2; i < ly; i++) gel(z,i) = gadd(gel(x,i),gel(y,i));
   }
-
-  i -= 2; ly -= i; y += i;
-  z = cgetg(ly,t_SER); z[1] = evalvalp(i) | evalvarn(vy);
-  for (j = 2; j < ly; j++) gel(z,j) = gcopy(gel(y,j));
-  return NORMALIZE_i(z, 2, ly);
+  z[1] = x[1]; return normalize(z);
 }
 /* typ(y) == RFRAC, x polynomial in same variable or "scalar" */
 static GEN
@@ -944,7 +949,7 @@ add_rfrac(GEN x, GEN y)
 GEN
 gadd(GEN x, GEN y)
 {
-  long tx = typ(x), ty = typ(y), vx, vy, lx, ly, i, l;
+  long tx = typ(x), ty = typ(y), vx, vy, lx, i, l;
   pari_sp av, tetpil;
   GEN z, p1;
 
@@ -957,6 +962,7 @@ gadd(GEN x, GEN y)
       if (X==Y || equalii(X,Y))
         return add_intmod_same(z, X, gel(x,2), gel(y,2));
       gel(z,1) = gcdii(X,Y);
+      warn_coercion(X,Y,gel(z,1));
       av = avma; p1 = addii(gel(x,2),gel(y,2));
       gel(z,2) = gerepileuptoint(av, remii(p1, gel(z,1))); return z;
     }
@@ -998,22 +1004,7 @@ gadd(GEN x, GEN y)
         if (varncmp(vx, vy) < 0) return add_ser_scal(x, y);
         else                     return add_ser_scal(y, x);
       }
-      l = valp(y) - valp(x);
-      if (l < 0) { l = -l; swap(x,y); }
-      /* valp(x) <= valp(y) */
-      lx = lg(x);
-      ly = lg(y) + l; if (lx < ly) ly = lx;
-      if (l)
-      {
-        if (l > lx-2) return gcopy(x);
-        z = cgetg(ly,t_SER);
-        for (i=2; i<=l+1; i++) gel(z,i) = gcopy(gel(x,i));
-        for (   ; i < ly; i++) gel(z,i) = gadd(gel(x,i),gel(y,i-l));
-      } else {
-        z = cgetg(ly,t_SER);
-        for (i=2; i < ly; i++) gel(z,i) = gadd(gel(x,i),gel(y,i));
-      }
-      z[1] = x[1]; return normalize(z);
+      return ser_add(x, y);
     case t_RFRAC:
       vx = varn(gel(x,2));
       vy = varn(gel(y,2));
@@ -1169,7 +1160,7 @@ gadd(GEN x, GEN y)
           i = lg(y) + valp(y) - RgX_val(x);
           if (i < 3) return gcopy(y);
 
-          p1 = RgX_to_ser(x,i); y = gadd(p1,y);
+          p1 = RgX_to_ser(x,i); y = ser_add(p1,y);
           settyp(p1, t_VECSMALL); /* p1 left on stack */
           return y;
 
@@ -1276,6 +1267,7 @@ gsub(GEN x, GEN y)
       if (X==Y || equalii(X,Y))
         return sub_intmod_same(z, X, gel(x,2), gel(y,2));
       gel(z,1) = gcdii(X,Y);
+      warn_coercion(X,Y,gel(z,1));
       av = avma; p1 = subii(gel(x,2),gel(y,2));
       gel(z,2) = gerepileuptoint(av, modii(p1, gel(z,1))); return z;
     }
@@ -1341,7 +1333,12 @@ static GEN
 mul_ser_scal(GEN y, GEN x) {
   long ly, i;
   GEN z;
-  if (isrationalzero(x)) return zeropol(varn(y));
+  if (isexactzero(x)) return gmul(RgX_get_0(y), x);
+  if (ser_isexactzero(y))
+  {
+    if (lg(y) == 2) return gcopy(y);
+    return scalarser(gmul(x,gel(y,2)), varn(y), valp(y));
+  }
   z = cgetg_copy(y, &ly); z[1] = y[1];
   for (i = 2; i < ly; i++) gel(z,i) = gmul(x,gel(y,i));
   return normalize(z);
@@ -1577,6 +1574,7 @@ mul_polmod(GEN X, GEN Y, GEN x, GEN y)
   if (vx==vy) {
     pari_sp av;
     gel(z,1) = RgX_gcd(X,Y); av = avma;
+    warn_coercion(X,Y,gel(z,1));
     gel(z,2) = gerepileupto(av, gmod(gmul(x, y), gel(z,1)));
     return z;
   }
@@ -1707,7 +1705,7 @@ mulcc(GEN x, GEN y)
   gel(z,1) = gadd(p1,p2);
   gel(z,2) = gadd(p3,p4);
 #else
-  if (typ(xr)==t_INT && typ(yr)==t_INT && typ(xi)==t_INT && typ(yr)==t_INT)
+  if (typ(xr)==t_INT && typ(yr)==t_INT && typ(xi)==t_INT && typ(yi)==t_INT)
   { /* 3M formula */
     p3 = addii(xr,xi);
     p4 = addii(yr,yi);
@@ -1847,7 +1845,9 @@ gmul(GEN x, GEN y)
       z = cgetg(3,t_INTMOD);
       if (X==Y || equalii(X,Y))
         return mul_intmod_same(z, X, gel(x,2), gel(y,2));
-      gel(z,1) = gcdii(X,Y); av = avma; p1 = mulii(gel(x,2),gel(y,2));
+      gel(z,1) = gcdii(X,Y);
+      warn_coercion(X,Y,gel(z,1));
+      av = avma; p1 = mulii(gel(x,2),gel(y,2));
       gel(z,2) = gerepileuptoint(av, remii(p1, gel(z,1))); return z;
     }
     case t_FRAC:
@@ -1908,7 +1908,7 @@ gmul(GEN x, GEN y)
         }
       }
       else
-        y = RgX_mullow(x, y, lx-2);
+        y = RgXn_mul(x, y, lx-2);
       z = fill_ser(z, y);
       return gerepilecopy((pari_sp)(z + lx), z);
     }
@@ -2134,7 +2134,7 @@ ff_poltype(GEN *x, GEN *p, GEN *pol)
 {
   GEN Q, P = *x;
   if (!signe(P)) return 0;
-  if (!RgX_is_FpXQX(P,pol,p) || !*p || !*pol)
+  if (!RgX_is_FpXQX(P,pol,p) || !*p || !*pol || typ(*pol)!=t_POL)
     return 0;
   Q = RgX_to_FpX(*pol, *p);
   P = RgX_to_FpXQX(P, Q, *p);
@@ -2143,6 +2143,7 @@ ff_poltype(GEN *x, GEN *p, GEN *pol)
   return 1;
 }
 
+/* return a non-normalized result */
 GEN
 sqr_ser_part(GEN x, long l1, long l2)
 {
@@ -2261,6 +2262,11 @@ gsqr(GEN x)
 
     case t_SER:
       lx = lg(x);
+      if (ser_isexactzero(x)) {
+        GEN z = gcopy(x);
+        setvalp(z, 2*valp(x));
+        return z;
+      }
       if (lx < 40)
         return normalize( sqr_ser_part(x, 0, lx-3) );
       else
@@ -2279,7 +2285,7 @@ gsqr(GEN x)
           }
         }
         else
-          x = RgX_sqrlow(x, lx-2);
+          x = RgXn_sqr(x, lx-2);
         z = fill_ser(z, x);
         return gerepilecopy(av, z);
       }
@@ -2322,8 +2328,11 @@ div_scal_rfrac(GEN x, GEN y)
 {
   GEN y1 = gel(y,1), y2 = gel(y,2);
   pari_sp av = avma;
-  if (typ(y1) == t_POL && varn(y2) == varn(y1) && degpol(y1) > 0)
-    return gerepileupto(av, gred_rfrac_simple(gmul(x, y2), y1));
+  if (typ(y1) == t_POL && varn(y2) == varn(y1))
+  {
+    if (degpol(y1)) return gerepileupto(av, gred_rfrac_simple(gmul(x, y2), y1));
+    y1 = gel(y1,2);
+  }
   return RgX_Rg_mul(y2, gdiv(x,y1));
 }
 static GEN
@@ -2333,7 +2342,13 @@ div_rfrac(GEN x, GEN y)
 static GEN
 div_ser_scal(GEN x, GEN y) {
   long i, lx;
-  GEN z = cgetg_copy(x, &lx); z[1] = x[1];
+  GEN z;
+  if (ser_isexactzero(x))
+  {
+    if (lg(x) == 2) return gcopy(x);
+    return scalarser(gdiv(gel(x,2), y), varn(x), valp(x));
+  }
+  z = cgetg_copy(x, &lx); z[1] = x[1];
   for (i=2; i<lx; i++) gel(z,i) = gdiv(gel(x,i),y);
   return normalize(z);
 }
@@ -2401,7 +2416,11 @@ div_ser(GEN x, GEN y, long vx)
   GEN y_lead, p1, p2, z;
 
   if (!signe(y)) pari_err_INV("div_ser", y);
-  if (lx == 2) return zeroser(vx, l);
+  if (ser_isexactzero(x))
+  {
+    if (lx == 2) return zeroser(vx, l);
+    return scalarser(gmul(gel(x,2),RgX_get_0(y)), varn(x), l);
+  }
   y_lead = gel(y,2);
   if (gequal0(y_lead)) /* normalize denominator if leading term is 0 */
   {
@@ -2523,8 +2542,9 @@ gdiv(GEN x, GEN y)
       z = cgetg(3,t_INTMOD);
       if (X==Y || equalii(X,Y))
         return div_intmod_same(z, X, gel(x,2), gel(y,2));
-      gel(z,1) = gcdii(X,Y); av = avma;
-      p1 = mulii(gel(x,2), Fp_inv(gel(y,2), gel(z,1)));
+      gel(z,1) = gcdii(X,Y);
+      warn_coercion(X,Y,gel(z,1));
+      av = avma; p1 = mulii(gel(x,2), Fp_inv(gel(y,2), gel(z,1)));
       gel(z,2) = gerepileuptoint(av, remii(p1, gel(z,1))); return z;
     }
     case t_FRAC: {
@@ -2668,7 +2688,11 @@ gdiv(GEN x, GEN y)
         return gerepile(av, tetpil, gdiv(p2,p1));
     }
   }
-  if (gequal0(y) && ty != t_MAT) pari_err_INV("gdiv",y);
+  if (gequal0(y))
+  {
+    if (is_matvec_t(tx) && lg(x) == 1) return gcopy(x);
+    if (ty != t_MAT) pari_err_INV("gdiv",y);
+  }
 
   if (is_const_t(tx) && is_const_t(ty)) switch(tx)
   {
@@ -2980,7 +3004,8 @@ gmulsg(long s, GEN y)
       return normalizepol_lg(z, ly);
 
     case t_SER:
-      if (!s) return zeropol(varn(y));
+      if (ser_isexactzero(y)) return gcopy(y);
+      if (!s) return scalarser(RgX_get_0(y), varn(y), valp(y));
       z = cgetg_copy(y, &ly); z[1]=y[1];
       for (i=2; i<ly; i++) gel(z,i) = gmulsg(s,gel(y,i));
       return normalize(z);
@@ -3009,12 +3034,16 @@ gmulsg(long s, GEN y)
 GEN
 gdivgs(GEN x, long s)
 {
-  long lx, i;
+  long tx = typ(x), lx, i;
   pari_sp av;
   GEN z, y, p1;
 
-  if (!s) pari_err_INV("gdivgs",gen_0);
-  switch(typ(x))
+  if (!s)
+  {
+    if (is_matvec_t(tx) && lg(x) == 1) return gcopy(x);
+    pari_err_INV("gdivgs",gen_0);
+  }
+  switch(tx)
   {
     case t_INT:
       av = avma; z = divis_rem(x,s,&i);
@@ -3176,6 +3205,7 @@ gmul2n(GEN x, long n)
       for (i=2; i<lx; i++) gel(z,i) = gmul2n(gel(x,i),n);
       return normalizepol_lg(z, lx); /* needed if char = 2 */
     case t_SER:
+      if (ser_isexactzero(x)) return gcopy(x);
       z = cgetg_copy(x, &lx); z[1] = x[1];
       for (i=2; i<lx; i++) gel(z,i) = gmul2n(gel(x,i),n);
       return normalize(z); /* needed if char = 2 */
@@ -3199,50 +3229,6 @@ gmul2n(GEN x, long n)
 /*                              INVERSE                            */
 /*                                                                 */
 /*******************************************************************/
-GEN
-inv_ser(GEN b)
-{
-  pari_sp av = avma, av2, lim;
-  long j, lold, l = lg(b), e = valp(b), v = varn(b);
-  GEN y, x = cgetg(l, t_SER), a = leafcopy(b);
-  ulong mask = quadratic_prec_mask(l - 2);
-
-  if (!signe(b)) pari_err_INV("inv_ser",b);
-
-  for (j = 3; j < l; j++) gel(x,j) = gen_0;
-  gel(x,2) = ginv(gel(b,2));
-  a[1] = x[1] = _evalvalp(0) | evalvarn(v) | evalsigne(1);
-  av2 = avma; lim = stack_lim(av2, 2);
-  lold = 1;
-  while (mask > 1)
-  {
-    long lnew = lold << 1;
-    GEN z;
-
-    if (mask & 1) lnew--;
-    mask >>= 1;
-    setlg(a, lnew + 2);
-    setlg(x, lnew + 2);
-    /* TODO: gmul(a,x) should be a half product (the higher half is known) */
-    z = gmul(a,x); /* = 1 + O(t^lold) */
-    y = cgetg(lnew-lold + 2, t_SER);
-    y[1] = _evalvalp(lold) | evalvarn(v) | evalsigne(1);
-    for (j = 2; j < 2+lnew-lold; j++) gel(y,j) = gel(z,j+lold);
-    /* y = a*x - 1; */
-    y = gsub(x, gmul(x, y));
-    for (j = lold+2; j < lnew+2; j++) x[j] = y[j];
-    if (low_stack(lim, stack_lim(av2,2)))
-    {
-      if(DEBUGMEM>1) pari_warn(warnmem,"inv_ser");
-      y = gerepilecopy(av2, x);
-      for (j = 2; j < lnew+2; j++) x[j] = y[j];
-    }
-    lold = lnew;
-  }
-  x[1] = evalvalp(valp(x)-e) | evalvarn(v) | evalsigne(1);
-  return gerepilecopy(av, x);
-}
-
 static GEN
 inv_polmod(GEN T, GEN x)
 {
diff --git a/src/basemath/gen2.c b/src/basemath/gen2.c
index 75547fd..f30c789 100644
--- a/src/basemath/gen2.c
+++ b/src/basemath/gen2.c
@@ -160,11 +160,8 @@ greffe_aux(GEN x, long l, long lx, long v)
 GEN
 RgX_to_ser(GEN x, long l)
 {
-  long i, lx = lg(x);
-  if (lx == 2) return zeroser(varn(x), l-2);
-  /* analogous to RgX_valrem + normalize */
-  i = 2; while (i<lx && isrationalzero(gel(x,i))) i++;
-  return greffe_aux(x, l, lx, i - 2);
+  if (lg(x) == 2) return zeroser(varn(x), l-2);
+  return greffe_aux(x, l, lg(x), RgX_val(x));
 }
 GEN
 RgX_to_ser_inexact(GEN x, long l)
@@ -338,7 +335,7 @@ static int
 is_monomial_test(GEN x, long v, int(*test)(GEN))
 {
   long d, i, l;
-  if (!signe(x)) return 0;
+  if (!signe(x)) return (typ(x) == t_SER && v <= 0);
   if (v > 0) return 0;
   l = lg(x); d = 2-v;
   if (l <= d) return 0;
@@ -354,7 +351,7 @@ static int
 col_test(GEN x, int(*test)(GEN))
 {
   long i, l = lg(x);
-  if (l == 1) return 0;
+  if (l == 1) return 1;
   if (!test(gel(x,1))) return 0;
   for (i = 2; i < l; i++)
     if (!gequal0(gel(x,i))) return 0;
@@ -386,8 +383,11 @@ gequal1(GEN x)
       return equali1(x);
 
     case t_REAL:
-      return signe(x) > 0 ? absrnz_equal1(x): 0;
-
+    {
+      long s = signe(x);
+      if (!s) return expo(x) >= 0;
+      return s > 0 ? absrnz_equal1(x): 0;
+    }
     case t_INTMOD: case t_POLMOD:
       return gequal1(gel(x,2));
 
@@ -430,8 +430,11 @@ gequalm1(GEN x)
       return equalim1(x);
 
     case t_REAL:
-      return signe(x) < 0 ? absrnz_equal1(x): 0;
-
+    {
+      long s = signe(x);
+      if (!s) return expo(x) >= 0;
+      return s < 0 ? absrnz_equal1(x): 0;
+    }
     case t_INTMOD:
       av=avma; y=equalii(addsi(1,gel(x,2)), gel(x,1)); avma=av; return y;
 
@@ -575,6 +578,13 @@ gcmp(GEN x, GEN y)
       case t_REAL: return cmprr(x, y);
       case t_FRAC: return cmpfrac(x, y);
       case t_STR:  return cmp_str(GSTR(x), GSTR(y));
+      case t_INFINITY:
+      {
+        long sx = inf_get_sign(x), sy = inf_get_sign(y);
+        if (sx < sy) return -1;
+        if (sx > sy) return 1;
+        return 0;
+      }
     }
   switch(tx)
   {
@@ -583,7 +593,7 @@ gcmp(GEN x, GEN y)
       {
         case t_REAL: return cmpir(x, y);
         case t_FRAC: return cmpifrac(x, y);
-        case t_STR:  return -1;
+        case t_INFINITY: return inf_get_sign(y) == 1? -1: 1;
       }
       break;
     case t_REAL:
@@ -591,7 +601,7 @@ gcmp(GEN x, GEN y)
       {
         case t_INT:  return cmpri(x, y);
         case t_FRAC: return cmprfrac(x, y);
-        case t_STR:  return -1;
+        case t_INFINITY: return inf_get_sign(y) == 1? -1: 1;
       }
       break;
     case t_FRAC:
@@ -599,10 +609,10 @@ gcmp(GEN x, GEN y)
       {
         case t_INT:  return -cmpifrac(y, x);
         case t_REAL: return -cmprfrac(y, x);
-        case t_STR:  return -1;
+        case t_INFINITY: return inf_get_sign(y) == 1? -1: 1;
       }
       break;
-    case t_STR: return 1;
+    case t_INFINITY: return inf_get_sign(x) == 1? 1: -1;
   }
   pari_err_TYPE2("comparison",x,y);
   return 0;/*not reached*/
@@ -887,6 +897,7 @@ gidentical(GEN x, GEN y)
       if (!x) return y? 0: 1;
       if (!y) return 0;
       return vecidentical(x, y);
+    case t_INFINITY: return gidentical(gel(x,1),gel(y,1));
   }
   return 0;
 }
@@ -1002,6 +1013,8 @@ gequal(GEN x, GEN y)
         return gequal(x, y);
       case t_CLOSURE:
         return closure_identical(x,y);
+      case t_INFINITY:
+        return gequal(gel(x,1),gel(y,1));
     }
   (void)&av; /* emulate volatile */
   av = avma; i = gequal_try(x, y);
@@ -1069,7 +1082,7 @@ long
 gvaluation(GEN x, GEN p)
 {
   long tx = typ(x), tp = typ(p);
-  pari_sp av, limit;
+  pari_sp av;
 
   switch(tp)
   {
@@ -1140,12 +1153,12 @@ gvaluation(GEN x, GEN p)
         {
           long val;
           if (RgX_is_monomial(p)) return RgX_val(x) / degpol(p);
-          av = avma; limit=stack_lim(av,1);
+          av = avma;
           for (val=0; ; val++)
           {
             x = RgX_divrem(x,p,ONLY_DIVIDES);
             if (!x) { avma = av; return val; }
-            if (low_stack(limit, stack_lim(av,1)))
+            if (gc_needed(av,1))
             {
               if(DEBUGMEM>1) pari_warn(warnmem,"gvaluation");
               x = gerepilecopy(av, x);
@@ -1180,6 +1193,12 @@ gvaluation(GEN x, GEN p)
   pari_err_OP("valuation", x,p);
   return 0; /* not reached */
 }
+GEN
+gpvaluation(GEN x, GEN p)
+{
+  long v = gvaluation(x,p);
+  return v == LONG_MAX? mkoo(): stoi(v);
+}
 
 /* x is non-zero */
 long
@@ -1232,14 +1251,14 @@ long
 z_pval(long s, GEN p)
 {
   if (lgefint(p) > 3) return 0;
-  return z_lval(s, (ulong)p[2]);
+  return z_lval(s, uel(p,2));
 }
 /* assume |p| > 1 */
 long
 z_pvalrem(long s, GEN p, long *py)
 {
   if (lgefint(p) > 3) { *py = s; return 0; }
-  return z_lvalrem(s, (ulong)p[2], py);
+  return z_lvalrem(s, uel(p,2), py);
 }
 
 /* return v_q(x) and set *py = x / q^v_q(x), using divide & conquer */
@@ -1266,7 +1285,7 @@ Z_lval(GEN x, ulong p)
   long vx;
   pari_sp av;
   if (p == 2) return vali(x);
-  if (lgefint(x) == 3) return u_lval((ulong)x[2], p);
+  if (lgefint(x) == 3) return u_lval(uel(x,2), p);
   av = avma;
   for(vx = 0;;)
   {
@@ -1291,7 +1310,7 @@ Z_lvalrem(GEN x, ulong p, GEN *py)
   if (p == 2) { vx = vali(x); *py = shifti(x, -vx); return vx; }
   if (lgefint(x) == 3) {
     ulong u;
-    vx = u_lvalrem((ulong)x[2], p, &u);
+    vx = u_lvalrem(uel(x,2), p, &u);
     *py = signe(x) < 0? utoineg(u): utoipos(u);
     return vx;
   }
@@ -1317,7 +1336,7 @@ Z_lvalrem(GEN x, ulong p, GEN *py)
 static int
 isless_iu(GEN q, ulong p) {
   long l = lgefint(q);
-  return l==2 || (l == 3 && (ulong)q[2] <= p);
+  return l==2 || (l == 3 && uel(q,2) <= p);
 }
 
 long
@@ -1375,7 +1394,7 @@ Z_pvalrem(GEN x, GEN p, GEN *py)
   long vx;
   pari_sp av;
 
-  if (lgefint(p) == 3) return Z_lvalrem(x, (ulong)p[2], py);
+  if (lgefint(p) == 3) return Z_lvalrem(x, uel(p,2), py);
   if (lgefint(x) == 3) { *py = icopy(x); return 0; }
   av = avma; vx = 0; (void)new_chunk(lgefint(x));
   for(;;)
@@ -1388,13 +1407,13 @@ Z_pvalrem(GEN x, GEN p, GEN *py)
 long
 u_pvalrem(ulong x, GEN p, ulong *py)
 {
-  if (lgefint(p) == 3) return u_lvalrem(x, (ulong)p[2], py);
+  if (lgefint(p) == 3) return u_lvalrem(x, uel(p,2), py);
   *py = x; return 0;
 }
 long
 u_pval(ulong x, GEN p)
 {
-  if (lgefint(p) == 3) return u_lval(x, (ulong)p[2]);
+  if (lgefint(p) == 3) return u_lval(x, uel(p,2));
   return 0;
 }
 long
@@ -1402,7 +1421,7 @@ Z_pval(GEN x, GEN p) {
   long vx;
   pari_sp av;
 
-  if (lgefint(p) == 3) return Z_lval(x, (ulong)p[2]);
+  if (lgefint(p) == 3) return Z_lval(x, uel(p,2));
   if (lgefint(x) == 3) return 0;
   av = avma; vx = 0;
   for(;;)
@@ -1718,6 +1737,7 @@ gneg(GEN x)
     case t_VEC: return RgV_neg(x);
     case t_COL: return RgC_neg(x);
     case t_MAT: return RgM_neg(x);
+    case t_INFINITY: return inf_get_sign(x) == 1? mkmoo(): mkoo();
     default:
       pari_err_TYPE("gneg",x);
       return NULL; /* not reached */
@@ -2451,7 +2471,18 @@ normalize(GEN x)
   GEN y, z;
 
   if (typ(x) != t_SER) pari_err_TYPE("normalize",x);
-  if (lx==2) { setsigne(x,0); return x; }
+  if (lx == 2) { setsigne(x,0); return x; }
+  if (lx == 3) {
+    z = gel(x,2);
+    if (!gcmp0(z)) { setsigne(x,1); return x; }
+    if (isrationalzero(z)) return zeroser(vx,vp+1);
+    if (isexactzero(z)) {
+      /* dangerous case: already normalized ? */
+      if (!signe(x)) return x;
+      setvalp(x,vp+1); /* no: normalize */
+    }
+    setsigne(x,0); return x;
+  }
   for (i=2; i<lx; i++)
     if (! isrationalzero(gel(x,i))) break;
   if (i == lx) return zeroser(vx,lx-2+vp);
@@ -2532,6 +2563,7 @@ gsigne(GEN x)
   {
     case t_INT: case t_REAL: return signe(x);
     case t_FRAC: return signe(gel(x,1));
+    case t_INFINITY: return inf_get_sign(x);
   }
   pari_err_TYPE("gsigne",x);
   return 0; /* not reached */
diff --git a/src/basemath/gen3.c b/src/basemath/gen3.c
index d4f66b1..a0c803e 100644
--- a/src/basemath/gen3.c
+++ b/src/basemath/gen3.c
@@ -25,6 +25,40 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 /**                 PRINCIPAL VARIABLE NUMBER                      **/
 /**                                                                **/
 /********************************************************************/
+static void
+recvar(hashtable *h, GEN x)
+{
+  long i = 1, lx = lg(x);
+  void *v;
+  switch(typ(x))
+  {
+    case t_POL: case t_SER:
+      v = (void*)varn(x);
+      if (!hash_search(h, v)) hash_insert(h, v, NULL);
+      i = 2; break;
+    case t_POLMOD: case t_RFRAC:
+    case t_VEC: case t_COL: case t_MAT: break;
+    case t_LIST:
+      x = list_data(x);
+      lx = x? lg(x): 1; break;
+    default:
+      return;
+  }
+  for (; i < lx; i++) recvar(h, gel(x,i));
+}
+
+GEN
+variables_vecsmall(GEN x)
+{
+  hashtable *h = hash_create_ulong(100, 1);
+  recvar(h, x);
+  return vars_sort_inplace(hash_keys(h));
+}
+
+GEN
+variables_vec(GEN x)
+{ return x? vars_to_RgXV(variables_vecsmall(x)): gpolvar(NULL); }
+
 long
 gvar(GEN x)
 {
@@ -313,6 +347,12 @@ poldegree(GEN x, long v)
   pari_err_TYPE("degree",x);
   return 0; /* not reached  */
 }
+GEN
+gppoldegree(GEN x, long v)
+{
+  long d = poldegree(x,v);
+  return d == -LONG_MAX? mkmoo(): stoi(d);
+}
 
 /* assume v >= 0 and x is a POLYNOMIAL in v, return deg_v(x) */
 long
@@ -356,9 +396,8 @@ degree(GEN x)
 GEN
 pollead(GEN x, long v)
 {
-  long l, tx = typ(x), w;
+  long tx = typ(x), w;
   pari_sp av;
-  GEN xinit;
 
   if (is_scalar_t(tx)) return gcopy(x);
   w = varn(x);
@@ -367,33 +406,25 @@ pollead(GEN x, long v)
     case t_POL:
       if (v < 0 || v == w)
       {
-        l=lg(x);
+        long l = lg(x);
         return (l==2)? gen_0: gcopy(gel(x,l-1));
       }
       break;
 
     case t_SER:
       if (v < 0 || v == w) return signe(x)? gcopy(gel(x,2)): gen_0;
+      if (varncmp(v, w) > 0) x = polcoeff_i(x, valp(x), v);
       break;
 
     default:
       pari_err_TYPE("pollead",x);
       return NULL; /* not reached */
   }
-  if (v < w) return gcopy(x);
-  av = avma; xinit = x;
-  x = gsubst(gsubst(x,w,pol_x(MAXVARN)),v,pol_x(0));
-  if (gvar(x)) { avma = av; return gcopy(xinit);}
-  tx = typ(x);
-  if (tx == t_POL) {
-    l = lg(x); if (l == 2) { avma = av; return gen_0; }
-    x = gel(x,l-1);
-  }
-  else if (tx == t_SER) {
-    if (!signe(x)) { avma = av; return gen_0;}
-    x = gel(x,2);
-  } else pari_err_TYPE("pollead",x);
-  return gerepileupto(av, gsubst(x,MAXVARN,pol_x(w)));
+  if (varncmp(v, w) < 0) return gcopy(x);
+  av = avma; w = fetch_var_higher();
+  x = gsubst(x, v, pol_x(w));
+  x = pollead(x, w);
+  delete_var(); return gerepileupto(av, x);
 }
 
 /* returns 1 if there's a real component in the structure, 0 otherwise */
@@ -968,7 +999,7 @@ gdivround(GEN x, GEN y)
     int fl;
     q = quotrem(x,y,&r);
     av1 = avma;
-    fl = gcmp(gmul2n(Q_abs(r),1), Q_abs(y));
+    fl = gcmp(gmul2n(Q_abs_shallow(r),1), Q_abs_shallow(y));
     avma = av1; cgiv(r);
     if (fl >= 0) /* If 2*|r| >= |y| */
     {
@@ -1050,6 +1081,16 @@ ser2pol_i(GEN x, long lx)
   return y;
 }
 
+GEN
+inv_ser(GEN b)
+{
+  pari_sp av = avma;
+  long l = lg(b), e = valp(b), v = varn(b), prec = l-2;
+  GEN y = RgXn_inv(ser2pol_i(b, l), prec);
+  GEN x = poltoser(y, v, prec);
+  setvalp(x, -e); return gerepilecopy(av, x);
+}
+
 /* T t_POL in var v, mod out by T components of x which are
  * t_POL/t_RFRAC in v. Recursively */
 static GEN
@@ -1069,7 +1110,7 @@ mod_r(GEN x, long v, GEN T)
     case t_SER:
       w = varn(x);
       if (w == v) break; /* fail */
-      if (varncmp(v, w) < 0) return x;
+      if (varncmp(v, w) < 0 || ser_isexactzero(x)) return x;
       y = cgetg_copy(x, &lx); y[1] = x[1];
       for (i = 2; i < lx; i++) gel(y,i) = mod_r(gel(x,i),v,T);
       return normalize(y);
@@ -1257,7 +1298,7 @@ gsubst(GEN x, long v, GEN y)
 {
   long tx = typ(x), ty = typ(y), lx = lg(x), ly = lg(y);
   long l, vx, vy, ex, ey, i, j, k, jb;
-  pari_sp av, av2, lim;
+  pari_sp av, av2;
   GEN X, t, p1, p2, modp1, z;
 
   switch(ty)
@@ -1324,12 +1365,12 @@ gsubst(GEN x, long v, GEN y)
       {
         if (lx == 2) return (ty==t_MAT)? scalarmat(x,ly-1): gcopy(x);
         av = avma; X = pol_x(vx);
-        av2 = avma; lim = stack_lim(av2,1);
+        av2 = avma;
         z = gadd(gsubst(gel(x,lx-1),v,y), zeroser(vx,1));
         for (i = lx-2; i>=2; i--)
         {
           z = gadd(gmul(z,X), gsubst(gel(x,i),v,y));
-          if (low_stack(lim, stack_lim(av2,1)))
+          if (gc_needed(av2,1))
           {
             if(DEBUGMEM>1) pari_warn(warnmem,"gsubst (i = %ld)", i);
             z = gerepileupto(av2, z);
@@ -1345,12 +1386,12 @@ gsubst(GEN x, long v, GEN y)
           if (ey < 1 || lx == 2) return zeroser(vy, ey*(ex+lx-2));
           if (vy != vx)
           {
-            av = avma; lim = stack_lim(av,1); z = gel(x,lx-1);
+            av = avma; z = gel(x,lx-1);
 
             for (i=lx-2; i>=2; i--)
             {
               z = gadd(gmul(y,z), gel(x,i));
-              if (low_stack(lim, stack_lim(av,1)))
+              if (gc_needed(av,1))
               {
                 if(DEBUGMEM>1) pari_warn(warnmem,"gsubst (i = %ld)", i);
                 z = gerepileupto(av, z);
@@ -1369,7 +1410,7 @@ gsubst(GEN x, long v, GEN y)
             l2 = (i-2)*ey + (gequal0(y)? 2 : ly);
             if (l > l2) l = l2;
           }
-          av = avma; lim=stack_lim(av,1);
+          av = avma;
           t = leafcopy(y);
           if (l < ly) setlg(t, l);
           z = scalarser(gel(x,2),varn(y),l-2);
@@ -1386,7 +1427,7 @@ gsubst(GEN x, long v, GEN y)
                 p1 = gadd(p1, gmul(gel(t,j-k+2),gel(y,k)));
               gel(t,j) = gadd(p1, gmul(gel(t,2),gel(y,j)));
             }
-            if (low_stack(lim, stack_lim(av,1)))
+            if (gc_needed(av,1))
             {
               if(DEBUGMEM>1) pari_warn(warnmem,"gsubst");
               gerepileall(av,2, &z,&t);
@@ -1407,7 +1448,7 @@ gsubst(GEN x, long v, GEN y)
           y = (ty == t_RFRAC)? rfractoser(y, vy, n): poltoser(y, vy, n);
           x = ser2pol_i(x, lx);
           x = primitive_part(x, &cx);
-          z = RgX_modXn_eval(x, ser2rfrac_i(y), n);
+          z = RgXn_eval(x, ser2rfrac_i(y), n);
           z = RgX_to_ser(z, n+2);
           if (cx) z = gmul(z, cx);
           if (!ex && !cx) return gerepilecopy(av, z);
@@ -1501,7 +1542,7 @@ GEN
 serreverse(GEN x)
 {
   long v=varn(x), lx = lg(x), i, mi;
-  pari_sp av0 = avma, av, lim;
+  pari_sp av0 = avma, av;
   GEN a, y, u;
 
   if (typ(x)!=t_SER) pari_err_TYPE("serreverse",x);
@@ -1509,7 +1550,7 @@ serreverse(GEN x)
   if (lx < 3) pari_err_DOMAIN("serreverse", "x", "=", gen_0,x);
   y = ser_normalize(x);
   if (y == x) a = NULL; else { a = gel(x,2); x = y; }
-  av = avma; lim = stack_lim(av, 2);
+  av = avma;
   mi = lx-1; while (mi>=3 && gequal0(gel(x,mi))) mi--;
   u = cgetg(lx,t_SER);
   y = cgetg(lx,t_SER);
@@ -1543,7 +1584,7 @@ serreverse(GEN x)
     i++;
     gel(u,i) = gerepileupto(av2, gneg(p1));
     gel(y,i) = gdivgs(gel(u,i), i-1);
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       GEN dummy = cgetg(1,t_VEC);
       if(DEBUGMEM>1) pari_warn(warnmem,"serreverse");
@@ -1565,15 +1606,20 @@ derivser(GEN x)
 {
   long i, vx = varn(x), e = valp(x), lx = lg(x);
   GEN y;
-  if (lx == 2) return zeroser(vx,e? e-1: 0);
+  if (ser_isexactzero(x))
+  {
+    x = gcopy(x);
+    if (e) setvalp(x,e-1);
+    return x;
+  }
   if (e)
   {
-    y = cgetg(lx,t_SER); y[1] = evalvalp(e-1) | evalvarn(vx);
+    y = cgetg(lx,t_SER); y[1] = evalsigne(1)|evalvalp(e-1) | evalvarn(vx);
     for (i=2; i<lx; i++) gel(y,i) = gmulsg(i+e-2,gel(x,i));
   } else {
     if (lx == 3) return zeroser(vx, 0);
     lx--;
-    y = cgetg(lx,t_SER); y[1] = _evalvalp(0) | evalvarn(vx);
+    y = cgetg(lx,t_SER); y[1] = evalsigne(1)|_evalvalp(0) | evalvarn(vx);
     for (i=2; i<lx; i++) gel(y,i) = gmulsg(i-1,gel(x,i+1));
   }
   return normalize(y);
@@ -1582,7 +1628,7 @@ derivser(GEN x)
 GEN
 deriv(GEN x, long v)
 {
-  long lx, vx, tx, i, j;
+  long lx, tx, i, j;
   pari_sp av;
   GEN y;
 
@@ -1604,17 +1650,22 @@ deriv(GEN x, long v)
       retmkpolmod(deriv(a,v), RgX_copy(b));
     }
     case t_POL:
-      vx = varn(x);
-      if (varncmp(vx, v) > 0) return RgX_get_0(x);
-      if (varncmp(vx, v) == 0) return RgX_deriv(x);
+      switch(varncmp(varn(x), v))
+      {
+        case 1: return RgX_get_0(x);
+        case 0: return RgX_deriv(x);
+      }
       y = cgetg_copy(x, &lx); y[1] = x[1];
       for (i=2; i<lx; i++) gel(y,i) = deriv(gel(x,i),v);
       return normalizepol_lg(y,i);
 
     case t_SER:
-      vx = varn(x);
-      if (varncmp(vx, v) > 0) return RgX_get_0(x);
-      if (varncmp(vx, v) == 0) return derivser(x);
+      switch(varncmp(varn(x), v))
+      {
+        case 1: return RgX_get_0(x);
+        case 0: return derivser(x);
+      }
+      if (ser_isexactzero(x)) return gcopy(x);
       y = cgetg_copy(x, &lx); y[1] = x[1];
       for (j=2; j<lx; j++) gel(y,j) = deriv(gel(x,j),v);
       return normalize(y);
@@ -1704,10 +1755,14 @@ diffop(GEN x, GEN v, GEN dv)
       vx  = varn(x); idx = lookup(v,vx);
       if (!idx) return gen_0;
       av = avma;
-      y = cgetg_copy(x, &lx); y[1] = x[1];
-      for (i=2; i<lx; i++) gel(y,i) = diffop(gel(x,i),v,dv);
-      y = normalize(y); /* y is probably invalid */
-      y = gsubst(y, vx, pol_x(vx)); /* Fix that */
+      if (ser_isexactzero(x)) y = x;
+      else
+      {
+        y = cgetg_copy(x, &lx); y[1] = x[1];
+        for (i=2; i<lx; i++) gel(y,i) = diffop(gel(x,i),v,dv);
+        y = normalize(y); /* y is probably invalid */
+        y = gsubst(y, vx, pol_x(vx)); /* Fix that */
+      }
       y = gadd(y, gmul(gel(dv,idx),derivser(x)));
       return gerepileupto(av, y);
 
@@ -1749,20 +1804,10 @@ diffop0(GEN x, GEN v, GEN dv, long n)
 static GEN
 swapvar_act(GEN x, long vx, long v, GEN (*act)(void*, long, GEN), void *data)
 {
-  GEN y;
-  if (v != MAXVARN) { /* (vx,v) -> (MAXVARN, v) */
-    y = act(data, v, gsubst(x,vx,pol_x(MAXVARN)));
-    y = gsubst(y,MAXVARN,pol_x(vx));
-  } else if (vx != 0) { /* (vx,v) -> (vx, 0) */
-    y = act(data, 0, gsubst(x,v,pol_x(0)));
-    y = gsubst(y,0,pol_x(v));
-  } else { /* (0,MAXVARN) -> (w, 0) */
-    long w = fetch_var();
-    y = act(data, 0, gsubst(gsubst(x,0,pol_x(w)), MAXVARN,pol_x(0)));
-    y = gsubst(gsubst(y,0,pol_x(MAXVARN)), w,pol_x(0));
-    (void)delete_var();
-  }
-  return y;
+  long v0 = fetch_var();
+  GEN y = act(data, v, gsubst(x,vx,pol_x(v0)));
+  y = gsubst(y,v0,pol_x(vx));
+  (void)delete_var(); return y;
 }
 /* x + O(v^data) */
 static GEN
@@ -2019,37 +2064,63 @@ round0(GEN x, GEN *pte)
   return ground(x);
 }
 
+/* x t_REAL, return q=floor(x+1/2), set e = expo(x-q) */
+static GEN
+round_i(GEN x, long *pe)
+{
+  long e;
+  GEN B, q,r, m = mantissa_real(x, &e); /* x = m/2^e */
+  if (e <= 0)
+  {
+    if (e) m = shifti(m,-e);
+    *pe = -e; return m;
+  }
+  B = int2n(e-1);
+  m = addii(m, B);
+  q = shifti(m, -e);
+  r = remi2n(m, e);
+  /* 2^e (x+1/2) = m = 2^e q + r, sgn(r)=sgn(m), |r|<2^e */
+  if (!signe(r))
+    *pe = -1;
+  else
+  {
+    if (signe(m) < 0)
+    {
+      q = subiu(q,1);
+      r = addii(r, B);
+    }
+    else
+      r = subii(r, B);
+    /* |x - q| = |r| / 2^e */
+    *pe = signe(r)? expi(r) - e: -e;
+    cgiv(r);
+  }
+  return q;
+}
 /* assume x a t_REAL */
 GEN
 roundr(GEN x)
 {
   long ex, s = signe(x);
   pari_sp av;
-  GEN t;
   if (!s || (ex=expo(x)) < -1) return gen_0;
   if (ex == -1) return s>0? gen_1:
                             absrnz_equal2n(x)? gen_0: gen_m1;
-  av = avma;
-  t = addrr(real2n(-1, nbits2prec(ex+1)), x); /* x + 0.5 */
-  return gerepileuptoint(av, floorr(t));
+  av = avma; x = round_i(x, &ex);
+  if (ex >= 0) pari_err_PREC( "roundr (precision loss in truncation)");
+  return gerepileuptoint(av, x);
 }
 GEN
 roundr_safe(GEN x)
 {
-  long e1, ex, s = signe(x);
+  long ex, s = signe(x);
   pari_sp av;
-  GEN t, y;
 
   if (!s || (ex = expo(x)) < -1) return gen_0;
   if (ex == -1) return s>0? gen_1:
                             absrnz_equal2n(x)? gen_0: gen_m1;
-  av = avma;
-  t = addrr(real2n(-1,nbits2prec(ex+1)), x); /* x + 0.5 */
-
-  e1 = expo(t) - bit_prec(t) + 1;
-  y = mantissa2nr(t, e1);
-  if (signe(x) < 0) y = addsi(-1,y);
-  return gerepileuptoint(av,y);
+  av = avma; x = round_i(x, &ex);
+  return gerepileuptoint(av, x);
 }
 
 GEN
@@ -2080,6 +2151,7 @@ ground(GEN x)
       for (i=2; i<lx; i++) gel(y,i) = ground(gel(x,i));
       return normalizepol_lg(y, lx);
     case t_SER:
+      if (ser_isexactzero(x)) return gcopy(x);
       y = cgetg_copy(x, &lx); y[1] = x[1];
       for (i=2; i<lx; i++) gel(y,i) = ground(gel(x,i));
       return normalize(y);
@@ -2109,23 +2181,9 @@ grndtoi(GEN x, long *e)
     case t_INT: return icopy(x);
     case t_REAL: {
       long ex = expo(x);
-      GEN t;
       if (!signe(x) || ex < -1) { *e = ex; return gen_0; }
-      av = avma;
-      /* ex+2 since we may have ex = -1 */
-      t = addrr(real2n(-1,nbits2prec(ex+2)), x); e1 = expo(t);
-      if (e1 < 0)
-      {
-        if (signe(t) >= 0) { *e = ex; avma = av; return gen_0; }
-        *e = expo(addsr(1,x)); avma = av; return gen_m1;
-      }
-      e1 = e1 - bit_prec(t) + 1;
-      y = mantissa2nr(t, e1);
-      if (signe(x) < 0) y = addsi(-1,y);
-      y = gerepileuptoint(av,y);
-
-      if (e1 <= 0) { av = avma; e1 = expo(subri(x,y)); avma = av; }
-      *e = e1; return y;
+      av = avma; x = round_i(x, e);
+      return gerepileuptoint(av, x);
     }
     case t_FRAC: return diviiround(gel(x,1), gel(x,2));
     case t_INTMOD: case t_QUAD: return gcopy(x);
@@ -2154,6 +2212,7 @@ grndtoi(GEN x, long *e)
       }
       return normalizepol_lg(y, lx);
     case t_SER:
+      if (ser_isexactzero(x)) return gcopy(x);
       y = cgetg_copy(x, &lx); y[1] = x[1];
       for (i=2; i<lx; i++)
       {
@@ -2442,11 +2501,11 @@ mkintn(long n, ...)
   for (i=0; i <n; i++)
   {
 #ifdef LONG_IS_64BIT
-    ulong a = (e && !i)? 0: va_arg(ap, long);
-    ulong b = va_arg(ap, long);
+    ulong a = (e && !i)? 0: (ulong) va_arg(ap, unsigned int);
+    ulong b = (ulong) va_arg(ap, unsigned int);
     *y = (a << 32) | b;
 #else
-    *y = va_arg(ap, long);
+    *y = (ulong) va_arg(ap, unsigned int);
 #endif
     y = int_precW(y);
   }
@@ -2512,7 +2571,7 @@ mkvecsmalln(long n, ...)
   long i;
   va_start(ap,n);
   x = cgetg(n+1, t_VECSMALL);
-  for (i=1; i <= n; i++) gel(x,i) = va_arg(ap, GEN);
+  for (i=1; i <= n; i++) x[i] = va_arg(ap, long);
   va_end(ap); return x;
 }
 
@@ -2616,15 +2675,22 @@ gtopolyrev(GEN x, long v) { return _gtopoly(x,v,1); }
 GEN
 gtopoly(GEN x, long v) { return _gtopoly(x,v,0); }
 
+/* assume prec >= 0 */
 GEN
 scalarser(GEN x, long v, long prec)
 {
   long i, l;
   GEN y;
 
-  if (isrationalzero(x)) return zeroser(v, prec);
+  if (gequal0(x))
+  {
+    if (isrationalzero(x)) return zeroser(v, prec);
+    y = cgetg(3, t_SER);
+    y[1] = evalsigne(0) | _evalvalp(prec) | evalvarn(v);
+    gel(y,2) = gcopy(x); return y;
+  }
   l = prec + 2; y = cgetg(l, t_SER);
-  y[1] = evalsigne(gequal0(x)? 0: 1) | _evalvalp(0) | evalvarn(v);
+  y[1] = evalsigne(1) | _evalvalp(0) | evalvarn(v);
   gel(y,2) = gcopy(x); for (i=3; i<l; i++) gel(y,i) = gen_0;
   return y;
 }
@@ -2684,6 +2750,8 @@ gtoser(GEN x, long v, long prec)
   GEN y;
 
   if (v < 0) v = 0;
+  if (prec < 0)
+    pari_err_DOMAIN("gtoser", "precision", "<", gen_0, stoi(prec));
   if (tx == t_SER)
   {
     long vx = varn(x);
@@ -2867,8 +2935,7 @@ GEN
 gtovecrev0(GEN x, long n)
 {
   GEN y = gtovec0(x, n);
-  long ly = lg(y), lim = ly>>1, i;
-  for (i = 1; i <= lim; i++) swap(gel(y,i), gel(y,ly-i));
+  vecreverse_inplace(y);
   return y;
 }
 GEN
@@ -3103,7 +3170,7 @@ _polcoeff(GEN x, long n, long v)
 static GEN
 _sercoeff(GEN x, long n, long v)
 {
-  long w, dx = degpol(x), ex = valp(x), N = n - ex;
+  long w, dx = lg(x)-3, ex = valp(x), N = n - ex;
   GEN z;
   if (dx < 0)
   {
@@ -3129,7 +3196,7 @@ _rfraccoeff(GEN x, long n, long v)
 {
   GEN P,Q, p = gel(x,1), q = gel(x,2);
   long vp = gvar(p), vq = gvar(q);
-  if (v < 0) v = minss(vp, vq);
+  if (v < 0) v = varncmp(vp, vq) < 0? vp: vq;
   P = (vp == v)? p: swap_vars(p, v);
   Q = (vq == v)? q: swap_vars(q, v);
   if (!RgX_is_monomial(Q)) pari_err_TYPE("polcoeff", x);
@@ -3268,6 +3335,11 @@ lift0(GEN x, long v)
       for (i=2; i<lx; i++) gel(y,i) = lift0(gel(x,i), v);
       return normalizepol_lg(y,lx);
     case t_SER:
+      if (ser_isexactzero(x))
+      {
+        if (lg(x) == 2) return gcopy(x);
+        return scalarser(lift0(gel(x,2),v), varn(x), valp(x));
+      }
       y = cgetg_copy(x, &lx); y[1] = x[1];
       for (i=2; i<lx; i++) gel(y,i) = lift0(gel(x,i), v);
       return normalize(y);
@@ -3299,6 +3371,11 @@ liftall_shallow(GEN x)
       for (i=2; i<lx; i++) gel(y,i) = liftall_shallow(gel(x,i));
       return normalizepol_lg(y,lx);
     case t_SER:
+      if (ser_isexactzero(x))
+      {
+        if (lg(x) == 2) return x;
+        return scalarser(liftall_shallow(gel(x,2)), varn(x), valp(x));
+      }
       y = cgetg_copy(x, &lx); y[1] = x[1];
       for (i=2; i<lx; i++) gel(y,i) = liftall_shallow(gel(x,i));
       return normalize(y);
@@ -3312,9 +3389,7 @@ liftall_shallow(GEN x)
 }
 GEN
 liftall(GEN x)
-{ pari_sp av = avma;
-  GEN z = liftall_shallow(x);
-  return z==x ? gcopy(z): gerepilecopy(av, z); }
+{ pari_sp av = avma; return gerepilecopy(av, liftall_shallow(x)); }
 
 GEN
 liftint_shallow(GEN x)
@@ -3331,6 +3406,11 @@ liftint_shallow(GEN x)
       for (i=2; i<lx; i++) gel(y,i) = liftint_shallow(gel(x,i));
       return normalizepol_lg(y,lx);
     case t_SER:
+      if (ser_isexactzero(x))
+      {
+        if (lg(x) == 2) return x;
+        return scalarser(liftint_shallow(gel(x,2)), varn(x), valp(x));
+      }
       y = cgetg_copy(x, &lx); y[1] = x[1];
       for (i=2; i<lx; i++) gel(y,i) = liftint_shallow(gel(x,i));
       return normalize(y);
@@ -3344,9 +3424,7 @@ liftint_shallow(GEN x)
 }
 GEN
 liftint(GEN x)
-{ pari_sp av = avma;
-  GEN z = liftint_shallow(x);
-  return z==x ? gcopy(z): gerepilecopy(av, z); }
+{ pari_sp av = avma; return gerepilecopy(av, liftint_shallow(x)); }
 
 GEN
 liftpol_shallow(GEN x)
@@ -3363,6 +3441,11 @@ liftpol_shallow(GEN x)
       for (i=2; i<lx; i++) gel(y,i) = liftpol_shallow(gel(x,i));
       return normalizepol_lg(y,lx);
     case t_SER:
+      if (ser_isexactzero(x))
+      {
+        if (lg(x) == 2) return x;
+        return scalarser(liftpol_shallow(gel(x,2)), varn(x), valp(x));
+      }
       y = cgetg_copy(x, &lx); y[1] = x[1];
       for (i=2; i<lx; i++) gel(y,i) = liftpol_shallow(gel(x,i));
       return normalize(y);
@@ -3375,9 +3458,7 @@ liftpol_shallow(GEN x)
 }
 GEN
 liftpol(GEN x)
-{ pari_sp av = avma;
-  GEN z = liftpol_shallow(x);
-  return z==x ? gcopy(z): gerepilecopy(av, z); }
+{ pari_sp av = avma; return gerepilecopy(av, liftpol_shallow(x)); }
 
 /* same as lift, without copy. May DESTROY x. For internal use only */
 GEN
@@ -3389,6 +3470,11 @@ lift_intern(GEN x)
     case t_INTMOD: case t_POLMOD: return gel(x,2);
     case t_PADIC: return padic_to_Q(x);
     case t_SER:
+      if (ser_isexactzero(x))
+      {
+        if (lg(x) == 2) return x;
+        return scalarser(lift_intern(gel(x,2)), varn(x), valp(x));
+      }
       for (i = lg(x)-1; i>=2; i--) gel(x,i) = lift_intern(gel(x,i));
       return normalize(x);
     case t_POL:
@@ -3429,6 +3515,7 @@ centerlift(GEN x)
       for (i=2; i<lx; i++) gel(y,i) = centerlift(gel(x,i));
       return normalizepol_lg(y,lx);
    case t_SER:
+      if (ser_isexactzero(x)) return lift(x);
       y = cgetg_copy(x, &lx); y[1] = x[1];
       for (i=2; i<lx; i++) gel(y,i) = centerlift(gel(x,i));
       return normalize(y);
@@ -3610,10 +3697,27 @@ RgM_mulreal(GEN x, GEN y)
 /*                                                                 */
 /*******************************************************************/
 static long
+_egal_i(GEN x, GEN y)
+{
+  x = simplify_shallow(x);
+  y = simplify_shallow(y);
+  if (typ(y) == t_INT)
+  {
+    if (equali1(y)) return gequal1(x);
+    if (equalim1(y)) return gequalm1(x);
+  }
+  else if (typ(x) == t_INT)
+  {
+    if (equali1(x)) return gequal1(y);
+    if (equalim1(x)) return gequalm1(y);
+  }
+  return gequal(x, y);
+}
+static long
 _egal(GEN x, GEN y)
 {
   pari_sp av = avma;
-  long r = gequal(simplify_shallow(x), simplify_shallow(y));
+  long r = _egal_i(x, y);
   avma = av; return r;
 }
 
@@ -3684,7 +3788,8 @@ geval_gp(GEN x, GEN t)
       return y;
 
     case t_CLOSURE:
-      if (closure_arity(x)) pari_err_IMPL("eval on functions with parameters");
+      if (closure_arity(x) || closure_is_variadic(x))
+        pari_err_IMPL("eval on functions with parameters");
       return closure_evalres(x);
   }
   pari_err_TYPE("geval",x);
@@ -3704,7 +3809,7 @@ simplify_shallow(GEN x)
   {
     case t_INT: case t_REAL: case t_INTMOD: case t_FRAC: case t_FFELT:
     case t_PADIC: case t_QFR: case t_QFI: case t_LIST: case t_STR: case t_VECSMALL:
-    case t_CLOSURE: case t_ERROR:
+    case t_CLOSURE: case t_ERROR: case t_INFINITY:
       return x;
     case t_COMPLEX: return isintzero(gel(x,2))? gel(x,1): x;
     case t_QUAD:    return isintzero(gel(x,3))? gel(x,2): x;
@@ -3873,7 +3978,7 @@ GEN
 poleval(GEN x, GEN y)
 {
   long i, j, imin, tx = typ(x);
-  pari_sp av0 = avma, av, lim;
+  pari_sp av0 = avma, av;
   GEN p1, p2, r, s;
 
   if (is_scalar_t(tx)) return gcopy(x);
@@ -3895,7 +4000,6 @@ poleval(GEN x, GEN y)
   if (i<=imin)
     return (i==imin)? gcopy(gel(x,imin)): gen_0;
 
-  lim = stack_lim(av0,2);
   p1 = gel(x,i); i--;
   if (typ(y)!=t_COMPLEX)
   {
@@ -3914,7 +4018,7 @@ poleval(GEN x, GEN y)
         }
       r = (i==j)? y: gpowgs(y, i-j+1);
       p1 = gadd(gmul(p1,r), gel(x,j));
-      if (low_stack(lim, stack_lim(av0,2)))
+      if (gc_needed(av0,2))
       {
         if (DEBUGMEM>1) pari_warn(warnmem,"poleval: i = %ld",i);
         p1 = gerepileupto(av0, p1);
@@ -3929,7 +4033,7 @@ poleval(GEN x, GEN y)
   {
     GEN p3 = gadd(p2, gmul(r, p1));
     p2 = gadd(gel(x,i), gmul(s, p1)); p1 = p3;
-    if (low_stack(lim, stack_lim(av0,2)))
+    if (gc_needed(av0,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"poleval: i = %ld",i);
       gerepileall(av, 2, &p1, &p2);
diff --git a/src/basemath/hnf_snf.c b/src/basemath/hnf_snf.c
index 60a5610..4b27e2e 100644
--- a/src/basemath/hnf_snf.c
+++ b/src/basemath/hnf_snf.c
@@ -96,7 +96,7 @@ hnffinal(GEN matgen,GEN perm,GEN* ptdep,GEN* ptB,GEN* ptC)
 {
   GEN p1,p2,U,H,Hnew,Bnew,Cnew,diagH1;
   GEN B = *ptB, C = *ptC, dep = *ptdep, depnew;
-  pari_sp av, lim;
+  pari_sp av;
   long i,j,k,s,i1,j1,zc;
   long co = lg(C);
   long col = lg(matgen)-1;
@@ -116,7 +116,7 @@ hnffinal(GEN matgen,GEN perm,GEN* ptdep,GEN* ptB,GEN* ptC)
 
   diagH1 = new_chunk(lnz+1); /* diagH1[i] = 0 iff H[i,i] != 1 (set later) */
 
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
   Cnew = cgetg(co, typ(C));
   setlg(C, col+1); p1 = gmul(C,U);
   for (j=1; j<=col; j++) gel(Cnew,j) = gel(p1,j);
@@ -138,7 +138,7 @@ hnffinal(GEN matgen,GEN perm,GEN* ptdep,GEN* ptB,GEN* ptC)
       for (   ; k<=lig;  k++) gel(z,k) = subii(gel(z,k), mulii(p1, gel(Hi,k-nlze)));
       gel(Cnew,j) = gsub(gel(Cnew,j), gmul(p1, gel(Cnew,i+zc)));
     }
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,3))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"hnffinal, i = %ld",i);
       gerepileall(av, 2, &Cnew, &B);
@@ -233,7 +233,7 @@ col_dup(long l, GEN col)
 GEN
 hnfspec_i(GEN mat0, GEN perm, GEN* ptdep, GEN* ptB, GEN* ptC, long k0)
 {
-  pari_sp av, lim;
+  pari_sp av;
   long co, n, s, nlze, lnz, nr, i, j, k, lk0, col, lig, *p;
   GEN mat;
   GEN p1, p2, matb, matbnew, vmax, matt, T, extramat, B, C, H, dep, permpro;
@@ -262,7 +262,7 @@ hnfspec_i(GEN mat0, GEN perm, GEN* ptdep, GEN* ptB, GEN* ptC, long k0)
     p1 = cgetg(k0+1,t_COL); gel(matt,j) = p1; gel(mat,j) = matj;
     for (i=1; i<=k0; i++) gel(p1,i) = stoi(matj[perm[i]]);
   }
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
 
   i = lig = li-1; col = co-1; lk0 = k0;
   T = (k0 || (lg(C) > 1 && lgcols(C) > 1))? matid(col): NULL;
@@ -328,7 +328,7 @@ hnfspec_i(GEN mat0, GEN perm, GEN* ptdep, GEN* ptB, GEN* ptC, long k0)
       if (T) ZC_lincomb1_inplace(gel(T,j), gel(T,col), stoi(-t));
     }
     lig--; col--;
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,3))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"hnfspec[1]");
       if (T) T = gerepilecopy(av, T); else avma = av;
@@ -371,7 +371,7 @@ hnfspec_i(GEN mat0, GEN perm, GEN* ptdep, GEN* ptB, GEN* ptC, long k0)
       if (T) ZC_lincomb1_inplace(gel(T,j), gel(T,col), stoi(-t));
     }
     lig--; col--;
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,3))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"hnfspec[2]");
       gerepileall(av, T? 2: 1, &vmax, &T);
@@ -414,7 +414,7 @@ END2: /* clean up mat: remove everything to the right of the 1s on diagonal */
         for (h=1; h<i0; h++) gel(Bj,h) = subii(gel(Bj,h), mulii(v,gel(Bk,h)));
       }
       if (T) ZC_lincomb1_inplace(gel(T,j), gel(T,k), negi(v));
-      if (low_stack(lim, stack_lim(av,1)))
+      if (gc_needed(av,3))
       {
         if(DEBUGMEM>1) pari_warn(warnmem,"hnfspec[3], (i,j) = %ld,%ld", i,j);
         for (h=1; h<co; h++) setlg(matb[h], i0+1); /* bottom can be forgotten */
@@ -628,7 +628,7 @@ hnfadd_i(GEN H, GEN perm, GEN* ptdep, GEN* ptB, GEN* ptC, /* cf hnfspec */
   permpro = ZM_imagecomplspec(extramat, &nlze);
   extramat = rowpermute(extramat, permpro);
   *ptB     = rowpermute(B,        permpro);
-  permpro = vecpermute(perm, permpro);
+  permpro = vecsmallpermute(perm, permpro);
   for (i=1; i<=lig; i++) perm[i] = permpro[i]; /* perm o= permpro */
 
   *ptdep  = rowslice(extramat, 1, nlze);
@@ -812,7 +812,7 @@ ZM_reduce(GEN A, GEN U, long i, long j0)
 }
 
 static GEN
-RgX_normalize(GEN T, GEN *pd)
+RgX_normalize_all(GEN T, GEN *pd)
 {
   GEN d = leading_term(T);
   while (gequal0(d) || ( typ(d) == t_REAL && lg(d) == 3
@@ -831,7 +831,7 @@ RgM_reduce(GEN A, GEN U, long i, long j0, long vx)
   long j, lA = lg(A);
   GEN d, T = gcoeff(A,i,j0);
   if (is_RgX(T,vx)) {
-    T = RgX_normalize(T, &d);
+    T = RgX_normalize_all(T, &d);
     if (degpol(T) == 0) { d = gel(T,2); T = gen_1; }
   } else {
     d = T; T = gen_1;
@@ -922,12 +922,12 @@ remove_0cols(long r, GEN *pA, GEN *pB, long remove)
 static GEN
 hnf_i(GEN A, int remove)
 {
-  pari_sp av0 = avma, av, lim;
+  pari_sp av0 = avma, av;
   long s, n, m, j, k, li, def, ldef;
 
   RgM_dimensions(A, &m, &n);
   if (!n) return cgetg(1,t_MAT);
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
   A = RgM_shallowcopy(A);
   def = n; ldef = (m>n)? m-n: 0;
   for (li=m; li>ldef; li--)
@@ -940,7 +940,7 @@ hnf_i(GEN A, int remove)
       /* zero a = Aij  using  b = Aik */
       k = (j==1)? def: j-1;
       ZC_elem(a,gcoeff(A,li,k), A,NULL, j,k);
-      if (low_stack(lim, stack_lim(av,1)))
+      if (gc_needed(av,1))
       {
         if (DEBUGMEM>1) pari_warn(warnmem,"ZM_hnf[1]. li=%ld",li);
         A = gerepilecopy(av, A);
@@ -955,7 +955,7 @@ hnf_i(GEN A, int remove)
     }
     else
       if (ldef) ldef--;
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"ZM_hnf[2]. li=%ld",li);
       A = gerepilecopy(av, A);
@@ -1000,12 +1000,12 @@ FpV_red_part_ipvec(GEN z, GEN p, long k)
 GEN
 ZpM_echelon(GEN x, long early_abort, GEN p, GEN pm)
 {
-  pari_sp av0 = avma, av, lim;
+  pari_sp av0 = avma, av;
   long m, li, co, i, j, k, def, ldef;
 
   co = lg(x); if (co == 1) return cgetg(1,t_MAT);
   li = lgcols(x);
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
   x = RgM_shallowcopy(x);
   m = Z_pval(pm, p);
 
@@ -1048,7 +1048,7 @@ ZpM_echelon(GEN x, long early_abort, GEN p, GEN pm)
 
       t = diviiexact(a, pvmin); togglesign(t);
       ZC_lincomb1_inplace(gel(x,j), gel(x,def), t);
-      if (low_stack(lim, stack_lim(av,1)))
+      if (gc_needed(av,1))
       {
         if (DEBUGMEM>1) pari_warn(warnmem,"ZpM_echelon. i=%ld",i);
         x = gerepilecopy(av, x); pvmin = gcoeff(x,i,def);
@@ -1133,7 +1133,7 @@ zlm_echelon(GEN x, long early_abort, ulong p, ulong pm)
 GEN
 ZM_hnfmodall_i(GEN x, GEN dm, long flag)
 {
-  pari_sp av, lim;
+  pari_sp av;
   const long center = (flag & hnf_CENTER);
   long moddiag = (flag & hnf_MODID);
   long li, co, i, j, k, def, ldef;
@@ -1161,7 +1161,7 @@ ZM_hnfmodall_i(GEN x, GEN dm, long flag)
       LDM[i] = lgefint(gel(dm,i));
     }
   }
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
   x = RgM_shallowcopy(x);
 
   ldef = 0;
@@ -1194,7 +1194,7 @@ ZM_hnfmodall_i(GEN x, GEN dm, long flag)
         if (lgefint(gel(p2,k)) > LDM[k])
           gel(p2,k) = centermodii(gel(p2,k), gel(dm,k),gel(dm2,k));
       }
-      if (low_stack(lim, stack_lim(av,1)))
+      if (gc_needed(av,1))
       {
         if (DEBUGMEM>1) pari_warn(warnmem,"ZM_hnfmod[1]. i=%ld",i);
         x = gerepilecopy(av, x);
@@ -1236,7 +1236,7 @@ ZM_hnfmodall_i(GEN x, GEN dm, long flag)
         ZC_elem(a, gcoeff(x,j,j), x, NULL, li,j);
         FpV_red_part_ipvec(gel(x,li), dm, j-1);
         FpV_red_part_ipvec(gel(x,j),  dm, j-1);
-        if (low_stack(lim, stack_lim(av,1)))
+        if (gc_needed(av,1))
         {
           if (DEBUGMEM>1) pari_warn(warnmem,"ZM_hnfmod[2]. i=%ld", i);
           x = gerepilecopy(av, x);
@@ -1279,7 +1279,7 @@ ZM_hnfmodall_i(GEN x, GEN dm, long flag)
       p1 = gel(x,j);
       for (k=1; k<i; k++)
         if (lgefint(gel(p1,k)) > LDM[k]) gel(p1,k) = remii(gel(p1,k), gel(dm,i));
-      if (low_stack(lim, stack_lim(av,1)))
+      if (gc_needed(av,1))
       {
         if (DEBUGMEM>1) pari_warn(warnmem,"ZM_hnfmod[3]. i=%ld", i);
         gerepileall(av, 2, &x, &dm); diag = gcoeff(x,i,i);
@@ -1331,7 +1331,7 @@ GEN
 ZM_hnfcenter(GEN M)
 {
   long i, j, k, N = lg(M)-1;
-  pari_sp av = avma, lim = stack_lim(av,1);
+  pari_sp av = avma;
 
   for (j=N-1; j>0; j--) /* skip last line */
   {
@@ -1350,7 +1350,7 @@ ZM_hnfcenter(GEN M)
       }
       else
         for (i = 1; i <= j; i++) gel(Mk,i) = subii(gel(Mk,i), mulii(q,gel(Mj,i)));
-      if (low_stack(lim, stack_lim(av,1)))
+      if (gc_needed(av,1))
       {
         if (DEBUGMEM) pari_warn(warnmem,"ZM_hnfcenter, j = %ld",j);
         M = gerepilecopy(av, M);
@@ -1485,7 +1485,7 @@ reverse_rows(GEN A)
 GEN
 ZM_hnflll(GEN A, GEN *ptB, int remove)
 {
-  pari_sp av = avma, lim = stack_lim(av,3);
+  pari_sp av = avma;
 #ifdef HNFLLL_QUALITY
   const long m1 = 1, n1 = 1; /* alpha = m1/n1. Maybe 3/4 here ? */
 #endif
@@ -1530,7 +1530,7 @@ ZM_hnflll(GEN A, GEN *ptB, int remove)
       {
         long row0, row1;
         reduce2(A,B,k,i,&row0,&row1,lambda,D);
-        if (low_stack(lim, stack_lim(av,3)))
+        if (gc_needed(av,3))
         {
           GEN b = D-1;
           if (DEBUGMEM) pari_warn(warnmem,"hnflll (reducing), kmax = %ld",kmax);
@@ -1540,7 +1540,7 @@ ZM_hnflll(GEN A, GEN *ptB, int remove)
       }
       if (++k > kmax) kmax = k;
     }
-    if (low_stack(lim, stack_lim(av,3)))
+    if (gc_needed(av,3))
     {
       GEN b = D-1;
       if (DEBUGMEM) pari_warn(warnmem,"hnflll, kmax = %ld / %ld",kmax,n-1);
@@ -1652,12 +1652,12 @@ ZV_gcdext_i(GEN A)
   return mkvec2(gel(A,n-1), B);
 }
 GEN
-ZV_gcdext(GEN A)
+ZV_extgcd(GEN A)
 {
   pari_sp av = avma;
   return gerepilecopy(av, ZV_gcdext_i(A));
 }
-/* as ZV_gcdext, transforming the gcd into a t_MAT, for mathnf0 */
+/* as ZV_extgcd, transforming the gcd into a t_MAT, for mathnf0 */
 static GEN
 ZV_hnfgcdext(GEN A)
 {
@@ -1674,7 +1674,7 @@ GEN
 ZM_hnfperm(GEN A, GEN *ptU, GEN *ptperm)
 {
   GEN U, c, l, perm, d, p, q, b;
-  pari_sp av = avma, av1, lim;
+  pari_sp av = avma, av1;
   long r, t, i, j, j1, k, m, n;
 
   n = lg(A)-1;
@@ -1688,7 +1688,7 @@ ZM_hnfperm(GEN A, GEN *ptU, GEN *ptperm)
   c = zero_zv(m);
   l = zero_zv(n);
   perm = cgetg(m+1, t_VECSMALL);
-  av1 = avma; lim = stack_lim(av1,1);
+  av1 = avma;
   A = RgM_shallowcopy(A);
   U = ptU? matid(n): NULL;
   /* U base change matrix : A0*U = A all along */
@@ -1747,7 +1747,7 @@ ZM_hnfperm(GEN A, GEN *ptU, GEN *ptperm)
         if (U) ZC_lincomb1_inplace(gel(U,j), gel(U,k), q);
       }
     }
-    if (low_stack(lim, stack_lim(av1,1)))
+    if (gc_needed(av1,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"hnfperm");
       gerepileall(av1, U? 2: 1, &A, &U);
@@ -1803,7 +1803,7 @@ hnfperm(GEN A)
 GEN
 ZM_hnfall(GEN A, GEN *ptB, long remove)
 {
-  pari_sp av = avma, av1, lim;
+  pari_sp av = avma, av1;
   long m, n, r, i, j, k, li;
   GEN B, c, h, a;
 
@@ -1815,7 +1815,7 @@ ZM_hnfall(GEN A, GEN *ptB, long remove)
   }
   c = zero_zv(m);
   h = const_vecsmall(n, m);
-  av1 = avma; lim = stack_lim(av1,1);
+  av1 = avma;
   A = RgM_shallowcopy(A);
   B = ptB? matid(n): NULL;
   r = n+1;
@@ -1830,7 +1830,7 @@ ZM_hnfall(GEN A, GEN *ptB, long remove)
         /* zero a = Aij  using  Aik */
         if (signe(a)) ZC_elem(a,gcoeff(A,i,k), A,B,j,k);
         ZM_reduce(A,B, i,k); /* ensure reduced entries */
-        if (low_stack(lim, stack_lim(av1,1)))
+        if (gc_needed(av1,1))
         {
           if (DEBUGMEM>1) pari_warn(warnmem,"hnfall[1], li = %ld", li);
           gerepileall(av1, B? 2: 1, &A, &B);
@@ -1853,7 +1853,7 @@ ZM_hnfall(GEN A, GEN *ptB, long remove)
       if (B) ZV_togglesign(gel(B,r));
     }
     ZM_reduce(A,B, li,r);
-    if (low_stack(lim, stack_lim(av1,1)))
+    if (gc_needed(av1,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"hnfall[2], li = %ld", li);
       gerepileall(av1, B? 2: 1, &A, &B);
@@ -1869,7 +1869,7 @@ ZM_hnfall(GEN A, GEN *ptB, long remove)
       k = c[i];
       if (signe(a)) ZC_elem(a,gcoeff(A,i,k), A,B, j,k);
       ZM_reduce(A,B, i,k); /* ensure reduced entries, even if a = 0 */
-      if (low_stack(lim, stack_lim(av1,1)))
+      if (gc_needed(av1,1))
       {
         if (DEBUGMEM>1) pari_warn(warnmem,"hnfall[3], j = %ld", j);
         gerepileall(av1, B? 2: 1, &A, &B);
@@ -2086,7 +2086,7 @@ ZM_snf_no_divide(GEN x, long i)
 GEN
 ZM_snfall_i(GEN x, GEN *ptU, GEN *ptV, int return_vec)
 {
-  pari_sp av0 = avma, av, lim = stack_lim(av0,1);
+  pari_sp av0 = avma, av;
   long i, j, k, m0, m, n0, n;
   GEN p1, u, v, U, V, V0, mdet, ys, perm = NULL;
 
@@ -2187,7 +2187,7 @@ ZM_snfall_i(GEN x, GEN *ptU, GEN *ptV, int return_vec)
         b = gcoeff(x,i,j); if (!signe(b)) continue;
         a = gcoeff(x,i,i);
         ZC_elem(b, a, x,V, j,i);
-        if (low_stack(lim, stack_lim(av,1)))
+        if (gc_needed(av,1))
         {
           if (DEBUGMEM>1) pari_warn(warnmem,"[1]: ZM_snfall i = %ld", i);
           snf_pile(av, &x,&U,&V);
@@ -2210,7 +2210,7 @@ ZM_snfall_i(GEN x, GEN *ptU, GEN *ptV, int return_vec)
         gcoeff(x,j,i) = gen_0;
         gcoeff(x,i,i) = d;
         if (U) update(u,v,a,b,(GEN*)(U+i),(GEN*)(U+j));
-        if (low_stack(lim, stack_lim(av,1)))
+        if (gc_needed(av,1))
         {
           if (DEBUGMEM>1) pari_warn(warnmem,"[2]: ZM_snfall, i = %ld", i);
           snf_pile(av, &x,&U,&V);
@@ -2227,7 +2227,7 @@ ZM_snfall_i(GEN x, GEN *ptU, GEN *ptV, int return_vec)
           gcoeff(x,i,j) = addii(gcoeff(x,i,j),gcoeff(x,k,j));
         if (U) gel(U,i) = gadd(gel(U,i),gel(U,k));
       }
-      if (low_stack(lim, stack_lim(av,1)))
+      if (gc_needed(av,1))
       {
         if (DEBUGMEM>1) pari_warn(warnmem,"[3]: ZM_snfall");
         snf_pile(av, &x,&U,&V);
@@ -2405,7 +2405,7 @@ gsnf_no_divide(GEN x, long i, long vx)
 GEN
 RgM_hnfall(GEN A, GEN *pB, long remove)
 {
-  pari_sp av, lim;
+  pari_sp av;
   long li, j, k, m, n, def, ldef;
   GEN B;
   long vx = gvar(A);
@@ -2417,7 +2417,7 @@ RgM_hnfall(GEN A, GEN *pB, long remove)
     return ZM_hnfall(A, pB, remove);
   }
   m = nbrows(A);
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
   A = RgM_shallowcopy(A);
   B = pB? matid(n): NULL;
   def = n; ldef = (m>n)? m-n: 0;
@@ -2438,12 +2438,12 @@ RgM_hnfall(GEN A, GEN *pB, long remove)
     else
     {
       GEN d;
-      gcoeff(A,li,def) = RgX_normalize(T, &d);
+      gcoeff(A,li,def) = RgX_normalize_all(T, &d);
       if (B && !gequal1(d)) gel(B, def) = RgC_Rg_div(gel(B, def), d);
       RgM_reduce(A, B, li, def, vx);
       def--;
     }
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"ghnfall");
       gerepileall(av, B? 2: 1, &A, &B);
@@ -2459,7 +2459,7 @@ RgM_hnfall(GEN A, GEN *pB, long remove)
 static GEN
 gsmithall_i(GEN x,long all)
 {
-  pari_sp av, lim;
+  pari_sp av;
   long i, j, k, n;
   GEN z, u, v, U, V;
   long vx = gvar(x);
@@ -2468,7 +2468,7 @@ gsmithall_i(GEN x,long all)
   n = lg(x)-1;
   if (!n) return trivsmith(all);
   if (lgcols(x) != n+1) pari_err_DIM("gsmithall");
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
   x = RgM_shallowcopy(x);
   if (all) { U = matid(n); V = matid(n); }
   for (i=n; i>=2; i--)
@@ -2517,7 +2517,7 @@ gsmithall_i(GEN x,long all)
           gcoeff(x,i,j) = gadd(gcoeff(x,i,j),gcoeff(x,k,j));
         if (all) gel(U,i) = gadd(gel(U,i),gel(U,k));
       }
-      if (low_stack(lim, stack_lim(av,1)))
+      if (gc_needed(av,1))
       {
         if (DEBUGMEM>1) pari_warn(warnmem,"gsmithall");
         gerepileall(av, all? 3: 1, &x, &U, &V);
@@ -2528,7 +2528,7 @@ gsmithall_i(GEN x,long all)
   {
     GEN d, T = gcoeff(x,k,k);
     if (!signe(T)) continue;
-    if (is_RgX(T,vx)) T = RgX_normalize(T, &d); else { d = T; T = gen_1; }
+    if (is_RgX(T,vx)) T = RgX_normalize_all(T, &d); else { d = T; T = gen_1; }
     if (all && !gequal1(d)) gel(V,k) = RgC_Rg_div(gel(V,k), d);
     gcoeff(x,k,k) = T;
   }
@@ -2589,110 +2589,3 @@ ZM_snf_group(GEN H, GEN *newU, GEN *newUi)
   return D;
 }
 
-/***********************************************************************
- ****                                                               ****
- ****         Frobenius form and Jordan form of a matrix            ****
- ****                                                               ****
- ***********************************************************************/
-
-static long
-prod_degree(GEN V)
-{
-  long i, s=0, l = lg(V);
-  for (i=1; i<l; i++)
-  {
-    long d = degpol(gel(V,i));
-    if (d<0) return d;
-    s += d;
-  }
-  return s;
-}
-
-GEN
-Frobeniusform(GEN V, long n)
-{
-  long i, j, k;
-  GEN M = zeromatcopy(n,n);
-  for (k=1,i=1;i<lg(V);i++,k++)
-  {
-    GEN  P = gel(V,i);
-    long d = degpol(P);
-    if (k+d-1 > n) pari_err_PREC("matfrobenius");
-    for (j=0; j<d-1; j++, k++) gcoeff(M,k+1,k) = gen_1;
-    for (j=0; j<d; j++) gcoeff(M,k-j,k) = gneg(gel(P, 1+d-j));
-  }
-  return M;
-}
-
-static GEN
-build_frobeniusbc(GEN V, long n)
-{
-  long i, j, k, l, m = lg(V)-1;
-  GEN M = zeromatcopy(n,n), z = monomial(gen_m1, 1, 0); /* -x */
-  for (k=1,l=1+m,i=1;i<=m;i++,k++)
-  {
-    GEN  P = gel(V,i);
-    long d = degpol(P);
-    if (d <= 0) continue;
-    if (l+d-2 > n) pari_err_PREC("matfrobenius");
-    gcoeff(M,k,i) = gen_1;
-    for (j=1; j<d; j++,k++,l++)
-    {
-      gcoeff(M,k,l)   = z;
-      gcoeff(M,k+1,l) = gen_1;
-    }
-  }
-  return M;
-}
-
-static GEN
-build_basischange(GEN N, GEN U)
-{
-  long i, j, n = lg(N)-1;
-  GEN p2 = cgetg(n+1, t_MAT);
-  for (j = 1; j <= n; ++j)
-  {
-    pari_sp btop = avma;
-    GEN p3 = NULL;
-    for (i = 1; i <= n; ++i)
-    {
-      GEN Uij = gcoeff(U, i, j), z;
-      if (is_RgX(Uij, 0))
-        z = RgX_RgM_eval_col(Uij, N, i);
-      else
-        z = Rg_col_ei(Uij, n, i);
-      p3 = p3 ? RgC_add(p3, z):z;
-    }
-    gel(p2,j) = gerepileupto(btop, p3);
-  }
-  return p2;
-}
-
-GEN
-matfrobenius(GEN M, long flag, long v)
-{
-  pari_sp ltop=avma;
-  long n;
-  GEN D, A, N, B, R, M_x;
-  if (typ(M)!=t_MAT) pari_err_TYPE("matfrobenius",M);
-  if (v<0) v=0;
-  if (varncmp(gvar(M), v) <= 0) pari_err_PRIORITY("matfrobenius", M, "<=", v);
-  n = lg(M)-1;
-  if (n && lgcols(M)!=n+1) pari_err_DIM("matfrobenius");
-  M_x = RgM_Rg_add_shallow(M, monomial(gen_m1, 1, v));
-  if (flag<2)
-  {
-    D = matsnf0(M_x,6);
-    if (prod_degree(D) != n) pari_err_PREC("matfrobenius");
-    if (flag != 1) D = Frobeniusform(D, n);
-    return gerepileupto(ltop, D);
-  }
-  if (flag>2) pari_err_FLAG("matfrobenius");
-  A = matsnf0(M_x,3);
-  D = smithclean(RgM_diagonal_shallow(gel(A,3)));
-  if (prod_degree(D) != n) pari_err_PREC("matfrobenius");
-  N = Frobeniusform(D, n);
-  B = build_frobeniusbc(D, n);
-  R = build_basischange(N, RgM_mul(B,gel(A,1)));
-  return gerepilecopy(ltop, mkvec2(N,R));
-}
diff --git a/src/basemath/hyperell.c b/src/basemath/hyperell.c
new file mode 100644
index 0000000..da5bee8
--- /dev/null
+++ b/src/basemath/hyperell.c
@@ -0,0 +1,691 @@
+/* Copyright (C) 2014  The PARI group.
+
+This file is part of the PARI/GP package.
+
+PARI/GP 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. It is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY WHATSOEVER.
+
+Check the License for details. You should have received a copy of it, along
+with the package; see the file 'COPYING'. If not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+/********************************************************************/
+/**                                                                **/
+/**                     HYPERELLIPTIC CURVES                       **/
+/**                                                                **/
+/********************************************************************/
+#include "pari.h"
+#include "paripriv.h"
+
+/* Implementation of Kedlaya Algorithm for counting point on hyperelliptic
+curves by Bill Allombert based on a GP script by Bernadette Perrin-Riou.
+
+References:
+Pierrick Gaudry and Nicolas G\"urel
+Counting Points in Medium Characteristic Using Kedlaya's Algorithm
+Experiment. Math.  Volume 12, Number 4 (2003), 395-402.
+   http://projecteuclid.org/euclid.em/1087568016
+
+Harrison, M. An extension of Kedlaya's algorithm for hyperelliptic
+  curves. Journal of Symbolic Computation, 47 (1) (2012), 89-101.
+  http://arxiv.org/pdf/1006.4206v3.pdf
+*/
+
+static GEN
+FpXXQ_red(GEN S, GEN T, GEN p)
+{
+  pari_sp av = avma;
+  long i, dS = degpol(S);
+  GEN A, C;
+  if (signe(S)==0) return pol_0(varn(T));
+  A = cgetg(dS+3, t_POL);
+  C = pol_0(varn(T));
+  for(i=dS; i>0; i--)
+  {
+    GEN Si = FpX_add(C, gel(S,i+2), p);
+    GEN R, Q = FpX_divrem(Si, T, p, &R);
+    gel(A,i+2) = R;
+    C = Q;
+  }
+  gel(A,2) = FpX_add(C, gel(S,2), p);
+  A[1] = S[1];
+  return gerepilecopy(av, FpXX_renormalize(A,dS+3));
+}
+
+static GEN
+FpXXQ_sqr(GEN x, GEN T, GEN p)
+{
+  pari_sp av = avma;
+  long n = degpol(T);
+  GEN z = FpX_red(ZXX_sqr_Kronecker(x, n), p);
+  z = Kronecker_to_ZXX(z, n, varn(T));
+  return gerepileupto(av, FpXXQ_red(z, T, p));
+}
+
+static GEN
+FpXXQ_mul(GEN x, GEN y, GEN T, GEN p)
+{
+  pari_sp av = avma;
+  long n = degpol(T);
+  GEN z = FpX_red(ZXX_mul_Kronecker(x, y, n), p);
+  z = Kronecker_to_ZXX(z, n, varn(T));
+  return gerepileupto(av, FpXXQ_red(z, T, p));
+}
+
+static GEN
+ZpXXQ_invsqrt(GEN S, GEN T, ulong p, long e)
+{
+  pari_sp av = avma, av2;
+  ulong mask;
+  long v = varn(S), n=1;
+  GEN a = pol_1(v);
+  if (e <= 1) return gerepilecopy(av, a);
+  mask = quadratic_prec_mask(e);
+  av2 = avma;
+  for (;mask>1;)
+  {
+    GEN q, q2, q22, f, fq, afq;
+    long n2 = n;
+    n<<=1; if (mask & 1) n--;
+    mask >>= 1;
+    q = powuu(p,n); q2 = powuu(p,n2);
+    f = RgX_sub(FpXXQ_mul(S, FpXXQ_sqr(a, T, q), T, q), pol_1(v));
+    fq = ZXX_Z_divexact(f, q2);
+    q22 = shifti(addis(q2,1),-1);
+    afq = FpXX_Fp_mul(FpXXQ_mul(a, fq, T, q2), q22, q2);
+    a = RgX_sub(a, ZXX_Z_mul(afq, q2));
+    if (gc_needed(av2,1))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"ZpXXQ_invsqrt, e = %ld", n);
+      a = gerepileupto(av2, a);
+    }
+  }
+  return gerepileupto(av, a);
+}
+
+static GEN
+to_ZX(GEN a, long v) { return typ(a)==t_INT? scalarpol(a,v): a; }
+
+static void
+is_sing(GEN H, ulong p)
+{
+  pari_err_DOMAIN("hyperellpadicfrobenius","H","is singular at",utoi(p),H);
+}
+
+static void
+get_UV(GEN *U, GEN *V, GEN T, ulong p, long e)
+{
+  GEN q = powuu(p,e), d;
+  GEN dT = FpX_deriv(T, q);
+  GEN R = polresultantext(T, dT);
+  long v = varn(T);
+  if (dvdiu(gel(R,3),p)) is_sing(T, p);
+  d = Fp_inv(gel(R,3), q);
+  *U = FpX_Fp_mul(FpX_red(to_ZX(gel(R,1),v),q),d,q);
+  *V = FpX_Fp_mul(FpX_red(to_ZX(gel(R,2),v),q),d,q);
+}
+
+static GEN
+frac_to_Fp(GEN a, GEN b, GEN p)
+{
+  GEN d = gcdii(a, b);
+  return Fp_div(diviiexact(a, d), diviiexact(b, d), p);
+}
+
+static GEN
+ZpXXQ_frob(GEN S, GEN U, GEN V, GEN T, ulong p, long e)
+{
+  pari_sp av = avma, av2;
+  long i, pr = degpol(S), dT = degpol(T);
+  GEN q = powuu(p,e);
+  GEN Tp = FpX_deriv(T, q), Tp1 = RgX_shift_shallow(Tp, 1);
+  GEN M = gel(S,pr+2), R;
+  av2 = avma;
+  for(i = pr-1; i>=0; i--)
+  {
+    GEN A, B, H, Bc;
+    ulong v, r;
+    H = FpX_divrem(FpX_mul(V,M,q), T, q, &B);
+    A = FpX_add(FpX_mul(U,M,q), FpX_mul(H, Tp, q),q);
+    v = u_lvalrem(2*i+1,p,&r);
+    Bc = FpX_deriv(B, q);
+    Bc = FpX_Fp_mul(ZX_Z_divexact(Bc,powuu(p,v)),Fp_div(gen_2, utoi(r), q), q);
+    M = FpX_add(gel(S,i+2), FpX_add(A, Bc, q), q);
+    if (gc_needed(av2,1))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"ZpXXQ_frob, step 1, i = %ld", i);
+      M = gerepileupto(av2, M);
+    }
+  }
+  if (degpol(M)<dT-1)
+    return gerepileupto(av, M);
+  R = RgX_shift_shallow(M,dT-degpol(M)-2);
+  av2 = avma;
+  for(i = degpol(M)-dT+2; i>=1; i--)
+  {
+    GEN B, c;
+    R = RgX_shift_shallow(R, 1);
+    gel(R,2) = gel(M, i+1);
+    if (degpol(R) < dT) continue;
+    B = FpX_add(FpX_mulu(T, 2*i, q), Tp1, q);
+    c = frac_to_Fp(leading_term(R), leading_term(B), q);
+    R = FpX_sub(R, FpX_Fp_mul(B, c, q), q);
+    if (gc_needed(av2,1))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"ZpXXQ_frob, step 2, i = %ld", i);
+      R = gerepileupto(av2, R);
+    }
+  }
+  if (degpol(R)==dT-1)
+  {
+    GEN c = frac_to_Fp(leading_term(R), leading_term(Tp), q);
+    R = FpX_sub(R, FpX_Fp_mul(Tp, c, q), q);
+    return gerepileupto(av, R);
+  } else
+    return gerepilecopy(av, R);
+}
+
+static GEN
+revdigits(GEN v)
+{
+  long i, n = lg(v)-1;
+  GEN w = cgetg(n+2, t_POL);
+  w[1] = evalsigne(1)|evalvarn(0);
+  for (i=0; i<n; i++)
+    gel(w,i+2) = gel(v,n-i);
+  return FpXX_renormalize(w, n+2);
+}
+
+static GEN
+diff_red(GEN s, GEN A, long m, GEN T, GEN p)
+{
+  long v, n;
+  GEN Q, sQ, qS;
+  pari_timer ti;
+  if (DEBUGLEVEL>1) timer_start(&ti);
+  Q = revdigits(FpX_digits(A,T,p));
+  n = degpol(Q);
+  if (DEBUGLEVEL>1) timer_printf(&ti,"reddigits");
+  sQ = FpXXQ_mul(s,Q,T,p);
+  if (DEBUGLEVEL>1) timer_printf(&ti,"redmul");
+  qS = RgX_shift_shallow(sQ,m-n);
+  v = ZX_val(sQ);
+  if (n > m + v)
+  {
+    long i, l = n-m-v;
+    GEN rS = cgetg(l+1,t_VEC);
+    for (i = l-1; i >=0 ; i--)
+      gel(rS,i+1) = gel(sQ, 1+v+l-i);
+    rS = FpX_fromdigits(rS,T,p);
+    gel(qS,2) = FpX_add(FpX_mul(rS, T, p), gel(qS, 2), p);
+    if (DEBUGLEVEL>1) timer_printf(&ti,"redadd");
+  }
+  return qS;
+}
+
+static GEN
+ZC_to_padic(GEN C, GEN q)
+{
+  long i, l = lg(C);
+  GEN V = cgetg(l,t_COL);
+  for(i = 1; i < l; i++)
+    gel(V, i) = gadd(gel(C, i), q);
+  return V;
+}
+
+static GEN
+ZM_to_padic(GEN M, GEN q)
+{
+  long i, l = lg(M);
+  GEN V = cgetg(l,t_MAT);
+  for(i = 1; i < l; i++)
+    gel(V, i) = ZC_to_padic(gel(M, i), q);
+  return V;
+}
+
+static GEN
+ZX_to_padic(GEN P, GEN q)
+{
+  long i, l = lg(P);
+  GEN Q = cgetg(l, t_POL);
+  Q[1] = P[1];
+  for (i=2; i<l ;i++)
+    gel(Q,i) = gadd(gel(P,i), q);
+  return normalizepol(Q);
+}
+
+static GEN
+ZXC_to_padic(GEN C, GEN q)
+{
+  long i, l = lg(C);
+  GEN V = cgetg(l,t_COL);
+  for(i = 1; i < l; i++)
+    gel(V, i) = ZX_to_padic(gel(C, i), q);
+  return V;
+}
+
+static GEN
+ZXM_to_padic(GEN M, GEN q)
+{
+  long i, l = lg(M);
+  GEN V = cgetg(l,t_MAT);
+  for(i = 1; i < l; i++)
+    gel(V, i) = ZXC_to_padic(gel(M, i), q);
+  return V;
+}
+
+static GEN
+ZlX_hyperellpadicfrobenius(GEN H, ulong p, long n)
+{
+  pari_sp av = avma;
+  long N, i, d;
+  GEN F, s, Q, pN1, U, V;
+  pari_timer ti;
+  if (typ(H) != t_POL) pari_err_TYPE("hyperellpadicfrobenius",H);
+  if (p == 2) is_sing(H, 2);
+  d = degpol(H);
+  if (d <= 0)
+    pari_err_CONSTPOL("hyperellpadicfrobenius");
+  if (odd(d) &&  p < (ulong) d)
+    pari_err_DOMAIN("hyperellpadicfrobenius","p","<", utoi(d), utoi(p));
+  if (!odd(d) &&  2*p < (ulong) d)
+    pari_err_DOMAIN("hyperellpadicfrobenius","2*p","<", utoi(d), utoi(2*p));
+  if (n < 1)
+    pari_err_DOMAIN("hyperellpadicfrobenius","n","<", gen_1, utoi(n));
+  N = n + logint(stoi(2*n), stoi(p), NULL);
+  pN1 = powuu(p,N+1);
+  Q = RgX_to_FpX(H, pN1);
+  if (dvdiu(leading_term(Q),p)) is_sing(H, p);
+  setvarn(Q,1);
+  if (DEBUGLEVEL>1) timer_start(&ti);
+  s = revdigits(FpX_digits(RgX_inflate(Q, p), Q, pN1));
+  if (DEBUGLEVEL>1) timer_printf(&ti,"s1");
+  s = ZpXXQ_invsqrt(s, Q, p, N);
+  if (DEBUGLEVEL>1) timer_printf(&ti,"invsqrt");
+  get_UV(&U, &V, Q, p, N+1);
+  F = cgetg(d, t_MAT);
+  for (i = 1; i < d; i++)
+  {
+    pari_sp av2 = avma;
+    GEN M, D;
+    D = diff_red(s, monomial(utoi(p),p*i-1,1),p>>1, Q, pN1);
+    if (DEBUGLEVEL>1) timer_printf(&ti,"red");
+    M = ZpXXQ_frob(D, U, V, Q, p, N + 1);
+    if (DEBUGLEVEL>1) timer_printf(&ti,"frob");
+    gel(F, i) = gerepilecopy(av2, RgX_to_RgC(M, d-1));
+  }
+  return gerepileupto(av, F);
+}
+
+GEN
+hyperellpadicfrobenius(GEN H, ulong p, long n)
+{
+  pari_sp av = avma;
+  GEN M = ZlX_hyperellpadicfrobenius(H, p, n);
+  GEN q = zeropadic(utoi(p),n);
+  return gerepileupto(av, ZM_to_padic(M, q));
+}
+
+INLINE GEN
+FpXXX_renormalize(GEN x, long lx)  { return ZXX_renormalize(x,lx); }
+
+static GEN
+FpXQXXQ_red(GEN F, GEN S, GEN T, GEN p)
+{
+  pari_sp av = avma;
+  long i, dF = degpol(F);
+  GEN A, C;
+  if (signe(F)==0) return pol_0(varn(S));
+  A = cgetg(dF+3, t_POL);
+  C = pol_0(varn(S));
+  for(i=dF; i>0; i--)
+  {
+    GEN Fi = FpXX_add(C, gel(F,i+2), p);
+    GEN R, Q = FpXQX_divrem(Fi, S, T, p, &R);
+    gel(A,i+2) = R;
+    C = Q;
+  }
+  gel(A,2) = FpXX_add(C, gel(F,2), p);
+  A[1] = F[1];
+  return gerepilecopy(av, FpXXX_renormalize(A,dF+3));
+}
+
+static GEN
+FpXQXXQ_sqr(GEN x, GEN S, GEN T, GEN p)
+{
+  pari_sp av = avma;
+  GEN z, kx;
+  long n = degpol(S);
+  kx = ZXX_to_Kronecker(x, n);
+  z = Kronecker_to_ZXX(FpXQX_sqr(kx, T, p), n, varn(S));
+  return gerepileupto(av, FpXQXXQ_red(z, S, T, p));
+}
+
+static GEN
+FpXQXXQ_mul(GEN x, GEN y, GEN S, GEN T, GEN p)
+{
+  pari_sp av = avma;
+  GEN z, kx, ky;
+  long n = degpol(S);
+  kx = ZXX_to_Kronecker(x, n);
+  ky = ZXX_to_Kronecker(y, n);
+  z = Kronecker_to_ZXX(FpXQX_mul(ky, kx, T, p), n, varn(S));
+  return gerepileupto(av, FpXQXXQ_red(z, S, T, p));
+}
+
+static GEN
+FpXXX_red(GEN z, GEN p)
+{
+  GEN res;
+  long i, l = lg(z);
+  res = cgetg(l,t_POL); res[1] = z[1];
+  for (i=2; i<l; i++)
+  {
+    GEN zi = gel(z,i);
+    if (typ(zi)==t_INT)
+      gel(res,i) = modii(zi,p);
+    else
+     gel(res,i) = FpXX_red(zi,p);
+  }
+  return FpXXX_renormalize(res,lg(res));
+}
+
+static GEN
+FpXXX_Fp_mul(GEN z, GEN a, GEN p)
+{
+  return FpXXX_red(RgX_Rg_mul(z, a), p);
+}
+
+static GEN
+ZpXQXXQ_invsqrt(GEN F, GEN S, GEN T, ulong p, long e)
+{
+  pari_sp av = avma, av2, av3;
+  ulong mask;
+  long v = varn(F), n=1;
+  pari_timer ti;
+  GEN a = pol_1(v);
+  if (DEBUGLEVEL>1) timer_start(&ti);
+  if (e <= 1) return gerepilecopy(av, a);
+  mask = quadratic_prec_mask(e);
+  av2 = avma;
+  for (;mask>1;)
+  {
+    GEN q, q2, q22, f, fq, afq;
+    long n2 = n;
+    n<<=1; if (mask & 1) n--;
+    mask >>= 1;
+    q = powuu(p,n); q2 = powuu(p,n2);
+    av3 = avma;
+    f = RgX_sub(FpXQXXQ_mul(F, FpXQXXQ_sqr(a, S, T, q), S, T, q), pol_1(v));
+    fq = gerepileupto(av3, RgX_Rg_divexact(f, q2));
+    q22 = shifti(addis(q2,1),-1);
+    afq = FpXXX_Fp_mul(FpXQXXQ_mul(a, fq, S, T, q2), q22, q2);
+    a = RgX_sub(a, RgX_Rg_mul(afq, q2));
+    if (gc_needed(av2,1))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"ZpXQXXQ_invsqrt, e = %ld", n);
+      a = gerepileupto(av2, a);
+    }
+  }
+  return gerepileupto(av, a);
+}
+
+static GEN
+frac_to_Fq(GEN a, GEN b, GEN T, GEN p)
+{
+  GEN d = gcdii(ZX_content(a), ZX_content(b));
+  return FpXQ_div(ZX_Z_divexact(a, d), ZX_Z_divexact(b, d), T, p);
+}
+
+static GEN
+ZpXQXXQ_frob(GEN F, GEN U, GEN V, GEN S, GEN T, ulong p, long e)
+{
+  pari_sp av = avma, av2;
+  long i, pr = degpol(F), dS = degpol(S), v = varn(T);
+  GEN q = powuu(p,e);
+  GEN Sp = RgX_deriv(S), Sp1 = RgX_shift_shallow(Sp, 1);
+  GEN M = gel(F,pr+2), R;
+  av2 = avma;
+  for(i = pr-1; i>=0; i--)
+  {
+    GEN A, B, H, Bc;
+    ulong v, r;
+    H = FpXQX_divrem(FpXQX_mul(V, M, T, q), S, T, q, &B);
+    A = FpXX_add(FpXQX_mul(U, M, T, q), FpXQX_mul(H, Sp, T, q),q);
+    v = u_lvalrem(2*i+1,p,&r);
+    Bc = RgX_deriv(B);
+    Bc = FpXX_Fp_mul(ZXX_Z_divexact(Bc,powuu(p,v)), Fp_div(gen_2, utoi(r), q), q);
+    M = FpXX_add(gel(F,i+2), FpXX_add(A, Bc, q), q);
+    if (gc_needed(av2,1))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"ZpXQXXQ_frob, step 1, i = %ld", i);
+      M = gerepileupto(av2, M);
+    }
+  }
+  if (degpol(M)<dS-1)
+    return gerepileupto(av, M);
+  R = RgX_shift_shallow(M,dS-degpol(M)-2);
+  av2 = avma;
+  for(i = degpol(M)-dS+2; i>=1; i--)
+  {
+    GEN B, c;
+    R = RgX_shift_shallow(R, 1);
+    gel(R,2) = gel(M, i+1);
+    if (degpol(R) < dS) continue;
+    B = FpXX_add(FpXX_mulu(S, 2*i, q), Sp1, q);
+    c = frac_to_Fq(to_ZX(leading_term(R),v), to_ZX(leading_term(B),v), T, q);
+    R = FpXX_sub(R, FpXQX_FpXQ_mul(B, c, T, q), q);
+    if (gc_needed(av2,1))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"ZpXXQ_frob, step 2, i = %ld", i);
+      R = gerepileupto(av2, R);
+    }
+  }
+  if (degpol(R)==dS-1)
+  {
+    GEN c = frac_to_Fq(to_ZX(leading_term(R),v), to_ZX(leading_term(Sp),v), T, q);
+    R = FpXX_sub(R, FpXQX_FpXQ_mul(Sp, c, T, q), q);
+    return gerepileupto(av, R);
+  } else
+    return gerepilecopy(av, R);
+}
+
+
+static GEN
+Fq_diff_red(GEN s, GEN A, long m, GEN S, GEN T, GEN p)
+{
+  long v, n;
+  GEN Q, sQ, qS;
+  pari_timer ti;
+  if (DEBUGLEVEL>1) timer_start(&ti);
+  Q = revdigits(FpXQX_digits(A, S, T, p));
+  n = degpol(Q);
+  if (DEBUGLEVEL>1) timer_printf(&ti,"reddigits");
+  sQ = FpXQXXQ_mul(s,Q,S,T,p);
+  if (DEBUGLEVEL>1) timer_printf(&ti,"redmul");
+  qS = RgX_shift_shallow(sQ,m-n);
+  v = ZX_val(sQ);
+  if (n > m + v)
+  {
+    long i, l = n-m-v;
+    GEN rS = cgetg(l+1,t_VEC);
+    for (i = l-1; i >=0 ; i--)
+      gel(rS,i+1) = gel(sQ, 1+v+l-i);
+    rS = FpXQX_fromdigits(rS,S,T,p);
+    gel(qS,2) = FpXX_add(FpXQX_mul(rS, S, T, p), gel(qS, 2), p);
+    if (DEBUGLEVEL>1) timer_printf(&ti,"redadd");
+  }
+  return qS;
+}
+
+static void
+Fq_get_UV(GEN *U, GEN *V, GEN S, GEN T, ulong p, long e)
+{
+  GEN q = powuu(p, e), d;
+  GEN dS = RgX_deriv(S);
+  GEN R  = polresultantext(S, dS), C;
+  long v = varn(S);
+  if (signe(FpX_red(to_ZX(gel(R,3),v),utoi(p)))==0) is_sing(S, p);
+  C = FpXQ_red(gel(R, 3), T, q);
+  d = ZpXQ_inv(C, T, utoi(p), e);
+  *U = FpXQX_FpXQ_mul(FpXQX_red(to_ZX(gel(R,1),v),T,q),d,T,q);
+  *V = FpXQX_FpXQ_mul(FpXQX_red(to_ZX(gel(R,2),v),T,q),d,T,q);
+}
+
+static GEN
+ZXX_to_FpXC(GEN x, long N, GEN p, long v)
+{
+  long i, l;
+  GEN z;
+  l = lg(x)-1; x++;
+  if (l > N+1) l = N+1; /* truncate higher degree terms */
+  z = cgetg(N+1,t_COL);
+  for (i=1; i<l ; i++)
+  {
+    GEN xi = gel(x, i);
+    gel(z,i) = typ(xi)==t_INT? scalarpol(Fp_red(xi, p), v): FpX_red(xi, p);
+  }
+  for (   ; i<l ; i++)
+    gel(z,i) = pol_0(v);
+  return z;
+}
+
+GEN
+ZlXQX_hyperellpadicfrobenius(GEN H, GEN T, ulong p, long n)
+{
+  pari_sp av = avma;
+  long N, i, d;
+  GEN xp, F, s, q, Q, pN1, U, V;
+  pari_timer ti;
+  if (typ(H) != t_POL) pari_err_TYPE("hyperellpadicfrobenius",H);
+  if (p == 2) is_sing(H, 2);
+  d = degpol(H);
+  if (d <= 0)
+    pari_err_CONSTPOL("hyperellpadicfrobenius");
+  if (odd(d) &&  p < (ulong) d)
+    pari_err_DOMAIN("hyperellpadicfrobenius","p","<", utoi(d), utoi(p));
+  if (!odd(d) && 2*p < (ulong) d)
+    pari_err_DOMAIN("hyperellpadicfrobenius","2*p","<", utoi(d), utoi(p));
+  if (n < 1)
+    pari_err_DOMAIN("hyperellpadicfrobenius","n","<", gen_1, utoi(n));
+  N = n + logint(stoi(2*n), stoi(p), NULL);
+  q = powuu(p,n); pN1 = powuu(p,N+1); T = FpX_get_red(T, pN1);
+  Q = RgX_to_FqX(H, T, pN1);
+  if (signe(FpX_red(to_ZX(leading_term(Q),varn(Q)),utoi(p)))==0) is_sing(H, p);
+  if (DEBUGLEVEL>1) timer_start(&ti);
+  xp = ZpX_Frobenius(T, utoi(p), N+1);
+  s = RgX_inflate(FpXY_FpXQ_evalx(Q, xp, T, pN1), p);
+  s = revdigits(FpXQX_digits(s, Q, T, pN1));
+  if (DEBUGLEVEL>1) timer_printf(&ti,"s1");
+  s = ZpXQXXQ_invsqrt(s, Q, T, p, N);
+  if (DEBUGLEVEL>1) timer_printf(&ti,"invsqrt");
+  Fq_get_UV(&U, &V, Q, T, p, N+1);
+  if (DEBUGLEVEL>1) timer_printf(&ti,"get_UV");
+  F = cgetg(d, t_MAT);
+  for (i = 1; i < d; i++)
+  {
+    pari_sp av2 = avma;
+    GEN M, D;
+    D = Fq_diff_red(s, monomial(utoi(p),p*i-1,1),p>>1, Q, T, pN1);
+    if (DEBUGLEVEL>1) timer_printf(&ti,"red");
+    M = ZpXQXXQ_frob(D, U, V, Q, T, p, N + 1);
+    if (DEBUGLEVEL>1) timer_printf(&ti,"frob");
+    gel(F, i) = gerepileupto(av2, ZXX_to_FpXC(M, d-1, q, varn(T)));
+  }
+  return gerepileupto(av, F);
+}
+
+GEN
+nfhyperellpadicfrobenius(GEN H, GEN T, ulong p, long n)
+{
+  pari_sp av = avma;
+  GEN M = ZlXQX_hyperellpadicfrobenius(lift(H),T,p,n);
+  GEN MM = ZpXQM_prodFrobenius(M, T, utoi(p), n);
+  GEN q = zeropadic(utoi(p),n);
+  GEN m = gmul(ZXM_to_padic(MM, q), gmodulo(gen_1, T));
+  return gerepileupto(av, m);
+}
+
+static GEN
+Flx_genus2charpoly_naive(GEN H, ulong p)
+{
+  pari_sp av = avma;
+  ulong pi = get_Fl_red(p);
+  ulong i, j, p2 = p>>1, D = 2, e = ((p&2UL) == 0) ? -1 : 1;
+  long a, b, c = 0;
+  if (degpol(H) == 5)
+    a = b = 0;
+  else
+  {
+    a = krouu(Flx_lead(H), p);
+    b = 1;
+  }
+  while (krouu(D, p) >= 0) D++;
+  for (i=0; i < p; i++)
+  {
+    ulong v = Flx_eval(H, i, p);
+    a += krouu(v, p);
+    b += !!v;
+    for (j=1; j <= p2; j++)
+    {
+      GEN r2 = Flx_Fl2_eval_pre(H, mkvecsmall2(i, j), D, p, pi);
+      c += uel(r2,2) ?
+           (uel(r2,1) ? krouu(Fl2_norm_pre(r2, D, p, pi), p): e)
+         : !!uel(r2,1);
+      avma = av;
+    }
+  }
+  return mkvecsmalln(6, 0UL, p*p, a*p, (b+2*c+a*a)>>1, a, 1UL);
+}
+
+GEN
+hyperellcharpoly(GEN H)
+{
+  pari_sp av = avma;
+  GEN M, R, T=NULL, pp=NULL;
+  long d, n, eps = 0;
+  ulong p;
+  if (is_vec_t(typ(H)) && lg(H)==3)
+    H = gadd(gsqr(gel(H, 2)), gmul2n(gel(H, 1), 2));
+  if (typ(H)!=t_POL || !RgX_is_FpXQX(H, &T, &pp) || !pp)
+    pari_err_TYPE("hyperellcharpoly",H);
+  p = itou(pp);
+  if (!T)
+  {
+    H = RgX_to_FpX(H, pp);
+    d = degpol(H);
+    if (p > 2 && ((d == 5 && p < 3000) || (d == 6 && p < 5500)))
+    {
+      GEN Hp = ZX_to_Flx(H, p);
+      if (!Flx_is_squarefree(Hp, p)) is_sing(H, p);
+      R = zx_to_ZX(Flx_genus2charpoly_naive(Hp, p));
+      return gerepileupto(av, R);
+    }
+    n = (d>>1) + 1; eps = odd(d)? 0: Fp_issquare(leading_term(H), pp);
+    M = hyperellpadicfrobenius(H, p, n);
+    R = centerlift(carberkowitz(M, 0));
+  }
+  else
+  {
+    int fixvar;
+    T = typ(T)==t_FFELT? FF_mod(T): RgX_to_FpX(T, pp);
+    fixvar = (varncmp(varn(T),varn(H)) <= 0);
+    if (fixvar) setvarn(T, fetch_var());
+    H = RgX_to_FpXQX(H, T, pp);
+    d = degpol(H); eps = odd(d)? 0: Fq_issquare(leading_term(H), T, pp);
+    n = ((degpol(T)*d)>>1) + 1;
+    M = nfhyperellpadicfrobenius(H, T, p, n);
+    R = centerlift(liftpol_shallow(carberkowitz(M, 0)));
+    if (fixvar) (void)delete_var();
+  }
+  if (!odd(d))
+  {
+    GEN q = T ? powuu(p, degpol(T)): pp;
+    GEN v, Rx = RgX_div_by_X_x(R, eps? q: negi(q), &v);
+    if (signe(v)) pari_err_BUG("hyperellcharpoly");
+    return gerepilecopy(av, Rx);
+  }
+  return gerepileupto(av, R);
+}
diff --git a/src/basemath/ifactor1.c b/src/basemath/ifactor1.c
index e08a560..0f12711 100644
--- a/src/basemath/ifactor1.c
+++ b/src/basemath/ifactor1.c
@@ -108,7 +108,7 @@ nextprime(GEN n)
   if (signe(n) <= 0) { avma = av; return gen_2; }
   if (lgefint(n) == 3)
   {
-    ulong k = unextprime(n[2]);
+    ulong k = unextprime(uel(n,2));
     avma = av;
     if (k) return utoipos(k);
 #ifdef LONG_IS_64BIT
@@ -187,7 +187,7 @@ precprime(GEN n)
   if (signe(n) <= 0) { avma = av; return gen_0; }
   if (lgefint(n) <= 3)
   {
-    ulong k = (ulong)n[2];
+    ulong k = uel(n,2);
     avma = av;
     return utoi(uprecprime(k));
   }
@@ -583,6 +583,7 @@ ellmult(GEN N, GEN *gl, long nbc, ulong k, GEN *X1, GEN *X2, GEN *XAUX)
 static GEN*
 alloc_scratch(long nbc, long spc, long tf)
 {
+  pari_sp bot = pari_mainstack->bot;
   long i, tw = evallg(tf) | evaltyp(t_INT), len = spc + 385 + spc*tf;
   GEN *X, w;
   if ((long)((GEN)avma - (GEN)bot) < len + (3*nbc + 240)*tf)
@@ -1178,7 +1179,7 @@ pollardbrent(GEN n)
   if (tf >= 4)
     size = expi(n) + 1;
   else if (tf == 3)                /* try to keep purify happy...  */
-    size = 1 + expu((ulong)n[2]);
+    size = 1 + expu(uel(n,2));
 
   if (size <= 28)
     c0 = 32;/* amounts very nearly to 'insist'. Now that we have squfof(), we
@@ -1492,7 +1493,7 @@ squfof(GEN n)
   int act1 = 1, act2 = 1;
 
 #ifdef LONG_IS_64BIT
-  if (tf > 3 || (tf == 3 && (ulong)n[2]          >= (1UL << (BITS_IN_LONG-5))))
+  if (tf > 3 || (tf == 3 && uel(n,2)             >= (1UL << (BITS_IN_LONG-5))))
 #else  /* 32 bits */
   if (tf > 4 || (tf == 4 && (ulong)(*int_MSW(n)) >= (1UL << (BITS_IN_LONG-5))))
 #endif
@@ -1959,12 +1960,12 @@ is_357_power(GEN x, GEN *pt, ulong *mask)
     return 0;
   }
 #ifdef LONG_IS_64BIT
-  r = (lx == 3)? (ulong)x[2]: umodiu(x, 6046846918939827UL);
+  r = (lx == 3)? uel(x,2): umodiu(x, 6046846918939827UL);
   if (!uis_357_powermod(r, mask)) return 0;
 #else
-  r = (lx == 3)? (ulong)x[2]: umodiu(x, 211*209*61*203);
+  r = (lx == 3)? uel(x,2): umodiu(x, 211*209*61*203);
   if (!uis_357_powermod_32bit_1(r, mask)) return 0;
-  r = (lx == 3)? (ulong)x[2]: umodiu(x, 117*31*43*71);
+  r = (lx == 3)? uel(x,2): umodiu(x, 117*31*43*71);
   if (!uis_357_powermod_32bit_2(r, mask)) return 0;
 #endif
   av = avma;
@@ -2982,7 +2983,7 @@ ifac_main(GEN *partial)
   if (factor_add_primes && !(get_hint(partial) & 8))
   {
     GEN p = VALUE(here);
-    if (lgefint(p)>3 || (ulong)p[2] > 0x1000000UL) (void)addprimes(p);
+    if (lgefint(p)>3 || uel(p,2) > 0x1000000UL) (void)addprimes(p);
   }
   return here;
 }
@@ -3010,7 +3011,7 @@ ifac_main(GEN *partial)
 static long
 ifac_decomp(GEN n, long hint)
 {
-  pari_sp av = avma, lim = stack_lim(av, 1);
+  pari_sp av = avma;
   long nb = 0;
   GEN part, here, workspc, pairs = (GEN)av;
 
@@ -3024,7 +3025,7 @@ ifac_decomp(GEN n, long hint)
   {
     here = ifac_main(&part);
     if (!here) break;
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       long offset;
       if(DEBUGMEM>1)
@@ -3069,7 +3070,7 @@ static long
 ifac_moebius(GEN n)
 {
   long mu = 1;
-  pari_sp av = avma, lim = stack_lim(av,1);
+  pari_sp av = avma;
   GEN part = ifac_start(n, 1);
   for(;;)
   {
@@ -3077,7 +3078,7 @@ ifac_moebius(GEN n)
     GEN p;
     if (!ifac_next(&part,&p,&v)) return v? 0: mu;
     mu = -mu;
-    if (low_stack(lim, stack_lim(av,1))) ifac_GC(av,&part);
+    if (gc_needed(av,1)) ifac_GC(av,&part);
   }
 }
 
@@ -3100,7 +3101,7 @@ ifac_skip(GEN part)
 static int
 ifac_ispowerful(GEN n)
 {
-  pari_sp av = avma, lim = stack_lim(av,1);
+  pari_sp av = avma;
   GEN part = ifac_start(n, 0);
   for(;;)
   {
@@ -3111,14 +3112,14 @@ ifac_ispowerful(GEN n)
     if (e != 1 || Z_isanypower(p,NULL)) { ifac_skip(part); continue; }
     if (!ifac_next(&part,&p,&e)) return 1;
     if (e == 1) return 0;
-    if (low_stack(lim, stack_lim(av,1))) ifac_GC(av,&part);
+    if (gc_needed(av,1)) ifac_GC(av,&part);
   }
 }
 static GEN
 ifac_core(GEN n)
 {
   GEN m = gen_1, c = cgeti(lgefint(n));
-  pari_sp av = avma, lim = stack_lim(av,1);
+  pari_sp av = avma;
   GEN part = ifac_start(n, 0);
   for(;;)
   {
@@ -3129,7 +3130,7 @@ ifac_core(GEN n)
     if (!odd(e) || Z_issquare(p)) { ifac_skip(part); continue; }
     if (!ifac_next(&part,&p,&e)) return m;
     if (odd(e)) m = mulii(m, p);
-    if (low_stack(lim, stack_lim(av,1))) { affii(m,c); m=c; ifac_GC(av,&part); }
+    if (gc_needed(av,1)) { affii(m,c); m=c; ifac_GC(av,&part); }
   }
 }
 
@@ -3157,9 +3158,9 @@ utridiv_bound(ulong n)
 }
 
 static void
-ifac_factoru(GEN n, GEN P, GEN E, long *pi)
+ifac_factoru(GEN n, long hint, GEN P, GEN E, long *pi)
 {
-  GEN part = ifac_start(n, 0);
+  GEN part = ifac_start_hint(n, 0, hint);
   for(;;)
   {
     long v;
@@ -3197,60 +3198,74 @@ u_forprime_next_fast(forprime_t *T)
 
 /* Factor n and output [p,e] where
  * p, e are vecsmall with n = prod{p[i]^e[i]} */
-GEN
-factoru(ulong n)
+static GEN
+factoru_sign(ulong n, ulong all, long hint)
 {
   GEN f, E, E2, P, P2;
   pari_sp av;
-  ulong p;
-  long v, i, oldi;
+  ulong p, lim;
+  long i;
   forprime_t S;
 
   if (n == 0) retmkvec2(mkvecsmall(0), mkvecsmall(1));
   if (n == 1) retmkvec2(cgetg(1,t_VECSMALL), cgetg(1,t_VECSMALL));
 
-  v = vals(n);
-  if (v)
-  {
-    n >>= v;
-    if (n == 1) retmkvec2(mkvecsmall(2), mkvecsmall(v));
-  }
   f = cgetg(3,t_VEC); av = avma;
+  lim = all; if (!lim) lim = utridiv_bound(n);
   /* enough room to store <= 15 primes and exponents (OK if n < 2^64) */
-  (void)new_chunk((15 + 1)*2);
-  u_forprime_init(&S, 3, utridiv_bound(n));
-  P = cgetg(16, t_VECSMALL);
+  (void)new_chunk(16*2);
+  P = cgetg(16, t_VECSMALL); i = 1;
   E = cgetg(16, t_VECSMALL);
-  if (v) { P[1] = 2; E[1] = v; i = 2; } else i = 1;
-  oldi = i;
-  while ( (p = u_forprime_next_fast(&S)) )
+  if (lim > 2)
   {
-    int stop;
-    /* tiny integers without small factors are often primes */
-    if (p == 673)
+    long v = vals(n), oldi;
+    if (v)
     {
-      oldi = i;
-      if (uisprime_661(n)) { P[i] = n; E[i] = 1; i++; goto END; }
+      P[1] = 2; E[1] = v; i = 2;
+      n >>= v; if (n == 1) goto END;
     }
-    v = u_lvalrem_stop(&n, p, &stop);
-    if (v) {
-      P[i] = p;
-      E[i] = v; i++;
-    }
-    if (stop) {
-      if (n != 1) { P[i] = n; E[i] = 1; i++; }
-      goto END;
+    u_forprime_init(&S, 3, lim);
+    oldi = i;
+    while ( (p = u_forprime_next_fast(&S)) )
+    {
+      int stop;
+      /* tiny integers without small factors are often primes */
+      if (p == 673)
+      {
+        oldi = i;
+        if (uisprime_661(n)) { P[i] = n; E[i] = 1; i++; goto END; }
+      }
+      v = u_lvalrem_stop(&n, p, &stop);
+      if (v) {
+        P[i] = p;
+        E[i] = v; i++;
+      }
+      if (stop) {
+        if (n != 1) { P[i] = n; E[i] = 1; i++; }
+        goto END;
+      }
     }
+    if (oldi != i && uisprime_661(n)) { P[i] = n; E[i] = 1; i++; goto END; }
+  }
+  if (all)
+  { /* smallfact: look for easy pure powers then stop */
+#ifdef LONG_IS_64BIT
+    ulong mask = all > 563 ? (all > 7129 ? 1: 3): 7;
+#else
+    ulong mask = all > 22 ? (all > 83 ? 1: 3): 7;
+#endif
+    long k = 1, ex;
+    while (uissquareall(n, &n)) k <<= 1;
+    while ( (ex = uis_357_power(n, &n, &mask)) ) k *= ex;
+    P[i] = n; E[i] = k; i++; goto END;
   }
-  if (oldi != i && uisprime_661(n)) { P[i] = n; E[i] = 1; i++; }
-  else
   {
     GEN perm;
-    ifac_factoru(utoipos(n), P, E, &i);
+    ifac_factoru(utoipos(n), hint, P, E, &i);
     setlg(P, i);
     perm = vecsmall_indexsort(P);
-    P = vecpermute(P, perm);
-    E = vecpermute(E, perm);
+    P = vecsmallpermute(P, perm);
+    E = vecsmallpermute(E, perm);
   }
 END:
   avma = av;
@@ -3259,6 +3274,9 @@ END:
   while (--i >= 1) { P2[i] = P[i]; E2[i] = E[i]; }
   return f;
 }
+GEN
+factoru(ulong n)
+{ return factoru_sign(n, 0, decomp_default_hint); }
 
 long
 moebiusu(ulong n)
@@ -3333,7 +3351,7 @@ moebius(GEN n)
       if (!equali1(gel(E,1))) { avma = av; return 0; }
     avma = av; return odd(l)? 1: -1;
   }
-  if (lgefint(n) == 3) return moebiusu(n[2]);
+  if (lgefint(n) == 3) return moebiusu(uel(n,2));
   p = mod4(n); if (!p) return 0;
   if (p == 2) { s = -1; n = shifti(n, -1); } else { s = 1; n = icopy(n); }
   setabssign(n);
@@ -3471,7 +3489,7 @@ core(GEN n)
   {
     case 2: return gen_0;
     case 3:
-      p = coreu(n[2]);
+      p = coreu(uel(n,2));
       return signe(n) > 0? utoipos(p): utoineg(p);
   }
 
@@ -3628,7 +3646,7 @@ ifactor_sign(GEN n, ulong all, long hint, long sn)
     av = avma;
     /* enough room to store <= 15 primes and exponents (OK if n < 2^64) */
     (void)new_chunk((15*3 + 15 + 1) * 2);
-    f = factoru(n[2]);
+    f = factoru_sign(uel(n,2), all, hint);
     avma = av;
     Pf = gel(f,1);
     Ef = gel(f,2);
diff --git a/src/basemath/lll.c b/src/basemath/lll.c
index 4c5f9f7..d9cd6b6 100644
--- a/src/basemath/lll.c
+++ b/src/basemath/lll.c
@@ -100,19 +100,24 @@ static long
 Babai(pari_sp av, long kappa, GEN *pG, GEN *pB, GEN *pU, GEN mu, GEN r, GEN s,
       long a, long zeros, long maxG, long n, GEN eta, GEN halfplus1, long prec)
 {
-  const pari_sp lim = stack_lim(av,2);
+  pari_sp av0 = avma;
   GEN B = *pB, G = *pG, U = *pU, tmp, rtmp, ztmp;
   long k, aa = (a > zeros)? a : zeros+1;
   GEN maxmu = gen_0, max2mu = gen_0;
   /* N.B: we set d = 0 (resp. n = 0) to avoid updating U (resp. B) */
   const long d = U ? lg(U)-1: 0;
 
+  if (gc_needed(av,2))
+  {
+    if(DEBUGMEM>1) pari_warn(warnmem,"Babai[0], a=%ld", aa);
+    gerepileall(av,U?3:2,&B,&G,&U);
+  }
   for (;;) {
     int go_on = 0;
     GEN max3mu;
     long i, j;
 
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av0,2))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"Babai[1], a=%ld", aa);
       gerepileall(av,U?5:4,&B,&G,&maxmu,&max2mu,&U);
@@ -157,7 +162,7 @@ Babai(pari_sp av, long kappa, GEN *pG, GEN *pB, GEN *pU, GEN mu, GEN r, GEN s,
       tmp = gmael(mu,kappa,j);
       if (absr_cmp(tmp, eta) <= 0) continue; /* (essentially) size-reduced */
 
-      if (low_stack(lim, stack_lim(av,2)))
+      if (gc_needed(av0,2))
       {
         if(DEBUGMEM>1) pari_warn(warnmem,"Babai[2], a=%ld, j=%ld", aa,j);
         gerepileall(av,U?5:4,&B,&G,&maxmu,&max2mu,&U);
@@ -339,6 +344,7 @@ fplll(GEN *ptrB, GEN *ptrU, GEN *ptrr, double DELTA, double ETA, long flag, long
   const long triangular = 0;
   pari_timer T;
   GEN B = *ptrB, U;
+  long cnt = 0;
 
   d = lg(B)-1;
   if (gram)
@@ -421,12 +427,8 @@ fplll(GEN *ptrB, GEN *ptrU, GEN *ptrr, double DELTA, double ETA, long flag, long
     }
     else
     { /* Step5: Find the right insertion index kappa, kappa2 = initial kappa */
-      if (DEBUGLEVEL>=10 && kappa==kappamax && signe(gel(s,kappa-1)))
-      {
-        long e = expo(divrr(mulrr(gmael(r,kappa-1,kappa-1), delta),
-                            gel(s,kappa-1)));
-        err_printf("(%ld) ", e);
-      }
+      if (DEBUGLEVEL>=4 && kappa==kappamax && signe(gel(s,kappa-1)))
+        if (++cnt > 20) { cnt = 0; err_printf("(%ld) ", expo(gel(s,1))); }
       kappa2 = kappa;
       do {
         kappa--;
@@ -504,19 +506,23 @@ GEN
 ZM_lll_norms(GEN x, double DELTA, long flag, GEN *B)
 {
   pari_sp ltop = avma;
+  const long compat = flag & LLL_COMPATIBLE;
   const double ETA = 0.51;
   long p, n = lg(x)-1;
   GEN U;
   if (n <= 1) return lll_trivial(x, flag);
   x = RgM_shallowcopy(x);
   U = (flag & LLL_INPLACE)? NULL: matid(n);
-  for (p = LOWDEFAULTPREC; ; incrprec(p))
+  for (p = compat? DEFAULTPREC: LOWDEFAULTPREC;;)
   {
     GEN m = fplll(&x, &U, B, DELTA, ETA, flag, p);
     if (m) return m;
+    if (compat)
+      p += DEFAULTPREC-2;
+    else
+      incrprec(p);
     gerepileall(ltop, U? 2: 1, &x, &U);
   }
-  return NULL; /* NOT REACHED */
 }
 
 /********************************************************************/
@@ -632,7 +638,7 @@ static GEN
 lllgramallgen(GEN x, long flag)
 {
   long lx = lg(x), i, j, k, l, n;
-  pari_sp av, lim;
+  pari_sp av;
   GEN B, L, h, fl;
   int flc;
 
@@ -641,7 +647,7 @@ lllgramallgen(GEN x, long flag)
 
   fl = cgetg(lx, t_VECSMALL);
 
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
   B = scalarcol_shallow(gen_1, lx);
   L = cgetg(lx,t_MAT);
   for (j=1; j<lx; j++) { gel(L,j) = zerocol(n); fl[j] = 0; }
@@ -660,7 +666,7 @@ lllgramallgen(GEN x, long flag)
         if (REDgen(k, l, h, L, gel(B,l+1))) flc = 1;
       if (++k > n) break;
     }
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"lllgramallgen");
       gerepileall(av,3,&B,&L,&h);
@@ -794,32 +800,32 @@ qflllgram0(GEN x, long flag)
 /**                   INTEGRAL KERNEL (LLL REDUCED)                **/
 /**                                                                **/
 /********************************************************************/
-/* Horribly slow (coeff explosion in small dimension): never use this */
 static GEN
-kerint1(GEN x)
+kerint0(GEN M)
 {
-  pari_sp av = avma;
-  return gerepilecopy(av, ZM_lll(QM_ImQ_hnf(ker(x)), LLLDFT, LLL_INPLACE));
+  GEN U, H = ZM_hnfall(M,&U,1);
+  long d = lg(M)-lg(H);
+  if (!d) return cgetg(1, t_MAT);
+  return ZM_lll(vecslice(U,1,d), LLLDFT, LLL_INPLACE);
 }
-/* Mostly useless: use ZM_lll(x, 0.99, LLL_KER) directly */
 GEN
-kerint(GEN x)
+kerint(GEN M)
 {
   pari_sp av = avma;
-  GEN h = ZM_lll(x, LLLDFT, LLL_KER);
-  if (lg(h)==1) { avma = av; return cgetg(1, t_MAT); }
-  return gerepilecopy(av, ZM_lll(h, LLLDFT, LLL_INPLACE));
+  return gerepilecopy(av, kerint0(M));
 }
-
+/* OBSOLETE: use kerint */
 GEN
-matkerint0(GEN x, long flag)
+matkerint0(GEN M, long flag)
 {
-  if (typ(x) != t_MAT) pari_err_TYPE("matkerint",x);
-  RgM_check_ZM(x, "kerint");
+  pari_sp av = avma;
+  if (typ(M) != t_MAT) pari_err_TYPE("matkerint",M);
+  M = Q_primpart(M);
+  RgM_check_ZM(M, "kerint");
   switch(flag)
   {
-    case 0: return kerint(x);
-    case 1: return kerint1(x);
+    case 0:
+    case 1: return gerepilecopy(av, kerint0(M));
     default: pari_err_FLAG("matkerint");
   }
   return NULL; /* not reached */
diff --git a/src/basemath/modsym.c b/src/basemath/modsym.c
new file mode 100644
index 0000000..ea8c732
--- /dev/null
+++ b/src/basemath/modsym.c
@@ -0,0 +1,2944 @@
+/* $Id$
+
+Copyright (C) 2011  The PARI group.
+
+This file is part of the PARI/GP package.
+
+PARI/GP 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. It is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY WHATSOEVER.
+
+Check the License for details. You should have received a copy of it, along
+with the package; see the file 'COPYING'. If not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "pari.h"
+#include "paripriv.h"
+
+/* Adapted from shp_package/moments by Robert Pollack
+ * http://www.math.mcgill.ca/darmon/programs/shp/shp.html */
+static GEN mskinit(ulong N, long k, long sign);
+static GEN mshecke_i(GEN W, ulong p);
+static GEN msnew_trivial(GEN W);
+static GEN mscuspidal_trivial(GEN W0);
+static GEN ZGl2Q_star(GEN v);
+static GEN getMorphism_trivial(GEN WW1, GEN WW2, GEN v);
+static GEN getMorphism(GEN W1, GEN W2, GEN v);
+static GEN voo_act_Gl2Q(GEN g, long k);
+static GEN mscuspidal_i(GEN W);
+
+/* Input: P^1(Z/NZ) (formed by create_p1mod)
+   Output: # P^1(Z/NZ) */
+static long
+p1_size(GEN p1N) { return lg(gel(p1N,1)) - 1; }
+static ulong
+p1N_get_N(GEN p1N) { return gel(p1N,3)[2]; }
+static GEN
+p1N_get_hash(GEN p1N) { return gel(p1N,2); }
+static GEN
+p1N_get_fa(GEN p1N) { return gel(p1N,4); }
+static GEN
+p1N_get_div(GEN p1N) { return gel(p1N,5); }
+/* ms-specific accessors */
+/* W = msinit or msfromell */
+static GEN
+get_ms(GEN W) { return lg(W) == 4? gel(W,1): W; }
+static GEN
+ms_get_p1N(GEN W) { W = get_ms(W); return gel(W,1); }
+static long
+ms_get_N(GEN W) { return p1N_get_N(ms_get_p1N(W)); }
+static GEN
+ms_get_hashcusps(GEN W) { W = get_ms(W); return gel(W,16); }
+static GEN
+ms_get_section(GEN W) { W = get_ms(W); return gel(W,12); }
+static GEN
+ms_get_genindex(GEN W) { W = get_ms(W); return gel(W,5); }
+static long
+ms_get_nbgen(GEN W) { return lg(ms_get_genindex(W))-1; }
+static long
+ms_get_nbE1(GEN W)
+{
+  GEN W11;
+  W = get_ms(W); W11 = gel(W,11);
+  return W11[4] - W11[3];
+}
+/* msk-specific accessors */
+static long
+msk_get_dim(GEN W) { return gmael(W,3,2)[2]; }
+static GEN
+msk_get_basis(GEN W) { return gmael(W,3,1); }
+static long
+msk_get_weight(GEN W) { return gmael(W,3,2)[1]; }
+static GEN
+msk_get_st(GEN W) { return gmael(W,3,3); }
+static GEN
+msk_get_link(GEN W) { return gmael(W,3,4); }
+static GEN
+msk_get_invphiblock(GEN W) { return gmael(W,3,5); }
+static long
+msk_get_sign(GEN W)
+{
+  GEN t = gel(W,2);
+  return typ(t)==t_INT? 0: itos(gel(t,1));
+}
+static GEN
+msk_get_star(GEN W) { return gmael(W,2,2); }
+static GEN
+msk_get_starproj(GEN W) { return gmael(W,2,3); }
+
+void
+checkms(GEN W)
+{
+  if (typ(W) != t_VEC || lg(W) != 4)
+    pari_err_TYPE("checkms [please apply msinit]", W);
+}
+
+/** MODULAR TO SYM **/
+
+/* q a t_FRAC or t_INT */
+static GEN
+Q_log_init(ulong N, GEN q)
+{
+  long l, n;
+  GEN Q;
+
+  q = gboundcf(q, 0);
+  l = lg(q);
+  Q = cgetg(l, t_VECSMALL);
+  Q[1] = 1;
+  for (n=2; n <l; n++) Q[n] = umodiu(gel(q,n), N);
+  for (n=3; n < l; n++)
+    Q[n] = Fl_add(Fl_mul(Q[n], Q[n-1], N), Q[n-2], N);
+  return Q;
+}
+
+/** INIT MODSYM STRUCTURE, WEIGHT 2 **/
+
+/* num = [Gamma : Gamma_0(N)] = N * Prod_{p|N} (1+p^-1) */
+static ulong
+count_Manin_symbols(ulong N, GEN P)
+{
+  long i, l = lg(P);
+  ulong num = N;
+  for (i = 1; i < l; i++) { ulong p = P[i]; num *= p+1; num /= p; }
+  return num;
+}
+/* returns the list of "Manin symbols" (c,d) in (Z/NZ)^2, (c,d,N) = 1
+ * generating H^1(X_0(N), Z) */
+static GEN
+generatemsymbols(ulong N, ulong num, GEN divN)
+{
+  GEN ret = cgetg(num+1, t_VEC);
+  ulong c, d, curn = 0;
+  long i, l;
+  /* generate Manin-symbols in two lists: */
+  /* list 1: (c:1) for 0 <= c < N */
+  for (c = 0; c < N; c++) gel(ret, ++curn) = mkvecsmall2(c, 1);
+  if (N == 1) return ret;
+  /* list 2: (c:d) with 1 <= c < N, c | N, 0 <= d < N, gcd(d,N) > 1, gcd(c,d)=1.
+   * Furthermore, d != d0 (mod N/c) with c,d0 already in the list */
+  l = lg(divN) - 1;
+  /* c = 1 first */
+  gel(ret, ++curn) = mkvecsmall2(1,0);
+  for (d = 2; d < N; d++)
+    if (ugcd(d,N) != 1UL)
+      gel(ret, ++curn) = mkvecsmall2(1,d);
+  /* omit c = 1 (first) and c = N (last) */
+  for (i=2; i < l; i++)
+  {
+    ulong Novc, d0;
+    c = divN[i];
+    Novc = N / c;
+    for (d0 = 2; d0 <= Novc; d0++)
+    {
+      ulong k, d = d0;
+      if (ugcd(d, Novc) == 1UL) continue;
+      for (k = 0; k < c; k++, d += Novc)
+        if (ugcd(c,d) == 1UL)
+        {
+          gel(ret, ++curn) = mkvecsmall2(c,d);
+          break;
+        }
+    }
+  }
+  if (curn != num) pari_err_BUG("generatemsymbols [wrong number of symbols]");
+  return ret;
+}
+
+#if OLD_HASH
+static ulong
+hash2(GEN H, long N, long a, long b)
+{ return ucoeff(H, smodss(a,N) + 1, smodss(b,N) + 1); }
+/* symbols from generatemsymbols(). Returns H such that
+ * H[ nc mod N, nd mod N ] = index of (c,d) in 'symbols', n < N, (n,N) = 1 */
+static GEN
+inithashmsymbols(ulong N, GEN symbols)
+{
+  GEN H = zero_Flm_copy(N, N);
+  long k, l = lg(symbols);
+  ulong n;
+  for (n = 1; n < N; n++)
+    if (ugcd(n,N) == 1)
+      for (k=1; k < l; k++)
+      {
+        GEN s = gel(symbols, k);
+        ucoeff(H, Fl_mul(s[1],n,N) + 1, Fl_mul(s[2],n,N) + 1) = k;
+      }
+  return H;
+}
+#else
+static GEN
+inithashmsymbols(ulong N, GEN symbols)
+{
+  GEN H = zerovec(N);
+  long k, l = lg(symbols);
+  /* skip the (c:1), 0 <= c < N and (1:0) */
+  for (k=N+2; k < l; k++)
+  {
+    GEN s = gel(symbols, k);
+    ulong c = s[1], d = s[2], Novc = N/c;
+    if (gel(H,c) == gen_0) gel(H,c) = const_vecsmall(Novc+1,0);
+    if (c != 1) { d %= Novc; if (!d) d = Novc; }
+    mael(H, c, d) = k;
+  }
+  return H;
+}
+#endif
+
+/** Helper functions for Sl2(Z) / Gamma_0(N) **/
+/* M a 2x2 ZM in SL2(Z) */
+static GEN
+SL2_inv(GEN M)
+{
+  GEN a=gcoeff(M,1,1), b=gcoeff(M,1,2), c=gcoeff(M,2,1), d=gcoeff(M,2,2);
+  return mkmat2(mkcol2(d, negi(c)), mkcol2(negi(b), a));
+}
+/* M a 2x2 zm in SL2(Z) */
+static GEN
+sl2_inv(GEN M)
+{
+  long a=coeff(M,1,1), b=coeff(M,1,2), c=coeff(M,2,1), d=coeff(M,2,2);
+  return mkmat2(mkvecsmall2(d, -c), mkvecsmall2(-b, a));
+}
+/* Return the zm [a,b; c,d] */
+static GEN
+mat2(long a, long b, long c, long d)
+{ return mkmat2(mkvecsmall2(a,c), mkvecsmall2(b,d)); }
+
+/* Input: a = 2-vector = path = {r/s,x/y}
+ * Output: either [r,x;s,y] or [-r,x;-s,y], whichever has determinant > 0 */
+static GEN
+path_to_zm(GEN a)
+{
+  GEN v = gel(a,1), w = gel(a,2);
+  long r = v[1], s = v[2], x = w[1], y = w[2];
+  if (cmpii(mulss(r,y), mulss(x,s)) < 0) { r = -r; s = -s; }
+  return mat2(r,x,s,y);
+}
+/* path from c1 to c2 */
+static GEN
+mkpath(GEN c1, GEN c2) { return mat2(c1[1], c2[1], c1[2], c2[2]); }
+static long
+cc(GEN M) { GEN v = gel(M,1); return v[2]; }
+static long
+dd(GEN M) { GEN v = gel(M,2); return v[2]; }
+
+/*Input: a,b = 2 paths, N = integer
+ *Output: 1 if the a,b are \Gamma_0(N)-equivalent; 0 otherwise */
+static int
+gamma_equiv(GEN a, GEN b, ulong N)
+{
+  pari_sp av = avma;
+  GEN m = path_to_zm(a);
+  GEN n = path_to_zm(b);
+  GEN d = subii(mulss(cc(m),dd(n)), mulss(dd(m),cc(n)));
+  ulong res = umodiu(d, N);
+  avma = av; return res == 0;
+}
+/* Input: a,b = 2 paths that are \Gamma_0(N)-equivalent, N = integer
+ * Output: M in \Gamma_0(N) such that Mb=a */
+static GEN
+gamma_equiv_matrix(GEN a, GEN b)
+{
+  GEN m = zm_to_ZM( path_to_zm(a) );
+  GEN n = zm_to_ZM( path_to_zm(b) );
+  return ZM_mul(m, SL2_inv(n));
+}
+
+/*************/
+/* P^1(Z/NZ) */
+/*************/
+
+/* Input: N = integer
+ * Output: creates P^1(Z/NZ) = [symbols, H, N]
+ *   symbols: list of vectors [x,y] that give a set of representatives
+ *            of P^1(Z/NZ)
+ *   H: an M by M grid whose value at the r,c-th place is the index of the
+ *      "standard representative" equivalent to [r,c] occuring in the first
+ *      list. If gcd(r,c,N) > 1 the grid has value 0. */
+static GEN
+create_p1mod(ulong N)
+{
+  GEN fa = factoru(N), div = divisorsu(N);
+  ulong nsym = count_Manin_symbols(N, gel(fa,1));
+  GEN symbols = generatemsymbols(N, nsym, div);
+  GEN H = inithashmsymbols(N,symbols);
+  return mkvec5(symbols, H, utoipos(N), fa, div);
+}
+
+/* result is known to be representable as an ulong */
+static ulong
+lcmuu(ulong a, ulong b) { ulong d = ugcd(a,b); return (a/d) * b; }
+/* a != 0 in Z/NZ. Return u in (Z/NZ)^* such that au = gcd(a, N) (mod N)*/
+static ulong
+Fl_inverse(ulong a, ulong N)
+{
+  pari_sp av;
+  ulong d, d0, d1, e, u = Fl_invgen(a, N, &d);
+  if (d == 1) return u;
+  e = N/d;
+  d0 = ucoprime_part(d, e); /* d = d0 d1, d0 coprime to N/d, core(d1) | N/d */
+  if (d0 == 1) return u;
+  av = avma;
+  d1 = d / d0;
+  e = lcmuu(e, d1);
+  u = itou(Z_chinese_coprime(utoipos(u), gen_1,
+                             utoipos(e), utoipos(d0), utoipos(e*d0)));
+  avma = av; return u;
+}
+/* Let (c : d) in P1(Z/NZ).
+ * If c = 0 return (0:1). If d = 0 return (1:0).
+ * Else replace by (cu : du), where u in (Z/NZ)^* such that C := cu = gcd(c,N).
+ * In create_p1mod(), (c : d) is represented by (C:D) where D = du (mod N/c)
+ * is smallest such that gcd(C,D) = 1. Return (C : du mod N/c), which need
+ * not belong to P1(Z/NZ) ! A second component du mod N/c = 0 is replaced by
+ * N/c in this case to avoid problems with array indices */
+static GEN
+p1_std_form(long c, long d, ulong N)
+{
+  ulong u;
+  c = smodss(c, N);
+  d = smodss(d, N);
+  if (!c) return mkvecsmall2(0, 1);
+  if (!d) return mkvecsmall2(1, 0);
+  u = Fl_invsafe(d, N);
+  if (u != 0) return mkvecsmall2(Fl_mul(c,u,N), 1); /* (d,N) = 1 */
+
+  u = Fl_inverse(c, N);
+  if (u > 1) { c = Fl_mul(c,u,N); d = Fl_mul(d,u,N); }
+  /* c | N */
+  if (c != 1) d = d % (N/c);
+  if (!d) d = N/c;
+  return mkvecsmall2(c, d);
+}
+
+/* Input: v = [x,y] = elt of P^1(Z/NZ) = class in Gamma_0(N) \ PSL2(Z)
+ * Output: returns the index of the standard rep equivalent to v */
+static long
+p1_index(long x, long y, GEN p1N)
+{
+  ulong N = p1N_get_N(p1N);
+  GEN H = p1N_get_hash(p1N), c;
+
+#ifdef OLD_HASH
+  return hash2(p1N_get_hash(p1N), N, x, y);
+#else
+  c = p1_std_form(x, y, N);
+  x = c[1];
+  y = c[2];
+  if (y == 1) return x+1;
+  if (y == 0) return N+1;
+  if (mael(H,x,y) == 0) pari_err_BUG("p1_index");
+  return mael(H,x,y);
+#endif
+}
+
+/* Cusps for \Gamma_0(N) */
+
+/* \sum_{d | N} \phi(gcd(d, N/d)), using multiplicativity. fa = factor(N) */
+static ulong
+nbcusp(GEN fa)
+{
+  GEN P = gel(fa,1), E = gel(fa,2);
+  long i, l = lg(P);
+  ulong T = 1;
+  for (i = 1; i < l; i++)
+  {
+    long e = E[i] >> 1; /* floor(E[i] / 2) */
+    ulong p = P[i];
+    if (odd(E[i]))
+      T *= 2 * upowuu(p, e);
+    else
+      T *= (p+1) * upowuu(p, e - 1);
+  }
+  return T;
+}
+
+/* to each cusp in \Gamma_0(N) P1(Q), represented by p/q, we associate a
+ * unique index. Canonical representative: (1:0) or (p:q) with q | N, q < N,
+ * p defined modulo d := gcd(N/q,q), (p,d) = 1.
+ * Return [[N, nbcusps], H, cusps]*/
+static GEN
+inithashcusps(GEN p1N)
+{
+  ulong N = p1N_get_N(p1N);
+  GEN div = p1N_get_div(p1N), H = zerovec(N+1);
+  long k, ind, l = lg(div), ncusp = nbcusp(p1N_get_fa(p1N));
+  GEN cusps = cgetg(ncusp+1, t_VEC);
+
+  gel(H,1) = mkvecsmall2(0/*empty*/, 1/* first cusp: (1:0) */);
+  gel(cusps, 1) = mkvecsmall2(1,0);
+  ind = 2;
+  for (k=1; k < l-1; k++) /* l-1: remove q = N */
+  {
+    ulong p, q = div[k], d = ugcd(q, N/q);
+    GEN h = const_vecsmall(d+1,0);
+    gel(H,q+1) = h ;
+    for (p = 0; p < d; p++)
+      if (ugcd(p,d) == 1)
+      {
+        h[p+1] = ind;
+        gel(cusps, ind) = mkvecsmall2(p,q);
+        ind++;
+      }
+  }
+  return mkvec3(mkvecsmall2(N,ind-1), H, cusps);
+}
+/* c = [p,q], (p,q) = 1, return a canonical representative for
+ * \Gamma_0(N)(p/q) */
+static GEN
+cusp_std_form(GEN c, GEN S)
+{
+  long p, N = gel(S,1)[1], q = smodss(c[2], N);
+  ulong u, d;
+  if (q == 0) return mkvecsmall2(1, 0);
+  p = smodss(c[1], N);
+  u = Fl_inverse(q, N);
+  q = Fl_mul(q,u, N);
+  d = ugcd(q, N/q);
+  return mkvecsmall2(Fl_div(p % d,u % d, d), q);
+}
+/* c = [p,q], (p,q) = 1, return the index of the corresponding cusp.
+ * S from inithashcusps */
+static ulong
+cusp_index(GEN c, GEN S)
+{
+  long p, q;
+  GEN H = gel(S,2);
+  c = cusp_std_form(c, S);
+  p = c[1]; q = c[2];
+  if (!mael(H,q+1,p+1)) pari_err_BUG("cusp_index");
+  return mael(H,q+1,p+1);
+}
+
+/* M a square invertible ZM, return a ZM iM such that iM M = M iM = d.Id */
+static GEN
+ZM_inv_denom(GEN M)
+{
+  GEN ciM = ZM_det(M);
+  GEN c, iM = Q_primitive_part(ZM_inv(M, ciM), &c);
+  if (c) ciM = diviiexact(ciM, c);
+  return mkvec2(iM, ciM);
+}
+/* return M^(-1) v, dinv = ZM_inv_denom(M) OR Qevproj_init(M) */
+static GEN
+ZC_apply_dinv(GEN dinv, GEN v)
+{
+  GEN x, c, iM;
+  if (lg(dinv) == 3)
+  {
+    iM = gel(dinv,1);
+    c = gel(dinv,2);
+  }
+  else
+  { /* Qevproj_init */
+    iM = gel(dinv,2);
+    c = gel(dinv,3);
+    v = typ(v) == t_MAT? rowpermute(v, gel(dinv,4))
+                       : vecpermute(v, gel(dinv,4));
+  }
+  x = RgM_RgC_mul(iM, v);
+  if (!isint1(c)) x = RgC_Rg_div(x, c);
+  return x;
+}
+
+/* M an n x d ZM of rank d (basis of a Q-subspace), n >= d.
+ * Initialize a projector on M */
+GEN
+Qevproj_init(GEN M)
+{
+  GEN v, perm, MM, dinv, iM, ciM;
+  v = ZM_indexrank(M); perm = gel(v,1);
+  MM = rowpermute(M, perm); /* square invertible */
+  dinv = ZM_inv_denom(MM);
+  iM = gel(dinv,1);
+  ciM= gel(dinv,2);
+  return mkvec4(M, iM, ciM, perm);
+}
+/* same with typechecks */
+static GEN
+Qevproj_init0(GEN M)
+{
+  switch(typ(M))
+  {
+    case t_VEC:
+      if (lg(M) == 5) return M;
+      break;
+    case t_MAT:
+      M = Q_primpart(M);
+      RgM_check_ZM(M,"Qevproj_init");
+      return Qevproj_init(M);
+  }
+  pari_err_TYPE("Qevproj_init",M);
+  return NULL;
+}
+
+/* T an n x n QM, stabilizing d-dimensional Q-vector space spanned by the
+ * columns of M, pro = Qevproj_init(M). Return d x d matrix of T acting
+ * on M */
+GEN
+Qevproj_apply(GEN T, GEN pro)
+{
+  GEN M = gel(pro,1), iM = gel(pro,2), ciM = gel(pro,3), perm = gel(pro,4);
+  return RgM_Rg_div(RgM_mul(iM, RgM_mul(rowpermute(T,perm), M)), ciM);
+}
+/* Qevproj_apply(T,pro)[,k] */
+GEN
+Qevproj_apply_vecei(GEN T, GEN pro, long k)
+{
+  GEN M = gel(pro,1), iM = gel(pro,2), ciM = gel(pro,3), perm = gel(pro,4);
+  GEN v = RgM_RgC_mul(iM, RgM_RgC_mul(rowpermute(T,perm), gel(M,k)));
+  return RgC_Rg_div(v, ciM);
+}
+
+/* normalize a Q-basis*/
+static GEN
+Q_primpart_basis(GEN M)
+{
+  long i, l;
+  GEN N = cgetg_copy(M, &l);
+  for (i = 1; i < l; i++) gel(N,i) = Q_primpart(gel(M,i));
+  return N;
+}
+static GEN
+ZM_ker(GEN M) { return Q_primpart_basis(keri(M)); }
+static GEN
+QM_ker(GEN M) { return ZM_ker(Q_primpart(M)); }
+static GEN
+QM_image(GEN A)
+{
+  A = Q_primpart_basis(A);
+  return vecpermute(A, ZM_indeximage(A));
+}
+
+static int
+cmp_dim(void *E, GEN a, GEN b)
+{
+  long k;
+  (void)E;
+  a = gel(a,1);
+  b = gel(b,1); k = lg(a)-lg(b);
+  return k? ((k > 0)? 1: -1): 0;
+}
+
+/* Decompose the subspace H (Qevproj format) in simple subspaces.
+ * Eg for H = msnew */
+static GEN
+mssplit_i(GEN W, GEN H)
+{
+  ulong p, N = ms_get_N(W);
+  long first, dim;
+  forprime_t S;
+  GEN T1 = NULL, T2 = NULL, V;
+  dim = lg(gel(H,1))-1;
+  V = vectrunc_init(dim+1);
+  if (!dim) return V;
+  (void)u_forprime_init(&S, 2, ULONG_MAX);
+  vectrunc_append(V, H);
+  first = 1; /* V[1..first-1] contains simple subspaces */
+  while ((p = u_forprime_next(&S)))
+  {
+    GEN T;
+    long n, j, lV;
+    if (N % p == 0) continue;
+    if (T1 && T2)
+    {
+      T = RgM_add(T1,T2);
+      T2 = NULL;
+    }
+    else
+    {
+      T2 = T1;
+      T1 = T = mshecke_i(W, p);
+    }
+    lV = lg(V);
+    for (j = first; j < lV; j++)
+    {
+      pari_sp av = avma;
+      GEN Vj = gel(V,j), P = gel(Vj,1);
+      GEN TVj = Qevproj_apply(T, Vj); /* c T | V_j */
+      GEN ch = QM_charpoly_ZX(TVj), fa = ZX_factor(ch), F, E;
+      long k;
+      F = gel(fa, 1);
+      E = gel(fa, 2);
+      n = lg(F)-1;
+      if (n == 1)
+      {
+        if (isint1(gel(E,1)))
+        { /* simple subspace */
+          swap(gel(V,first), gel(V,j));
+          first++;
+        }
+        else
+          avma = av;
+      }
+      else
+      { /* can split Vj */
+        GEN pows;
+        long D = 1;
+        for (k = 1; k <= n; k++)
+        {
+          long d = degpol(gel(F,k));
+          if (d > D) D = d;
+        }
+        /* remove V[j] */
+        swap(gel(V,j), gel(V,lg(V)-1)); setlg(V, lg(V)-1);
+        pows = RgM_powers(TVj, minss((long)2*sqrt(D), D));
+        for (k = 1; k <= n; k++)
+        {
+          GEN f = gel(F,k);
+          GEN M = RgX_RgMV_eval(f, pows); /* f(TVj) */
+          GEN K = QM_ker(M);
+          GEN p = Q_primpart( RgM_mul(P, K) );
+          vectrunc_append(V, Qevproj_init(p));
+          if (lg(K) == 2 || isint1(gel(E,k)))
+          { /* simple subspace */
+            swap(gel(V,first), gel(V, lg(V)-1));
+            first++;
+          }
+        }
+        if (j < first) j = first;
+      }
+    }
+    if (first >= lg(V)) {
+      gen_sort_inplace(V, NULL, cmp_dim, NULL);
+      return V;
+    }
+  }
+  pari_err_BUG("subspaces not found");
+  return NULL;
+}
+GEN
+mssplit(GEN W, GEN H)
+{
+  pari_sp av = avma;
+  checkms(W);
+  if (!msk_get_sign(W))
+    pari_err_DOMAIN("mssplit","abs(sign)","!=",gen_1,gen_0);
+  H = Qevproj_init0(H);
+  return gerepilecopy(av, mssplit_i(W,H));
+}
+
+/* proV = Qevproj_init of a Hecke simple subspace, return [ a_n, n <= B ] */
+static GEN
+msqexpansion_i(GEN W, GEN proV, ulong B)
+{
+  ulong p, N = ms_get_N(W), sqrtB;
+  long i, d, k = msk_get_weight(W);
+  forprime_t S;
+  GEN T1=NULL, T2=NULL, TV=NULL, ch=NULL, v, dTiv, Tiv, dinv, ciM, iM, L;
+  switch(B)
+  {
+    case 0: return cgetg(1,t_VEC);
+    case 1: return mkvec(gen_1);
+  }
+  (void)u_forprime_init(&S, 2, ULONG_MAX);
+  while ((p = u_forprime_next(&S)))
+  {
+    GEN T;
+    if (N % p == 0) continue;
+    if (T1 && T2)
+    {
+      T = RgM_add(T1,T2);
+      T2 = NULL;
+    }
+    else
+    {
+      T2 = T1;
+      T1 = T = mshecke_i(W, p);
+    }
+    TV = Qevproj_apply(T, proV); /* T | V */
+    ch = QM_charpoly_ZX(TV);
+    if (ZX_is_irred(ch)) break;
+    ch = NULL;
+  }
+  if (!ch) pari_err_BUG("q-Expansion not found");
+  /* T generates the Hecke algebra */
+  d = degpol(ch);
+  v = vec_ei(d, 1); /* take v = e_1 */
+  Tiv = cgetg(d+1, t_MAT); /* Tiv[i] = T^(i-1)v */
+  gel(Tiv, 1) = v;
+  for (i = 2; i <= d; i++) gel(Tiv, i) = RgM_RgC_mul(TV, gel(Tiv,i-1));
+  Tiv = Q_remove_denom(Tiv, &dTiv);
+  dinv = ZM_inv_denom(Tiv);
+  iM = gel(dinv,1);
+  ciM = gel(dinv,2);
+  if (dTiv) ciM = gdiv(ciM, dTiv);
+  L = const_vec(B,NULL);
+  sqrtB = (ulong)sqrt(B);
+  gel(L,1) = d > 1? mkpolmod(gen_1,ch): gen_1;
+  for (p = 2; p <= B; p++)
+  {
+    pari_sp av = avma;
+    GEN T, u, Tv, ap, P;
+    ulong m;
+    if (gel(L,p)) continue;  /* p not prime */
+    T = mshecke_i(W, p);
+    Tv = Qevproj_apply_vecei(T, proV, 1); /* Tp.v */
+    /* Write Tp.v = \sum u_i T^i v */
+    u = RgC_Rg_div(RgM_RgC_mul(iM, Tv), ciM);
+    ap = gerepilecopy(av, RgV_to_RgX(u, 0));
+    if (d > 1)
+      ap = mkpolmod(ap,ch);
+    else
+      ap = simplify_shallow(ap);
+    gel(L,p) = ap;
+    if (!(N % p))
+    { /* p divides the level */
+      ulong C = B/p;
+      for (m=1; m<=C; m++)
+        if (gel(L,m)) gel(L,m*p) = gmul(gel(L,m), ap);
+      continue;
+    }
+    P = powuu(p,k-1);
+    if (p <= sqrtB) {
+      ulong pj, oldpj = 1;
+      for (pj = p; pj <= B; oldpj=pj, pj *= p)
+      {
+        GEN apj = (pj==p)? ap
+                         : gsub(gmul(ap,gel(L,oldpj)), gmul(P,gel(L,oldpj/p)));
+        gel(L,pj) = apj;
+        for (m = B/pj; m > 1; m--)
+          if (gel(L,m) && m%p) gel(L,m*pj) = gmul(gel(L,m), apj);
+      }
+    } else {
+      gel(L,p) = ap;
+      for (m = B/p; m > 1; m--)
+        if (gel(L,m)) gel(L,m*p) = gmul(gel(L,m), ap);
+    }
+  }
+  return L;
+}
+GEN
+msqexpansion(GEN W, GEN proV, ulong B)
+{
+  pari_sp av = avma;
+  checkms(W);
+  proV = Qevproj_init0(proV);
+  return gerepilecopy(av, msqexpansion_i(W,proV,B));
+}
+
+static GEN
+Qevproj_star(GEN W, GEN H)
+{
+  long s = msk_get_sign(W);
+  if (s)
+  { /* project on +/- component */
+    GEN star = msk_get_star(W);
+    GEN A = gmul(star, H);
+    A = (s > 0)? gadd(A, H): gsub(A, H);
+    /* Im(star + sign) = Ker(star - sign) */
+    H = QM_image(A);
+  }
+  return H;
+}
+static GEN
+msnew_trivial(GEN W)
+{
+  GEN p1N = ms_get_p1N(W), P = gel(p1N_get_fa(p1N), 1);
+  ulong N = ms_get_N(W);
+  long i, nP = lg(P)-1;
+  GEN Snew, K, v;
+
+  K = mscuspidal_trivial(W);
+  if (uisprime(N)) { Snew = K; goto END; }
+  v = cgetg(2*nP + 1, t_COL);
+  for (i = 1; i <= nP; i++)
+  {
+    pari_sp av = avma, av2;
+    ulong M = N / P[i];
+    GEN T1, Td, Wi = mskinit(M, 2, 0);
+    T1 = getMorphism_trivial(W, Wi, mat2(1,0,0,1));
+    Td = getMorphism_trivial(W, Wi, mat2(P[i],0,0,1));
+    av2 = avma;
+    T1 = ZM_mul(T1, K); /* multiply by K = restrict to Ker delta */
+    Td = ZM_mul(Td, K);
+    gerepileallsp(av, av2, 2, &T1,&Td);
+    gel(v,2*i-1)= T1;
+    gel(v,2*i)  = Td;
+  }
+  Snew = ZM_mul(K, ZM_ker(matconcat(v)));
+END:
+  return Qevproj_star(W, Snew);
+}
+
+static GEN
+msnew_i(GEN W)
+{
+  GEN p1N = ms_get_p1N(W), P = gel(p1N_get_fa(p1N), 1);
+  ulong p, N = ms_get_N(W);
+  long i, nP = lg(P)-1, k = msk_get_weight(W);
+  GEN S, Snew, Sold, pr_S, pr_Sold, v;
+  forprime_t F;
+  if (k == 2) return msnew_trivial(W);
+  S = gel(mscuspidal_i(W), 2);
+  if (uisprime(N)) { Snew = S; goto END; }
+  v = cgetg(2*nP + 1, t_VEC);
+  for (i = 1; i <= nP; i++)
+  {
+    GEN Wi = mskinit(N/P[i], k, 0);
+    gel(v,2*i-1) = getMorphism(Wi, W, mat2(1,0,0,1));
+    gel(v,2*i)   = getMorphism(Wi, W, mat2(P[i],0,0,1));
+  }
+  v = QM_image(matconcat(v)); /* old forms */
+  /* restrict to cuspidal subspace */
+  Sold = Q_primpart_basis(intersect(S, v));
+  pr_S = Qevproj_init(S);
+  pr_Sold = Qevproj_init(Sold);
+  Snew = NULL;
+  (void)u_forprime_init(&F, 2, ULONG_MAX);
+  while ((p = u_forprime_next(&F)))
+  {
+    pari_sp av = avma;
+    GEN T, chS, chSold, chSnew;
+    if (N % p == 0) continue;
+    T = mshecke_i(W, p);
+    chS = QM_charpoly_ZX(Qevproj_apply(T, pr_S));
+    chSold = QM_charpoly_ZX(Qevproj_apply(T, pr_Sold));
+    chSnew = RgX_div(chS, chSold); /* = char T | S^new */
+    if (!degpol( ZX_gcd(chSnew, chSold) ))
+    {
+      GEN M = RgX_RgM_eval(chSnew, T);
+      Snew = QM_ker(M);
+      break;
+    }
+    avma = av;
+  }
+END:
+  return Qevproj_star(W, Snew);
+}
+GEN
+msnew(GEN W)
+{
+  pari_sp av = avma;
+  checkms(W);
+  return gerepilecopy(av, Qevproj_init( msnew_i(W)) );
+}
+
+/* Solve the Manin relations for a congruence subgroup \Gamma by constructing
+ * a well-formed fundamental domain for the action of \Gamma on upper half
+ * space. See
+ * Pollack and Stevens, Overconvergent modular symbols and p-adic L-functions
+ * Annales scientifiques de l'ENS 44, fascicule 1 (2011), 1-42
+ * http://math.bu.edu/people/rpollack/Papers/Overconvergent_modular_symbols_and_padic_Lfunctions.pdf
+ *
+ * FIXME: Implemented for \Gamma = \Gamma_0(N) only. */
+
+#if 0 /* Pollack-Stevens shift their paths so as to solve equations of the
+         form f(z+1) - f(z) = g. We don't (to avoid mistakes) so we will
+         have to solve eqs of the form f(z-1) - f(z) = g */
+/* c = a/b; as a t_VECSMALL [a,b]; return c-1 as a t_VECSMALL */
+static GEN
+Shift_left_cusp(GEN c) { long a=c[1], b=c[2]; return mkvecsmall2(a - b, b); }
+/* c = a/b; as a t_VECSMALL [a,b]; return c+1 as a t_VECSMALL */
+static GEN
+Shift_right_cusp(GEN c) { long a=c[1], b=c[2]; return mkvecsmall2(a + b, b); }
+/*Input: path = [r,s] (thought of as a geodesic between these points)
+ *Output: The path shifted by one to the left, i.e. [r-1,s-1] */
+static GEN
+Shift_left(GEN path)
+{
+  GEN r = gel(path,1), s = gel(path,2);
+  return mkvec2(Shift_left_cusp(r), Shift_left_cusp(s)); }
+/*Input: path = [r,s] (thought of as a geodesic between these points)
+ *Output: The path shifted by one to the right, i.e. [r+1,s+1] */
+GEN
+Shift_right(GEN path)
+{
+  GEN r = gel(path,1), s = gel(path,2);
+  return mkvec2(Shift_right_cusp(r), Shift_right_cusp(s)); }
+#endif
+
+/* linked lists */
+typedef struct list_t { GEN data; struct list_t *next; } list_t;
+static list_t *
+list_new(GEN x)
+{
+  list_t *L = (list_t*)stack_malloc(sizeof(list_t));
+  L->data = x;
+  L->next = NULL; return L;
+}
+static void
+list_insert(list_t *L, GEN x)
+{
+  list_t *l = list_new(x);
+  l->next = L->next;
+  L->next = l;
+}
+
+/*Input: N > 1, p1N = P^1(Z/NZ)
+ *Output: a connected fundamental domain for the action of \Gamma_0(N) on
+ *  upper half space.  When \Gamma_0(N) is torsion free, the domain has the
+ *  property that all of its vertices are cusps.  When \Gamma_0(N) has
+ *  three-torsion, 2 extra triangles need to be added.
+ *
+ * The domain is constructed by beginning with the triangle with vertices 0,1
+ * and oo.  Each adjacent triangle is successively tested to see if it contains
+ * points not \Gamma_0(N) equivalent to some point in our region.  If a
+ * triangle contains new points, it is added to the region.  This process is
+ * continued until the region can no longer be extended (and still be a
+ * fundamental domain) by added an adjacent triangle.  The list of cusps
+ * between 0 and 1 are then returned
+ *
+ * Precisely, the function returns a list such that the elements of the list
+ * with odd index are the cusps in increasing order.  The even elements of the
+ * list are either an "x" or a "t".  A "t" represents that there is an element
+ * of order three such that its fixed point is in the triangle directly
+ * adjacent to the our region with vertices given by the cusp before and after
+ * the "t".  The "x" represents that this is not the case. */
+enum { type_X, type_DO /* ? */, type_T };
+static GEN
+form_list_of_cusps(ulong N, GEN p1N)
+{
+  pari_sp av = avma;
+  long i, position, nbC = 2;
+  GEN v, L;
+  list_t *C, *c;
+  /* Let t be the index of a class in PSL2(Z) / \Gamma in our fixed enumeration
+   * v[t] != 0 iff it is the class of z tau^r for z a previous alpha_i
+   * or beta_i.
+   * For \Gamma = \Gamma_0(N), the enumeration is given by p1_index.
+   * We write cl(gamma) = the class of gamma mod \Gamma */
+  v = const_vecsmall(p1_size(p1N), 0);
+  i = p1_index( 0, 1, p1N); v[i] = 1;
+  i = p1_index( 1,-1, p1N); v[i] = 2;
+  i = p1_index(-1, 0, p1N); v[i] = 3;
+  /* the value is unused [debugging]: what matters is whether it is != 0 */
+  position = 4;
+  /* at this point, Fund = R, v contains the classes of Id, tau, tau^2 */
+
+  C  = list_new(mkvecsmall3(0,1, type_X));
+  list_insert(C, mkvecsmall3(1,1,type_DO));
+  /* C is a list of triples[a,b,t], where c = a/b is a cusp, and t is the type
+   * of the path between c and the PREVIOUS cusp in the list, coded as
+   *   type_DO = "?", type_X = "x", type_T = "t"
+   * Initially, C = [0/1,"?",1/1]; */
+
+  /* loop through the current set of cusps C and check to see if more cusps
+   * should be added */
+  for (;;)
+  {
+    int done = 1;
+    for (c = C; c; c = c->next)
+    {
+      GEN cusp1, cusp2, gam;
+      long pos, b1, b2, b;
+
+      if (!c->next) break;
+      cusp1 = c->data; /* = a1/b1 */
+      cusp2 = (c->next)->data; /* = a2/b2 */
+      if (cusp2[3] != type_DO) continue;
+
+      /* gam (oo -> 0) = (cusp2 -> cusp1), gam in PSL2(Z) */
+      gam = path_to_zm(mkpath(cusp2, cusp1)); /* = [a2,a1;b2,b1] */
+      /* we have normalized the cusp representation so that a1 b2 - a2 b1 = 1 */
+      b1 = coeff(gam,2,1); b2 = coeff(gam,2,2);
+      /* gam.1  = (a1 + a2) / (b1 + b2) */
+      b = b1 + b2;
+      /* Determine whether the adjacent triangle *below* (cusp1->cusp2)
+       * should be added */
+      pos = p1_index(b1,b2, p1N); /* did we see cl(gam) before ? */
+      if (v[pos])
+        cusp2[3] = type_X; /* NO */
+      else
+      { /* YES */
+        ulong B1, B2;
+        v[pos] = position;
+        i = p1_index(-(b1+b2), b1, p1N); v[i] = position+1;
+        i = p1_index(b2, -(b1+b2), p1N); v[i] = position+2;
+        /* add cl(gam), cl(gam*TAU), cl(gam*TAU^2) to v */
+        position += 3;
+        /* gam tau gam^(-1) in \Gamma ? */
+        B1 = smodss(b1, N);
+        B2 = smodss(b2, N);
+        if ((Fl_sqr(B2,N) + Fl_sqr(B1,N) + Fl_mul(B1,B2,N)) % N == 0)
+          cusp2[3] = type_T;
+        else
+        {
+          long a1 = coeff(gam, 1,1), a2 = coeff(gam, 1,2);
+          long a = a1 + a2; /* gcd(a,b) = 1 */
+          list_insert(c, mkvecsmall3(a,b,type_DO));
+          c = c->next;
+          nbC++;
+          done = 0;
+        }
+      }
+    }
+    if (done) break;
+  }
+  L = cgetg(nbC+1, t_VEC); i = 1;
+  for (c = C; c; c = c->next) gel(L,i++) = c->data;
+  return gerepilecopy(av, L);
+}
+
+/* M in PSL2(Z). Return index of M in P1^(Z/NZ) = Gamma0(N) \ PSL2(Z),
+ * and M0 in Gamma_0(N) such that M = M0 * M', where M' = chosen
+ * section( PSL2(Z) -> P1^(Z/NZ) ). */
+static GEN
+Gamma0N_decompose(GEN W, GEN M, long *index)
+{
+  GEN p1N = gel(W,1), W3 = gel(W,3), section = ms_get_section(W);
+  GEN A;
+  ulong N = p1N_get_N(p1N);
+  ulong c = umodiu(gcoeff(M,2,1), N);
+  ulong d = umodiu(gcoeff(M,2,2), N);
+  long s, ind = p1_index(c, d, p1N); /* as an elt of P1(Z/NZ) */
+  *index = W3[ind]; /* as an elt of F, E2, ... */
+  M = ZM_zm_mul(M, sl2_inv(gel(section,ind)));
+  /* normalize mod +/-Id */
+  A = gcoeff(M,1,1);
+  s = signe(A);
+  if (s < 0)
+    M = ZM_neg(M);
+  else if (!s)
+  {
+    GEN C = gcoeff(M,2,1);
+    if (signe(C) < 0) M = ZM_neg(M);
+  }
+  return M;
+}
+/* same for a path. Return [[ind], M] */
+static GEN
+path_Gamma0N_decompose(GEN W, GEN path)
+{
+  GEN p1N = gel(W,1);
+  GEN p1index_to_ind = gel(W,3);
+  GEN section = ms_get_section(W);
+  GEN M = path_to_zm(path);
+  long p1index = p1_index(cc(M), dd(M), p1N);
+  long ind = p1index_to_ind[p1index];
+  GEN M0 = ZM_zm_mul(zm_to_ZM(M), sl2_inv(gel(section,p1index)));
+  return mkvec2(mkvecsmall(ind), M0);
+}
+
+/*Form generators of H_1(X_0(N),{cusps},Z)
+*
+*Input: N = integer > 1, p1N = P^1(Z/NZ)
+*Output: [cusp_list,E,F,T2,T3,E1] where
+*  cusps_list = list of cusps describing fundamental domain of
+*    \Gamma_0(N).
+*  E = list of paths in the boundary of the fundamental domains and oriented
+*    clockwise such that they do not contain a point
+*    fixed by an element of order 2 and they are not an edge of a
+*    triangle containing a fixed point of an element of order 3
+*  F = list of paths in the interior of the domain with each
+*    orientation appearing separately
+* T2 = list of paths in the boundary of domain containing a point fixed
+*    by an element of order 2 (oriented clockwise)
+* T3 = list of paths in the boundard of domain which are the edges of
+*    some triangle containing a fixed point of a matrix of order 3 (both
+*    orientations appear)
+* E1 = a sublist of E such that every path in E is \Gamma_0(N)-equivalent to
+*    either an element of E1 or the flip (reversed orientation) of an element
+*    of E1.
+* (Elements of T2 are \Gamma_0(N)-equivalent to their own flip.)
+*
+* sec = a list from 1..#p1N of matrices describing a section of the map
+*   SL_2(Z) to P^1(Z/NZ) given by [a,b;c,d]-->[c,d].
+*   Given our fixed enumeration of P^1(Z/NZ), the j-th element of the list
+*   represents the image of the j-th element of P^1(Z/NZ) under the section. */
+
+/* insert path in set T */
+static void
+set_insert(hashtable *T, GEN path)
+{ hash_insert(T, path,  (void*)(T->nb + 1)); }
+
+static GEN
+hash_to_vec(hashtable *h)
+{
+  GEN v = cgetg(h->nb + 1, t_VEC);
+  ulong i;
+  for (i = 0; i < h->len; i++)
+  {
+    hashentry *e = h->table[i];
+    while (e)
+    {
+      GEN key = (GEN)e->key;
+      long index = (long)e->val;
+      gel(v, index) = key;
+      e = e->next;
+    }
+  }
+  return v;
+}
+
+static long
+path_to_p1_index(GEN path, GEN p1N)
+{
+  GEN M = path_to_zm(path);
+  return p1_index(cc(M), dd(M), p1N);
+}
+
+/* Pollack-Stevens sets */
+typedef struct PS_sets_t {
+  hashtable *F, *T2, *T31, *T32, *E1, *E2;
+  GEN E2_in_terms_of_E1, stdE1;
+} PS_sets_t;
+
+static hashtable *
+set_init(long max)
+{ return hash_create(max, (ulong(*)(void*))&hash_GEN,
+                          (int(*)(void*,void*))&gidentical, 1); }
+static void
+insert_E(GEN path, PS_sets_t *S, GEN p1N)
+{
+  GEN rev = vecreverse(path);
+  long std = path_to_p1_index(rev, p1N);
+  GEN v = gel(S->stdE1, std);
+  if (v)
+  { /* [s, p1], where E1[s] = the path p1 \equiv vecreverse(path) mod \Gamma */
+    GEN gamma, p1 = gel(v,2);
+    long r, s = itos(gel(v,1));
+
+    set_insert(S->E2, path);
+    r = S->E2->nb;
+    if (gel(S->E2_in_terms_of_E1, r) != gen_0) pari_err_BUG("insert_E");
+
+    gamma = gamma_equiv_matrix(rev, p1);
+    /* E2[r] + gamma * E1[s] = 0 */
+    gel(S->E2_in_terms_of_E1, r) = mkvec2(utoipos(s),
+                                          to_famat_shallow(gamma,gen_m1));
+  }
+  else
+  {
+    set_insert(S->E1, path);
+    std = path_to_p1_index(path, p1N);
+    gel(S->stdE1, std) = mkvec2(utoipos(S->E1->nb), path);
+  }
+}
+
+static GEN
+cusp_infinity() { return mkvecsmall2(1,0); }
+
+static void
+form_E_F_T(ulong N, GEN p1N, GEN *pC, PS_sets_t *S)
+{
+  GEN C, cusp_list = form_list_of_cusps(N, p1N);
+  long nbgen = lg(cusp_list)-1, nbmanin = p1_size(p1N), r, s, i;
+  hashtable *F, *T2, *T31, *T32, *E1, *E2;
+
+  *pC = C = cgetg(nbgen+1, t_VEC);
+  for (i = 1; i <= nbgen; i++)
+  {
+    GEN c = gel(cusp_list,i);
+    gel(C,i) = mkvecsmall2(c[1], c[2]);
+  }
+  S->F  = F  = set_init(nbmanin);
+  S->E1 = E1 = set_init(nbgen);
+  S->E2 = E2 = set_init(nbgen);
+  S->T2 = T2 = set_init(nbgen);
+  S->T31 = T31 = set_init(nbgen);
+  S->T32 = T32 = set_init(nbgen);
+
+  /* T31 represents the three torsion paths going from left to right */
+  /* T32 represents the three torsion paths going from right to left */
+  for (r = 1; r < nbgen; r++)
+  {
+    GEN c2 = gel(cusp_list,r+1);
+    if (c2[3] == type_T)
+    {
+      GEN c1 = gel(cusp_list,r), path = mkpath(c1,c2), path2 = vecreverse(path);
+      set_insert(T31, path);
+      set_insert(T32, path2);
+    }
+  }
+
+  /* to record relations between E2 and E1 */
+  S->E2_in_terms_of_E1 = zerovec(nbgen);
+  S->stdE1 = const_vec(nbmanin, NULL);
+
+  /* Assumption later: path [oo,0] is E1[1], path [1,oo] is E2[1] */
+  {
+    GEN oo = cusp_infinity();
+    GEN p1 = mkpath(oo, mkvecsmall2(0,1)); /* [oo, 0] */
+    GEN p2 = mkpath(mkvecsmall2(1,1), oo); /* [1, oo] */
+    insert_E(p1, S, p1N);
+    insert_E(p2, S, p1N);
+  }
+
+  for (r = 1; r < nbgen; r++)
+  {
+    GEN c1 = gel(cusp_list,r);
+    for (s = r+1; s <= nbgen; s++)
+    {
+      pari_sp av = avma;
+      GEN c2 = gel(cusp_list,s), path;
+      GEN d = subii(mulss(c1[1],c2[2]), mulss(c1[2],c2[1]));
+      avma = av;
+      if (!is_pm1(d)) continue;
+
+      path = mkpath(c1,c2);
+      if (r+1 == s)
+      {
+        GEN w = path;
+        ulong hash = T31->hash(w); /* T31, T32 use the same hash function */
+        if (!hash_search2(T31, w, hash) && !hash_search2(T32, w, hash))
+        {
+          if (gamma_equiv(path, vecreverse(path), N))
+            set_insert(T2, path);
+          else
+            insert_E(path, S, p1N);
+        }
+      } else {
+        set_insert(F, mkvec2(path, mkvecsmall2(r,s)));
+        set_insert(F, mkvec2(vecreverse(path), mkvecsmall2(s,r)));
+      }
+    }
+  }
+  setlg(S->E2_in_terms_of_E1, E2->nb+1);
+}
+
+/* v = \sum n_i g_i, return \sum n_i g_i^(-1) */
+static GEN
+ZGl2Q_star(GEN v)
+{
+  long i, l;
+  GEN w, G;
+  if (typ(v) == t_INT) return v;
+  G = gel(v,1);
+  w = cgetg_copy(G, &l);
+  for (i = 1; i < l; i++)
+  {
+    GEN g = gel(G,i);
+    if (typ(g) == t_MAT) g = SL2_inv(g);
+    gel(w,i) = g;
+  }
+  return ZG_normalize(mkmat2(w, gel(v,2)));
+}
+static GEN
+ZGl2QC_star(GEN v)
+{
+  long i, l;
+  GEN w = cgetg_copy(v, &l);
+  for (i = 1; i < l; i++) gel(w,i) = ZGl2Q_star(gel(v,i));
+  return w;
+}
+
+/* Input: h = set of unimodular paths, p1N = P^1(Z/NZ) = Gamma_0(N)\PSL2(Z)
+ * Output: Each path is converted to a matrix and then an element of P^1(Z/NZ)
+ * Append the matrix to W[12], append the index that represents
+ * these elements of P^1 (the classes mod Gamma_0(N) via our fixed
+ * enumeration to W[2]. */
+static void
+paths_decompose(GEN W, hashtable *h, int flag)
+{
+  GEN p1N = ms_get_p1N(W), section = ms_get_section(W);
+  GEN v = hash_to_vec(h);
+  long i, l = lg(v);
+  for (i = 1; i < l; i++)
+  {
+    GEN e = gel(v,i);
+    GEN M = path_to_zm(flag? gel(e,1): e);
+    long index = p1_index(cc(M), dd(M), p1N);
+    vecsmalltrunc_append(gel(W,2), index);
+    gel(section, index) = M;
+  }
+}
+static void
+fill_W2_W12(GEN W, PS_sets_t *S)
+{
+  GEN p1N = gel(W,1);
+  long n = p1_size(p1N);
+  gel(W, 2) = vecsmalltrunc_init(n+1);
+  gel(W,12) = cgetg(n+1, t_VEC);
+  /* F contains [path, [index cusp1, index cusp2]]. Others contain paths only */
+  paths_decompose(W, S->F, 1);
+  paths_decompose(W, S->E2, 0);
+  paths_decompose(W, S->T32, 0);
+  paths_decompose(W, S->E1, 0);
+  paths_decompose(W, S->T2, 0);
+  paths_decompose(W, S->T31, 0);
+}
+
+/* x t_VECSMALL, corresponds to a map x(i) = j, where 1 <= j <= max for all i
+ * Return y s.t. y[j] = i or 0 (not in image) */
+static GEN
+reverse_list(GEN x, long max)
+{
+  GEN y = const_vecsmall(max, 0);
+  long r, lx = lg(x);
+  for (r = 1; r < lx; r++) y[ x[r] ] = r;
+  return y;
+}
+
+/* go from C[a] to C[b]; return the indices of paths
+ * E.g. if a < b
+ *   (C[a]->C[a+1], C[a+1]->C[a+2], ... C[b-1]->C[b])
+ * (else reverse direction)
+ * = b - a paths */
+static GEN
+F_indices(GEN W, long a, long b)
+{
+  GEN v = cgetg(labs(b-a) + 1, t_VEC);
+  long s, k = 1;
+  if (a < b) {
+    GEN index_forward = gel(W,13);
+    for (s = a; s < b; s++) gel(v,k++) = gel(index_forward,s);
+  } else {
+    GEN index_backward = gel(W,14);
+    for (s = a; s > b; s--) gel(v,k++) = gel(index_backward,s);
+  }
+  return v;
+}
+/* go from C[a] to C[b] via oo; return the indices of paths
+ * E.g. if a < b
+ *   (C[a]->C[a-1], ... C[2]->C[1],
+ *    C[1]->oo, oo-> C[end],
+ *    C[end]->C[end-1], ... C[b+1]->C[b])
+ *  a-1 + 2 + end-(b+1)+1 = end - b + a + 1 paths  */
+static GEN
+F_indices_oo(GEN W, long end, long a, long b)
+{
+  GEN index_oo = gel(W,15);
+  GEN v = cgetg(end-labs(b-a)+1 + 1, t_VEC);
+  long s, k = 1;
+
+  if (a < b) {
+    GEN index_backward = gel(W,14);
+    for (s = a; s > 1; s--) gel(v,k++) = gel(index_backward,s);
+    gel(v,k++) = gel(index_backward,1); /* C[1] -> oo */
+    gel(v,k++) = gel(index_oo,2); /* oo -> C[end] */
+    for (s = end; s > b; s--) gel(v,k++) = gel(index_backward,s);
+  } else {
+    GEN index_forward = gel(W,13);
+    for (s = a; s < end; s++) gel(v,k++) = gel(index_forward,s);
+    gel(v,k++) = gel(index_forward,end); /* C[end] -> oo */
+    gel(v,k++) = gel(index_oo,1); /* oo -> C[1] */
+    for (s = 1; s < b; s++) gel(v,k++) = gel(index_forward,s);
+  }
+  return v;
+}
+/* index of oo -> C[1], oo -> C[end] */
+static GEN
+indices_oo(GEN W, GEN C)
+{
+  long end = lg(C)-1;
+  GEN w, v = cgetg(2+1, t_VEC), oo = cusp_infinity();
+  w = mkpath(oo, gel(C,1)); /* oo -> C[1]=0 */
+  gel(v,1) = path_Gamma0N_decompose(W, w);
+  w = mkpath(oo, gel(C,end)); /* oo -> C[end]=1 */
+  gel(v,2) = path_Gamma0N_decompose(W, w);
+  return v;
+}
+
+/* index of C[1]->C[2], C[2]->C[3], ... C[end-1]->C[end], C[end]->oo
+ * Recall that C[1] = 0, C[end] = 1 */
+static GEN
+indices_forward(GEN W, GEN C)
+{
+  long s, k = 1, end = lg(C)-1;
+  GEN v = cgetg(end+1, t_VEC);
+  for (s = 1; s <= end; s++)
+  {
+    GEN w = mkpath(gel(C,s), s == end? cusp_infinity(): gel(C,s+1));
+    gel(v,k++) = path_Gamma0N_decompose(W, w);
+  }
+  return v;
+}
+/* index of C[1]->oo, C[2]->C[1], ... C[end]->C[end-1] */
+static GEN
+indices_backward(GEN W, GEN C)
+{
+  long s, k = 1, end = lg(C)-1;
+  GEN v = cgetg(end+1, t_VEC);
+  for (s = 1; s <= end; s++)
+  {
+    GEN w = mkpath(gel(C,s), s == 1? cusp_infinity(): gel(C,s-1));
+    gel(v,k++) = path_Gamma0N_decompose(W, w);
+  }
+  return v;
+}
+
+/* N = integer > 1. Returns data describing Delta_0 = Z[P^1(Q)]_0 seen as
+ * a Gamma_0(N) - module. */
+static GEN
+msinit_N(ulong N)
+{
+  GEN p1N = create_p1mod(N);
+  GEN C, vecF, vecT2, vecT31;
+  ulong r, s, width;
+  long nball, nbgen, nbp1N = p1_size(p1N);
+  GEN TAU = mkmat2(mkcol2(gen_0,gen_1), mkcol2(gen_m1,gen_m1)); /*[0,-1;1,-1]*/
+  GEN W, W2, singlerel, annT2, annT31;
+  GEN F_index;
+  hashtable *F, *T2, *T31, *T32, *E1, *E2;
+  PS_sets_t S;
+
+  form_E_F_T(N,p1N, &C, &S);
+  E1  = S.E1;
+  E2  = S.E2;
+  T31 = S.T31;
+  T32 = S.T32;
+  F   = S.F;
+  T2  = S.T2;
+  nbgen = lg(C)-1;
+
+  W = cgetg(17, t_VEC);
+  gel(W,1) = p1N;
+
+ /* Put our paths in the order: F,E2,T32,E1,T2,T31
+  * W2[j] associates to the j-th element of this list its index in P1. */
+  fill_W2_W12(W, &S);
+  W2 = gel(W, 2);
+  nball = lg(W2)-1;
+  gel(W,3) = reverse_list(W2, nbp1N);
+
+  gel(W,5) = vecslice(gel(W,2), F->nb + E2->nb + T32->nb + 1, nball);
+  gel(W,4) = reverse_list(gel(W,5), nbp1N);
+  gel(W,13) = indices_forward(W, C);
+  gel(W,14) = indices_backward(W, C);
+  gel(W,15) = indices_oo(W, C);
+  gel(W,11) = mkvecsmall5(F->nb,
+                          F->nb + E2->nb,
+                          F->nb + E2->nb + T32->nb,
+                          F->nb + E2->nb + T32->nb + E1->nb,
+                          F->nb + E2->nb + T32->nb + E1->nb + T2->nb);
+
+  /* relations between T32 and T31 [not stored!]
+   * T32[i] = - T31[i] */
+
+  /* relations of F */
+  width = E1->nb + T2->nb + T31->nb;
+  /* F_index[r] = [index_1, ..., index_k], where index_i is the p1_index()
+   * of the elementary unimodular path between 2 consecutive cusps
+   * [in E1,E2,T2,T31 or T32] */
+  F_index = cgetg(F->nb+1, t_VEC);
+  vecF = hash_to_vec(F);
+  for (r = 1; r <= F->nb; r++)
+  {
+    GEN w = gel(gel(vecF,r), 2);
+    long a = w[1], b = w[2], d = labs(b - a);
+    /* c1 = cusp_list[a],  c2 = cusp_list[b], ci != oo */
+    gel(F_index,r) = (nbgen-d >= d-1)? F_indices(W, a,b)
+                                     : F_indices_oo(W, lg(C)-1,a,b);
+  }
+
+  singlerel = cgetg(width+1, t_VEC);
+  /* form the single boundary relation */
+  for (s = 1; s <= E2->nb; s++)
+  {
+    GEN data = gel(S.E2_in_terms_of_E1,s);
+    long c = itos(gel(data,1));
+    GEN u = gel(data,2); /* E2[s] = u * E1[c], u = - [gamma] */
+    GEN gamma = gcoeff(u,1,1);
+    gel(singlerel, c) = mkmat2(mkcol2(gen_1,gamma),mkcol2(gen_1,gen_m1));
+  }
+  for (r = E1->nb + 1; r <= width; r++) gel(singlerel, r) = gen_1;
+
+  /* form the 2-torsion relations */
+  annT2 = cgetg(T2->nb+1, t_VEC);
+  vecT2 = hash_to_vec(T2);
+  for (r = 1; r <= T2->nb; r++)
+  {
+    GEN w = gel(vecT2,r);
+    GEN gamma = gamma_equiv_matrix(vecreverse(w), w);
+    gel(annT2, r) = mkmat2(mkcol2(gen_1,gamma), mkcol2(gen_1,gen_1));
+  }
+
+  /* form the 3-torsion relations */
+  annT31 = cgetg(T31->nb+1, t_VEC);
+  vecT31 = hash_to_vec(T31);
+  for (r = 1; r <= T31->nb; r++)
+  {
+    GEN M = zm_to_ZM( path_to_zm( vecreverse(gel(vecT31,r)) ) );
+    GEN gamma = ZM_mul(ZM_mul(M, TAU), SL2_inv(M));
+    gel(annT31, r) = mkmat2(mkcol3(gen_1,gamma,ZM_sqr(gamma)),
+                            mkcol3(gen_1,gen_1,gen_1));
+  }
+  gel(W,6) = F_index;
+  gel(W,7) = S.E2_in_terms_of_E1;
+  gel(W,8) = annT2;
+  gel(W,9) = annT31;
+  gel(W,10)= singlerel;
+  gel(W,16)= inithashcusps(p1N);
+  return W;
+}
+static GEN
+cusp_to_P1Q(GEN c) { return c[2]? gdivgs(stoi(c[1]), c[2]): mkoo(); }
+GEN
+mspathgens(GEN W)
+{
+  pari_sp av = avma;
+  long i,j, l, nbE1, nbT2, nbT31;
+  GEN R, r, g, section, gen, annT2, annT31, singlerel;
+  checkms(W); W = get_ms(W);
+  section = ms_get_section(W);
+  gen = ms_get_genindex(W);
+  l = lg(gen);
+  g = cgetg(l,t_VEC);
+  for (i=1; i<l; i++)
+  {
+    GEN p = gel(section,gen[i]);
+    gel(g,i) = mkvec2(cusp_to_P1Q(gel(p,1)), cusp_to_P1Q(gel(p,2)));
+  }
+  nbE1 = ms_get_nbE1(W);
+  annT2 = gel(W,8); nbT2 = lg(annT2)-1;
+  annT31 = gel(W,9);nbT31 = lg(annT31)-1;
+  singlerel = gel(W,10);
+  R = cgetg(nbT2+nbT31+2, t_VEC);
+  l = lg(singlerel);
+  r = cgetg(l, t_VEC);
+  for (i = 1; i <= nbE1; i++)
+    gel(r,i) = mkvec2(gel(singlerel, i), stoi(i));
+  for (; i < l; i++)
+    gel(r,i) = mkvec2(gen_1, stoi(i));
+  gel(R,1) = r; j = 2;
+  for (i = 1; i <= nbT2; i++,j++)
+    gel(R,j) = mkvec( mkvec2(gel(annT2,i), stoi(i + nbE1)) );
+  for (i = 1; i <= nbT31; i++,j++)
+    gel(R,j) = mkvec( mkvec2(gel(annT31,i), stoi(i + nbE1 + nbT2)) );
+  return gerepilecopy(av, mkvec2(g,R));
+}
+
+/* Modular symbols in weight k: Hom_Gamma(Delta, Q[x,y]_{k-2}) */
+/* A symbol phi is represented by the {phi(g_i)}, {phi(g'_i)}, {phi(g''_i)}
+ * where the {g_i, g'_i, g''_i} are the Z[\Gamma]-generators of Delta,
+ * g_i corresponds to E1, g'_i to T2, g''_i to T31.
+ */
+
+/* FIXME: export. T^1, ..., T^n */
+static GEN
+RgX_powers(GEN T, long n)
+{
+  GEN v = cgetg(n+1, t_VEC);
+  long i;
+  gel(v, 1) = T;
+  for (i = 1; i < n; i++) gel(v,i+1) = RgX_mul(gel(v,i), T);
+  return v;
+}
+
+/* g = [a,b;c,d]. Return (X^{k-2} | g)(X,Y)[X = 1]. */
+static GEN
+voo_act_Gl2Q(GEN g, long k)
+{
+  GEN c = gcoeff(g,2,1), d = gcoeff(g,2,2);
+  return RgX_to_RgC(gpowgs(deg1pol_shallow(gneg(c), d, 0), k-2), k-1);
+}
+
+/* g = [a,b;c,d]. Return (P | g)(X,Y)[X = 1] = P(dX - cY, -b X + aY)[X = 1],
+ * for P = X^{k-2}, X_^{k-3}Y, ..., Y^{k-2} */
+GEN
+RgX_act_Gl2Q(GEN g, long k)
+{
+  GEN a = gcoeff(g,1,1), b = gcoeff(g,1,2);
+  GEN c = gcoeff(g,2,1), d = gcoeff(g,2,2);
+  GEN V1 = RgX_powers(deg1pol_shallow(gneg(c), d, 0), k-2);
+  GEN V2 = RgX_powers(deg1pol_shallow(a, gneg(b), 0), k-2);
+  GEN V = cgetg(k, t_MAT);
+  long i;
+  gel(V,1)   = RgX_to_RgC(gel(V1, k-2), k-1);
+  for (i = 1; i < k-2; i++)
+  {
+    GEN v1 = gel(V1, k-2-i); /* (d-cY)^(k-2-i) */
+    GEN v2 = gel(V2, i); /* (-b+aY)^i */
+    gel(V,i+1) = RgX_to_RgC(RgX_mul(v1,v2), k-1);
+  }
+  gel(V,k-1) = RgX_to_RgC(gel(V2, k-2), k-1);
+  return V; /* V[i+1] = X^i | g */
+}
+/* z in Z[\Gamma], return the matrix of z acting on (X^{k-2},...,Y^{k-2}) */
+GEN
+RgX_act_ZGl2Q(GEN z, long k)
+{
+  long l, j;
+  GEN S = NULL, G, E;
+  if (typ(z) == t_INT) return matid(k-1);
+  G = gel(z,1); l = lg(G);
+  E = gel(z,2);
+  for (j = 1; j < l; j++)
+  {
+    GEN M, g = gel(G,j), n = gel(E,j);
+    if (typ(g) == t_INT)
+      M = scalarmat_shallow(n, k-1);
+    else
+    {
+      M = RgX_act_Gl2Q(g, k);
+      if (is_pm1(n))
+      { if (signe(n) < 0) M = RgM_neg(M);
+      } else
+        M = RgM_Rg_mul(M, n);
+    }
+    S = j == 1? M: RgM_add(S, M);
+  }
+  return S;
+}
+/* Given a vector of elements in Z[G], return it as vector of operators on V
+ * (given by t_MAT) */
+static GEN
+ZGl2QC_to_act(GEN v, long k)
+{
+  long i, l;
+  GEN w = cgetg_copy(v, &l);
+  for (i = 1; i < l; i++) gel(w,i) = RgX_act_ZGl2Q(gel(v,i), k);
+  return w;
+}
+
+/* For all V[i] in Z[\Gamma], find the P such that  P . V[i]^* = 0;
+ * write P in basis X^{k-2}, ..., Y^{k-2} */
+static GEN
+ZGV_tors(GEN V, long k)
+{
+  long i, l = lg(V);
+  GEN v = cgetg(l, t_VEC);
+  for (i = 1; i < l; i++)
+  {
+    GEN a = ZGl2Q_star(gel(V,i));
+    gel(v,i) = ZM_ker(RgX_act_ZGl2Q(a,k));
+  }
+  return v;
+}
+
+static long
+set_from_index(GEN W11, long i)
+{
+  if (i <= W11[1]) return 1;
+  if (i <= W11[2]) return 2;
+  if (i <= W11[3]) return 3;
+  if (i <= W11[4]) return 4;
+  if (i <= W11[5]) return 5;
+  return 6;
+}
+
+/* det M = 1 */
+static void
+treat_index(GEN W, GEN M, long index, GEN v)
+{
+  GEN W11 = gel(W,11);
+  long shift = W11[3]; /* #F + #E2 + T32 */
+  switch(set_from_index(W11, index))
+  {
+    case 1: /*F*/
+    {
+      GEN F_index = gel(W,6), ind = gel(F_index, index);
+      long j, l = lg(ind);
+      for (j = 1; j < l; j++)
+      {
+        GEN IND = gel(ind,j), M0 = gel(IND,2);
+        long index = mael(IND,1,1);
+        treat_index(W, ZM_mul(M,M0), index, v);
+      }
+      break;
+    }
+
+    case 2: /*E2, E2[r] + gamma * E1[s] = 0 */
+    {
+      long r = index - W11[1];
+      GEN E2_in_terms_of_E1= gel(W,7), z = gel(E2_in_terms_of_E1, r);
+      long s = itou(gel(z,1));
+
+      index = s;
+      M = G_ZG_mul(M, gel(z,2)); /* M * (-gamma) */
+      gel(v, index) = ZG_add(gel(v, index), M);
+      break;
+    }
+
+    case 3: /*T32, T32[i] = -T31[i] */
+    {
+      long T3shift = W11[5] - W11[2]; /* #T32 + #E1 + #T2 */
+      index += T3shift;
+      index -= shift;
+      gel(v, index) = ZG_add(gel(v, index), to_famat_shallow(M,gen_m1));
+      break;
+    }
+    default: /*E1,T2,T31*/
+      index -= shift;
+      gel(v, index) = ZG_add(gel(v, index), to_famat_shallow(M,gen_1));
+      break;
+  }
+}
+static void
+treat_index_trivial(GEN v, GEN W, long index)
+{
+  GEN W11 = gel(W,11);
+  long shift = W11[3]; /* #F + #E2 + T32 */
+  switch(set_from_index(W11, index))
+  {
+    case 1: /*F*/
+    {
+      GEN F_index = gel(W,6), ind = gel(F_index, index);
+      long j, l = lg(ind);
+      for (j = 1; j < l; j++)
+      {
+        GEN IND = gel(ind,j);
+        treat_index_trivial(v, W, mael(IND,1,1));
+      }
+      break;
+    }
+
+    case 2: /*E2, E2[r] + gamma * E1[s] = 0 */
+    {
+      long r = index - W11[1];
+      GEN E2_in_terms_of_E1= gel(W,7), z = gel(E2_in_terms_of_E1, r);
+      long s = itou(gel(z,1));
+      index = s;
+      gel(v, index) = subiu(gel(v, index), 1);
+      break;
+    }
+
+    case 3: case 5: case 6: /*T32,T2,T31*/
+      break;
+
+    case 4: /*E1*/
+      index -= shift;
+      gel(v, index) = addiu(gel(v, index), 1);
+      break;
+  }
+}
+
+static GEN
+M2_log(GEN W, GEN M)
+{
+  GEN a = gcoeff(M,1,1), b = gcoeff(M,1,2);
+  GEN c = gcoeff(M,2,1), d = gcoeff(M,2,2);
+  GEN  u, v, D, V;
+  long index, s;
+
+  W = get_ms(W);
+  V = zerovec(ms_get_nbgen(W));
+
+  D = subii(mulii(a,d), mulii(b,c));
+  s = signe(D);
+  if (!s) return V;
+  if (is_pm1(D))
+  { /* shortcut, not need to apply Manin's trick */
+    if (s < 0) {
+      b = negi(b);
+      d = negi(d);
+    }
+    M = mkmat2(mkcol2(a,c), mkcol2(b,d));
+    M = Gamma0N_decompose(W, M, &index);
+    treat_index(W, M, index, V);
+  }
+  else
+  {
+    GEN U, B, P, Q, PQ, C1,C2;
+    long i, l;
+    (void)bezout(a,c,&u,&v);
+    B = addii(mulii(b,u), mulii(d,v));
+    /* [u,v;-c,a] [a,b; c,d] = [1,B; 0,D], i.e. M = U [1,B;0,D] */
+    U = mkmat2(mkcol2(a, c), mkcol2(negi(v),u));
+
+    /* {1/0 -> B/D} as \sum g_i, g_i unimodular paths */
+    PQ = ZV_allpnqn( gboundcf(gdiv(B,D), 0) );
+    P = gel(PQ,1); l = lg(P);
+    Q = gel(PQ,2);
+    C1 = gel(U,1);
+    for (i = 1; i < l; i++, C1 = C2)
+    {
+      GEN M;
+      C2 = ZM_ZC_mul(U, mkcol2(gel(P,i), gel(Q,i)));
+      if (!odd(i)) C1 = ZC_neg(C1);
+      M = Gamma0N_decompose(W, mkmat2(C1,C2), &index);
+      treat_index(W, M, index, V);
+    }
+  }
+  return V;
+}
+
+/* express +oo->q=a/b in terms of the Z[G]-generators, trivial action */
+static void
+Q_log_trivial(GEN v, GEN W, GEN q)
+{
+  GEN Q, W3 = gel(W,3), p1N = gel(W,1);
+  ulong c,d, N = p1N_get_N(p1N);
+  long i, lx;
+
+  Q = Q_log_init(N, q);
+  lx = lg(Q);
+  c = 0;
+  for (i = 1; i < lx; i++, c = d)
+  {
+    long index;
+    d = Q[i];
+    if (c && !odd(i)) c = N - c;
+    index = W3[ p1_index(c,d,p1N) ];
+    treat_index_trivial(v, W, index);
+  }
+}
+static void
+M2_log_trivial(GEN V, GEN W, GEN M)
+{
+  GEN p1N = gel(W,1), W3 = gel(W,3);
+  ulong N = p1N_get_N(p1N);
+  GEN a = gcoeff(M,1,1), b = gcoeff(M,1,2);
+  GEN c = gcoeff(M,2,1), d = gcoeff(M,2,2);
+  GEN  u, v, D;
+  long index, s;
+
+  D = subii(mulii(a,d), mulii(b,c));
+  s = signe(D);
+  if (!s) return;
+  if (is_pm1(D))
+  { /* shortcut, not need to apply Manin's trick */
+    if (s < 0) d = negi(d);
+    index = W3[ p1_index(umodiu(c,N),umodiu(d,N),p1N) ];
+    treat_index_trivial(V, W, index);
+  }
+  else
+  {
+    GEN U, B, P, Q, PQ;
+    long i, l;
+    if (!signe(c)) return Q_log_trivial(V,W,gdiv(b,d));
+    (void)bezout(a,c,&u,&v);
+    B = addii(mulii(b,u), mulii(d,v));
+    /* [u,v;-c,a] [a,b; c,d] = [1,B; 0,D], i.e. M = U [1,B;0,D] */
+    U = mkvec2(c, u);
+
+    /* {1/0 -> B/D} as \sum g_i, g_i unimodular paths */
+    PQ = ZV_allpnqn( gboundcf(gdiv(B,D), 0) );
+    P = gel(PQ,1); l = lg(P);
+    Q = gel(PQ,2);
+    for (i = 1; i < l; i++, c = d)
+    {
+      d = addii(mulii(gel(U,1),gel(P,i)), mulii(gel(U,2),gel(Q,i)));
+      if (!odd(i)) c = negi(c);
+      index = W3[ p1_index(umodiu(c,N),umodiu(d,N),p1N) ];
+      treat_index_trivial(V, W, index);
+    }
+  }
+}
+
+static GEN
+cusp_to_ZC(GEN c)
+{
+  switch(typ(c))
+  {
+    case t_INFINITY:
+      return mkcol2(gen_1,gen_0);
+    case t_INT:
+      return mkcol2(c,gen_1);
+    case t_FRAC:
+      return mkcol2(gel(c,1),gel(c,2));
+    case t_VECSMALL:
+      return mkcol2(stoi(c[1]), stoi(c[2]));
+    default:
+      pari_err_TYPE("mspathlog",c);
+      return NULL;
+  }
+}
+static GEN
+path_to_M2(GEN p)
+{ return mkmat2(cusp_to_ZC(gel(p,1)), cusp_to_ZC(gel(p,2))); }
+
+/* Expresses path p as \sum x_i g_i, where the g_i are our distinguished
+ * generators and x_i \in Z[\Gamma]. Returns [x_1,...,x_n] */
+static GEN
+mspathlog_i(GEN W, GEN p)
+{ return M2_log(W, path_to_M2(p)); }
+/* in case the action is trivial: v += mspathlog(path) */
+static void
+mspathlog_i_trivial(GEN v, GEN W, GEN p)
+{ M2_log_trivial(v, W, path_to_M2(p)); }
+
+GEN
+mspathlog(GEN W, GEN p)
+{
+  pari_sp av = avma;
+  checkms(W);
+  if (lg(p) != 3) pari_err_TYPE("mspathlog",p);
+  switch(typ(p))
+  {
+    case t_MAT:
+      RgM_check_ZM(p,"mspathlog");
+      break;
+    case t_VEC:
+      p = path_to_M2(p);
+      break;
+    default: pari_err_TYPE("mspathlog",p);
+  }
+  return gerepilecopy(av, M2_log(W, p));
+}
+static GEN
+mspathlog_trivial(GEN W, GEN p)
+{
+  GEN v;
+  W = get_ms(W);
+  v = zerovec(ms_get_nbgen(W));
+  M2_log_trivial(v, W, path_to_M2(p));
+  return v;
+}
+
+/** HECKE OPERATORS **/
+/* [a,b;c,d] * cusp */
+static GEN
+cusp_mul(GEN cusp, long a, long b, long c, long d)
+{
+  long x = cusp[1], y = cusp[2];
+  long A = a*x+b*y, B = c*x+d*y, u = cgcd(A,B);
+  if (u != 1) { A /= u; B /= u; }
+  return mkvecsmall2(A, B);
+}
+static GEN
+path_mul(GEN path, long a, long b, long c, long d)
+{
+  GEN c1 = cusp_mul(gel(path,1), a,b,c,d);
+  GEN c2 = cusp_mul(gel(path,2), a,b,c,d);
+  return mkpath(c1,c2);
+}
+/* f in Gl2(Q), act on path (zm) */
+static GEN
+Gl2Q_act_path(GEN f, GEN path)
+{ return path_mul(path, coeff(f,1,1),coeff(f,1,2),coeff(f,2,1),coeff(f,2,2)); }
+
+static GEN
+init_act_trivial(GEN W) { return zerocol(ms_get_nbE1(W)); }
+
+/* map from WW1 -> WW2, weight 2, trivial action. v a Gl2_Q or a t_VEC
+ * of Gl2_Q (\sum v[i] in Z[Gl2(Q)]). Return the matrix associated to the
+ * action of v. */
+static GEN
+getMorphism_trivial(GEN WW1, GEN WW2, GEN v)
+{
+  GEN W1 = get_ms(WW1), W2 = get_ms(WW2);
+  GEN section = ms_get_section(W1), gen = gel(W1,5);
+  long i, j, lv, nbE1 = ms_get_nbE1(W1);
+  GEN T = cgetg(nbE1+1, t_MAT);
+  if (typ(v) != t_VEC) v = mkvec(v);
+  lv = lg(v);
+  for (i = 1; i <= nbE1; i++)
+  {
+    long e = gen[i]; /* path-index of E1-element */
+    GEN w = gel(section, e); /* path_to_zm() */
+    GEN t = init_act_trivial(W2);
+    for (j = 1; j < lv; j++)
+      mspathlog_i_trivial(t, W2, Gl2Q_act_path(gel(v,j), w));
+    gel(T,i) = t;
+  }
+  return T;
+}
+
+/* f zm/ZM in Gl_2(Q), acts from the left on Delta, which is generated by
+ * (g_i) as Z[Gamma1]-module, and by (G_i) as Z[Gamma2]-module.
+ * We have f.G_j = \sum_i \lambda_{i,j} g_i,   \lambda_{i,j} in Z[Gamma1]
+ *
+ * For phi in Hom_Gamma1(D,V), g in D, phi | f is in Hom_Gamma2(D,V) and
+ *  (phi | f)(G_j) = phi(f.G_j) | f
+ *                 = phi( \sum_i \lambda_{i,j} g_i ) | f
+ *                 = \sum_i phi(g_i) | (\lambda_{i,j}^* f)
+ *                 = \sum_i phi(g_i) | \mu_{i,j}
+ * Return the \mu_{i,j} matrix as operators on V (t_MAT) */
+static GEN
+init_dual_act(GEN f, GEN W1, GEN W2)
+{
+  GEN section = ms_get_section(W2), gen = ms_get_genindex(W2);
+  long j, dim = lg(gen)-1, k = msk_get_weight(W1);
+  GEN T = cgetg(dim+1, t_MAT), F;
+  if (typ(gel(f,1)) == t_VEC)
+  {
+    F = f;
+    f = ZM_to_zm(F);
+  }
+  else
+    F = zm_to_ZM(f);
+  /* f zm = F ZM */
+  for (j = 1; j <= dim; j++)
+  {
+    pari_sp av = avma;
+    GEN w = gel(section, gen[j]); /* path_to_zm( E1/T2/T3 element ) */
+    GEN l = mspathlog_i(W1, Gl2Q_act_path(f, w)); /* lambda_{i,j} */
+    l = ZGl2QC_star(l); /* lambda_{i,j}^* */
+    l = ZGC_G_mul(l, F); /* mu_{i,j} */
+    gel(T,j) = gerepilecopy(av, ZGl2QC_to_act(l, k)); /* as operators on V */
+  }
+  return T;
+}
+/* phi in Hom_Gamma1(Delta, V), return the matrix whose colums are the
+ *   \sum_i phi(g_i) | \mu_{i,j} = (phi|f)(G_j),
+ * see init_dual_act. */
+static GEN
+dual_act(GEN phi, GEN mu)
+{
+  long l = lg(mu), a, j;
+  GEN ind = gel(phi,2), pols = gel(phi,3);
+  GEN v = cgetg(l, t_MAT);
+  for (j = 1; j < l; j++)
+  {
+    GEN T = NULL;
+    for (a = 1; a < lg(ind); a++)
+    {
+      long i = ind[a];
+      GEN t = gel(pols, a); /* phi(G_i) */
+      t = RgM_RgC_mul(gcoeff(mu,i,j), t);
+      T = T? RgC_add(T, t): t;
+    }
+    gel(v,j) = T;
+  }
+  return v;
+}
+
+/* phi in Hom(Delta, V), phi(G_k) = vecT[k]. Write phi as
+ *   \sum_{i,j} mu_{i,j} phi_{i,j}, mu_{i,j} in Q */
+static GEN
+getMorphism_basis(GEN W, GEN vecT)
+{
+  GEN basis = msk_get_basis(W);
+  long i, j, r, lvecT = lg(vecT), dim = lg(basis)-1;
+  GEN st = msk_get_st(W);
+  GEN link = msk_get_link(W);
+  GEN invphiblock = msk_get_invphiblock(W);
+  long s = st[1], t = st[2];
+  GEN R = zerovec(dim), Q, Ls, T0, T1, Ts, mu_st;
+  for (r = 2; r < lvecT; r++)
+  {
+    GEN Tr, L;
+    if (r == s) continue;
+    Tr = gel(vecT,r); /* Phi(G_r), r != 1,s */
+    L = gel(link, r);
+    Q = ZC_apply_dinv(gel(invphiblock,r), Tr);
+    /* write Phi(G_r) as sum_{a,b} mu_{a,b} Phi_{a,b}(G_r) */
+    for (j = 1; j < lg(L); j++) gel(R, L[j]) = gel(Q,j);
+  }
+  Ls = gel(link, s);
+  T1 = gel(vecT,1); /* Phi(G_1) */
+  gel(R, Ls[t]) = mu_st = gel(T1, 1);
+
+  T0 = NULL;
+  for (i = 2; i < lg(link); i++)
+  {
+    GEN L;
+    if (i == s) continue;
+    L = gel(link,i);
+    for (j =1 ; j < lg(L); j++)
+    {
+      long n = L[j]; /* phi_{i,j} = basis[n] */
+      GEN mu_ij = gel(R, n);
+      GEN phi_ij = gel(basis, n), pols = gel(phi_ij,3);
+      GEN z = RgC_Rg_mul(gel(pols, 3), mu_ij);
+      T0 = T0? RgC_add(T0, z): z; /* += mu_{i,j} Phi_{i,j} (G_s) */
+    }
+  }
+  Ts = gel(vecT,s); /* Phi(G_s) */
+  if (T0) Ts = RgC_sub(Ts, T0);
+  /* solve \sum_{j!=t} mu_{s,j} Phi_{s,j}(G_s) = Ts */
+  Q = ZC_apply_dinv(gel(invphiblock,s), Ts);
+  for (j = 1; j < t; j++) gel(R, Ls[j]) = gel(Q,j);
+  /* avoid mu_{s,t} */
+  for (j = t; j < lg(Q); j++) gel(R, Ls[j+1]) = gel(Q,j);
+  return R;
+}
+
+/* a = s(g_i) for some modular symbol s; b in Z[G]
+ * return s(b.g_i) = b^* . s(g_i) */
+static GEN
+ZGl2Q_act_s(GEN b, GEN a, long k)
+{
+  if (typ(b) == t_INT)
+  {
+    if (!signe(b)) return gen_0;
+    switch(typ(a))
+    {
+      case t_POL:
+        a = RgX_to_RgC(a, k-1); /*fall through*/
+      case t_COL:
+        a = RgC_Rg_mul(a,b);
+        break;
+      default: a = scalarcol_shallow(b,k-1);
+    }
+  }
+  else
+  {
+    b = RgX_act_ZGl2Q(ZGl2Q_star(b), k);
+    switch(typ(a))
+    {
+      case t_POL:
+        a = RgX_to_RgC(a, k-1); /*fall through*/
+      case t_COL:
+        a = RgM_RgC_mul(b,a);
+        break;
+      default: a = RgC_Rg_mul(gel(b,1),a);
+    }
+  }
+  return a;
+}
+
+static int
+checksymbol(GEN W, GEN s)
+{
+  GEN t, annT2, annT31, singlerel;
+  long i, k, l, nbE1, nbT2, nbT31;
+  k = msk_get_weight(W);
+  W = get_ms(W);
+  nbE1 = ms_get_nbE1(W);
+  singlerel = gel(W,10);
+  l = lg(singlerel);
+  if (k == 2)
+  {
+    for (i = nbE1+1; i < l; i++)
+      if (!gequal0(gel(s,i))) return 0;
+    return 1;
+  }
+  annT2 = gel(W,8); nbT2 = lg(annT2)-1;
+  annT31 = gel(W,9);nbT31 = lg(annT31)-1;
+  t = NULL;
+  for (i = 1; i < l; i++)
+  {
+    GEN a = gel(s,i);
+    a = ZGl2Q_act_s(gel(singlerel,i), a, k);
+    t = t? gadd(t, a): a;
+  }
+  if (!gcmp0(t)) return 0;
+  for (i = 1; i <= nbT2; i++)
+  {
+    GEN a = gel(s,i + nbE1);
+    a = ZGl2Q_act_s(gel(annT2,i), a, k);
+    if (!gcmp0(a)) return 0;
+  }
+  for (i = 1; i <= nbT31; i++)
+  {
+    GEN a = gel(s,i + nbE1 + nbT2);
+    a = ZGl2Q_act_s(gel(annT31,i), a, k);
+    if (!gcmp0(a)) return 0;
+  }
+  return 1;
+}
+long
+msissymbol(GEN W, GEN s)
+{
+  long k, nbgen;
+  checkms(W);
+  k = msk_get_weight(W);
+  nbgen = ms_get_nbgen(W);
+  switch(typ(s))
+  {
+    case t_VEC: /* values s(g_i) */
+      if (lg(s)-1 != nbgen) return 0;
+      break;
+    case t_COL:
+      if (k == 2) /* on the dual basis of (g_i) */
+      {
+        if (lg(s)-1 != nbgen) return 0;
+      }
+      else
+      {
+        GEN basis = msk_get_basis(W);
+        return (lg(s) == lg(basis));
+      }
+      break;
+    default: return 0;
+  }
+  return checksymbol(W,s);
+}
+#if DEBUG
+/* phi_i(G_j) */
+static GEN
+eval_phii_Gj(GEN W, long i, long j)
+{
+  GEN basis = msk_get_basis(W), b = gel(basis,i);
+  GEN ind = gel(b,2), pols = gel(b,3);
+  long s;
+  for (s = 1; s < lg(ind); s++)
+    if (ind[s] == j) return gel(pols,s);
+  return zerocol(lg(gel(pols,1))-1);
+}
+/* check that \sum d_i phi_i(G_j)  = T_j for all j */
+static void
+checkdec(GEN W, GEN D, GEN T)
+{
+  long i, j;
+  if (!checksymbol(W,T)) pari_err_BUG("checkdec");
+  for (j = 1; j < lg(T); j++)
+  {
+    GEN S = gen_0;
+    for (i = 1; i < lg(D); i++)
+    {
+      GEN d = gel(D,i);
+      if (gcmp0(d)) continue;
+      S = gadd(S, gmul(d, eval_phii_Gj(W, i, j)));
+    }
+    /* S = \sum_i d_i phi_i(G_j) */
+    if (!gequal(S, gel(T,j)))
+      pari_warn(warner, "checkdec j = %ld\n\tS = %Ps\n\tT = %Ps", j,S,gel(T,j));
+  }
+}
+#endif
+
+/* map op: Hom(W1,V) -> Hom(W2,V), given by \sum v[i], v[i] in Gl2(Q) */
+static GEN
+getMorphism(GEN W1, GEN W2, GEN v)
+{
+  GEN basis1 = msk_get_basis(W1);
+  long i, a, lv, dim1 = lg(basis1)-1;
+  GEN M = cgetg(dim1+1, t_MAT), act;
+  if (typ(v) != t_VEC) v = mkvec(v);
+  lv = lg(v); act = cgetg(lv, t_MAT);
+  for (i = 1; i < lv; i++) gel(act,i) = init_dual_act(gel(v,i), W1, W2);
+  for (a = 1; a <= dim1; a++)
+  {
+    pari_sp av = avma;
+    GEN phi = gel(basis1, a), D, T = NULL;
+    for (i = 1; i < lv; i++)
+    {
+      GEN t = dual_act(phi, gel(act, i));
+      T = T? gerepileupto(av, RgM_add(T,t)): t;
+    }
+    /* T = (phi|op)(G_1,...,G_d2) */
+    D = getMorphism_basis(W2, T);
+#if DEBUG
+    checkdec(W2,D,T);
+#endif
+    gel(M,a) = gerepilecopy(av, D);
+  }
+  return M;
+}
+
+static GEN
+Tp_matrices(ulong p)
+{
+  GEN v = cgetg(p+2, t_VEC);
+  ulong i;
+  for (i = 1; i <= p; i++) gel(v,i) = mat2(1, i-1, 0, p);
+  gel(v,i) = mat2(p, 0, 0, 1);
+  return v;
+}
+static GEN
+Up_matrices(ulong p)
+{
+  GEN v = cgetg(p+1, t_VEC);
+  ulong i;
+  for (i = 1; i <= p; i++) gel(v,i) = mat2(1, i-1, 0, p);
+  return v;
+}
+static GEN
+msendo(GEN W, GEN v)
+{
+  return msk_get_weight(W) == 2? getMorphism_trivial(W,W,v)
+                               : getMorphism(W, W, v);
+}
+static GEN
+endo_project(GEN W, GEN e, GEN H)
+{
+  if (H) H = Qevproj_init0(H);
+  else if (msk_get_sign(W))
+    H = msk_get_starproj(W);
+  if (H) e = Qevproj_apply(e, H);
+  return e;
+}
+static GEN
+mshecke_i(GEN W, ulong p)
+{
+  GEN v = ms_get_N(W) % p? Tp_matrices(p): Up_matrices(p);
+  return msendo(W,v);
+}
+GEN
+mshecke(GEN W, long p, GEN H)
+{
+  pari_sp av = avma;
+  GEN T;
+  checkms(W);
+  if (p <= 1) pari_err_PRIME("mshecke",stoi(p));
+  T = mshecke_i(W,p);
+  T = endo_project(W,T,H);
+  if (msk_get_weight(W) == 2) T = shallowtrans(T);
+  return gerepilecopy(av, T);
+}
+
+static GEN
+msatkinlehner_i(GEN W, long Q)
+{
+  long w, z, d, N = ms_get_N(W), M = N / Q;
+  GEN v;
+  if (Q == 1) return matid(msk_get_dim(W));
+  d = cbezout(Q, -M, &w, &z);
+  if (N % Q) pari_err_DOMAIN("msatkinlehner","N % Q","!=",gen_0,stoi(Q));
+  if (d != 1) pari_err_DOMAIN("msatkinlehner","gcd(Q,N/Q)","!=",gen_1,stoi(Q));
+  v = (Q == N)? mat2(0,1,-N,0): mat2(Q,1,N*z,Q*w);
+  return msendo(W,v);
+}
+GEN
+msatkinlehner(GEN W, long Q, GEN H)
+{
+  pari_sp av = avma;
+  GEN w;
+  long k;
+  checkms(W);
+  k = msk_get_weight(W);
+  if (Q <= 0) pari_err_DOMAIN("msatkinlehner","Q","<=",gen_0,stoi(Q));
+  w = msatkinlehner_i(W,Q);
+  w = endo_project(W,w,H);
+  if (k == 2) w = shallowtrans(w);
+  else if (Q != 1)
+    w = RgM_Rg_div(w, powuu(Q,(k-2)>>1));
+  return gerepilecopy(av, w);
+}
+
+static GEN
+msstar_i(GEN W)
+{
+  GEN v = mat2(-1,0,0,1);
+  return msendo(W,v);
+}
+GEN
+msstar(GEN W, GEN H)
+{
+  pari_sp av = avma;
+  GEN s;
+  checkms(W);
+  s = msstar_i(W);
+  s = endo_project(W,s,H);
+  if (msk_get_weight(W) == 2) s = shallowtrans(s);
+  return gerepilecopy(av, s);
+}
+
+#if 0
+/* is \Gamma_0(N) cusp1 = \Gamma_0(N) cusp2 ? */
+static int
+iscuspeq(ulong N, GEN cusp1, GEN cusp2)
+{
+  long p1, q1, p2, q2, s1, s2, d;
+  p1 = cusp1[1]; p2 = cusp2[1];
+  q1 = cusp1[2]; q2 = cusp2[2];
+  d = Fl_mul(smodss(q1,N),smodss(q2,N), N);
+  d = ugcd(d, N);
+
+  s1 = q1 > 2? Fl_inv(smodss(p1,q1), q1): 1;
+  s2 = q2 > 2? Fl_inv(smodss(p2,q2), q2): 1;
+  return Fl_mul(s1,q2,d) == Fl_mul(s2,q1,d);
+}
+#endif
+
+static GEN
+mscuspidal_trivial(GEN W0)
+{
+  pari_sp av = avma;
+  GEN W = get_ms(W0);
+  GEN section = ms_get_section(W), gen = ms_get_genindex(W);
+  GEN S = ms_get_hashcusps(W);
+  long j, nbE1 = ms_get_nbE1(W), ncusp = gel(S,1)[2];
+  GEN T = zeromatcopy(ncusp,nbE1);
+  for (j = 1; j <= nbE1; j++)
+  {
+    long e = gen[j]; /* path-index of E1-element */
+    GEN t = gel(section, e); /* path_to_zm() */
+    long i1 = cusp_index(gel(t,1), S);
+    long i2 = cusp_index(gel(t,2), S);
+    if (i1 != i2)
+    {
+      gcoeff(T, i1, j) = gen_1;
+      gcoeff(T, i2, j) = gen_m1;
+    }
+  }
+  return gerepilecopy(av, ZM_ker(T));
+}
+
+/* return E_c(r) */
+static GEN
+get_Ec_r(GEN c, long k)
+{
+  long p = c[1], q = c[2], u, v;
+  GEN gr;
+  (void)cbezout(p, q, &u, &v);
+  gr = mat2(p, -v, q, u); /* g . (1:0) = (p:q) */
+  return voo_act_Gl2Q(zm_to_ZM(sl2_inv(gr)), k);
+}
+/* returns the modular symbol associated to the cusp c := p/q via the rule
+ * E_c(path from a to b in Delta_0) := E_c(b) - E_c(a), where
+ * E_c(r) := 0 if r != c mod Gamma
+ *           v_oo | gamma_r^(-1)
+ * where v_oo is stable by T = [1,1;0,1] (i.e x^(k-2)) and
+ * gamma_r . (1:0) = r, for some gamma_r in SL_2(Z) * */
+GEN
+Eisenstein_symbol(GEN W, GEN c)
+{
+  GEN section = ms_get_section(W), gen = ms_get_genindex(W);
+  GEN S = ms_get_hashcusps(W);
+  long j, ic = cusp_index(c, S), l = lg(gen), k = msk_get_weight(W);
+  GEN vecT = cgetg(l, t_COL);
+  for (j = 1; j < l; j++)
+  {
+    GEN vj = NULL, g = gel(section, gen[j]); /* path_to_zm(generator) */
+    GEN c1 = gel(g,1), c2 = gel(g,2);
+    long i1 = cusp_index(c1, S);
+    long i2 = cusp_index(c2, S);
+    if (i1 == ic) vj = get_Ec_r(c1, k);
+    if (i2 == ic)
+    {
+      GEN s = get_Ec_r(c2, k);
+      vj = vj? gsub(vj, s): gneg(s);
+    }
+    if (!vj) vj = zerocol(k-1);
+    gel(vecT, j) = vj;
+  }
+  return getMorphism_basis(W, vecT);
+}
+
+static GEN
+EC_subspace_trivial(GEN W)
+{
+  GEN M, ch, chC, chE, T, TC, C = mscuspidal_trivial(W);
+  long N = ms_get_N(W);
+  ulong p;
+  forprime_t S;
+  (void)u_forprime_init(&S, 2, ULONG_MAX);
+  while ((p = u_forprime_next(&S)))
+    if (N % p) break;
+  T = mshecke_i(W, p);
+  ch = QM_charpoly_ZX(T);
+  TC = Qevproj_apply(T, Qevproj_init(C)); /* T_p | TC */
+  chC = QM_charpoly_ZX(TC);
+  chE = RgX_div(ch, chC); /* charpoly(T_p | E_k), coprime to chC */
+  M = RgX_RgM_eval(chE, T);
+  return mkvec2(Qevproj_star(W, QM_ker(M)), C);
+}
+
+static GEN
+mseisenstein_trivial(GEN W)
+{
+  GEN ES = EC_subspace_trivial(W);
+  return gel(ES,1);
+}
+static GEN
+mseisenstein_i(GEN W)
+{
+  GEN S, cusps, M;
+  long i, l;
+  if (msk_get_weight(W) == 2) return mseisenstein_trivial(W);
+  S = ms_get_hashcusps(W);
+  cusps = gel(S,3);
+  l = lg(cusps);
+  M = cgetg(l, t_MAT);
+  for (i = 1; i < l; i++) gel(M,i) = Eisenstein_symbol(W, gel(cusps,i));
+  return Qevproj_star(W, QM_image(M));
+}
+GEN
+mseisenstein(GEN W)
+{
+  pari_sp av = avma;
+  checkms(W);
+  return gerepilecopy(av, Qevproj_init(mseisenstein_i(W)));
+}
+
+/* upper bound for log_2 |charpoly(T_p|S)|, where S is a cuspidal subspace of
+ * dimension d, k is the weight */
+static long
+TpS_char_bound(ulong p, long k, long d)
+{ /* |eigenvalue| <= 2 p^(k-1)/2 */
+  return d * (2 + (log2((double)p)*(k-1))/2);
+}
+
+/* return [E,S] */
+static GEN
+mscuspidal_i(GEN W)
+{
+  GEN E, M, T, TE, chS;
+  long k = msk_get_weight(W), bit;
+  forprime_t S;
+  ulong p, N;
+  if (k == 2) return EC_subspace_trivial(W);
+  E = mseisenstein_i(W);
+  N = ms_get_N(W);
+  (void)u_forprime_init(&S, 2, ULONG_MAX);
+  while ((p = u_forprime_next(&S)))
+    if (N % p) break;
+  T = mshecke_i(W, p);
+  TE = Qevproj_apply(T, Qevproj_init(E)); /* T_p | E */
+  bit = TpS_char_bound(p, k, msk_get_dim(W) - (lg(TE)-1));
+  chS = QM_charpoly_ZX2_bound(T,TE,bit); /* charpoly(T_p | S_k) */
+  M = RgX_RgM_eval(chS, T);
+  return mkvec2(E, Qevproj_star(W, QM_ker(M)));
+}
+GEN
+mscuspidal(GEN W, long flag)
+{
+  pari_sp av = avma;
+  GEN v, S, E;
+  checkms(W);
+  v = mscuspidal_i(W);
+  E = gel(v,1);
+  S = gel(v,2); S = Qevproj_init(S);
+  if (flag)
+  { /* swap arguments to return [S,E] */
+    E = Qevproj_init(E);
+    v = mkvec2(S,E);
+  }
+  else
+    v = S;
+  return gerepilecopy(av, v);
+}
+
+/** INIT ELLSYM STRUCTURE **/
+/* V a vector of ZM. If all of them have 0 last row, return NULL.
+ * Otherwise return [m,i,j], where m = V[i][last,j] contains the value
+ * of smallest absolute value */
+static GEN
+RgMV_find_non_zero_last_row(long offset, GEN V)
+{
+  long i, lasti = 0, lastj = 0, lV = lg(V);
+  GEN m = NULL;
+  for (i = 1; i < lV; i++)
+  {
+    GEN M = gel(V,i);
+    long j, n, l = lg(M);
+    if (l == 1) continue;
+    n = nbrows(M);
+    for (j = 1; j < l; j++)
+    {
+      GEN a = gcoeff(M, n, j);
+      if (!gcmp0(a) && (!m || absi_cmp(a, m) < 0))
+      {
+        m = a; lasti = i; lastj = j;
+        if (is_pm1(m)) goto END;
+      }
+    }
+  }
+END:
+  if (!m) return NULL;
+  return mkvec2(m, mkvecsmall2(lasti+offset, lastj));
+}
+/* invert the d_oo := (\gamma_oo - 1) operator, acting on
+ * [x^(k-2), ..., y^(k-2)] */
+static GEN
+Delta_inv(GEN doo, long k)
+{
+  GEN M = RgX_act_ZGl2Q(doo, k);
+  M = RgM_minor(M, k-1, 1); /* 1st column and last row are 0 */
+  return ZM_inv_denom(M);
+}
+/* The ZX P = \sum a_i x^i y^{k-2-i} is given by the ZV [a_0, ..., a_k-2]~,
+ * return Q and d such that P = doo Q + d y^k-2, where d in Z and Q */
+static GEN
+doo_decompose(GEN dinv, GEN P, GEN *pd)
+{
+  long l = lg(P); *pd = gel(P, l-1);
+  P = vecslice(P, 1, l-2);
+  return shallowconcat(gen_0, ZC_apply_dinv(dinv, P));
+}
+
+static GEN
+get_phi_ij(long i,long j,long n, long s,long t,GEN P_st,GEN Q_st,GEN d_st,
+           GEN P_ij, GEN lP_ij, GEN dinv)
+{
+  GEN ind, pols;
+  if (i == s && j == t)
+  {
+    ind = mkvecsmall(1);
+    pols = mkvec(scalarcol_shallow(gen_1, lg(P_st)-1)); /* x^{k-2} */
+  }
+  else
+  {
+    GEN d_ij, Q_ij = doo_decompose(dinv, lP_ij, &d_ij);
+    GEN a = ZC_Z_mul(P_ij, d_st);
+    GEN b = ZC_Z_mul(P_st, negi(d_ij));
+    GEN c = RgC_sub(RgC_Rg_mul(Q_ij, d_st), RgC_Rg_mul(Q_st, d_ij));
+    if (i == s) { /* j != t */
+      ind = mkvecsmall2(1, s);
+      pols = mkvec2(c, ZC_add(a, b));
+    } else {
+      ind = mkvecsmall3(1, i, s);
+      pols = mkvec3(c, a, b); /* image of g_1, g_i, g_s */
+    }
+  }
+  return mkvec3(mkvecsmall3(i,j,n), ind, pols);
+}
+
+static GEN
+mskinit_trivial(GEN WN)
+{
+  long dim = ms_get_nbE1(WN);
+  return mkvec3(WN, gen_0, mkvec2(gen_0,mkvecsmall2(2, dim)));
+}
+/* sum of #cols of the matrices contained in V */
+static long
+RgMV_dim(GEN V)
+{
+  long l = lg(V), d = 0, i;
+  for (i = 1; i < l; i++) d += lg(gel(V,i)) - 1;
+  return d;
+}
+static GEN
+mskinit_nontrivial(GEN WN, long k)
+{
+  GEN annT2 = gel(WN,8), annT31 = gel(WN,9), singlerel = gel(WN,10);
+  GEN link, basis, monomials, invphiblock;
+  long nbE1 = ms_get_nbE1(WN);
+  GEN dinv = Delta_inv(ZG_neg( ZGl2Q_star(gel(singlerel,1)) ), k);
+  GEN p1 = cgetg(nbE1+1, t_VEC), remove;
+  GEN p2 = ZGV_tors(annT2, k);
+  GEN p3 = ZGV_tors(annT31, k);
+  GEN gentor = shallowconcat(p2, p3);
+  GEN P_st, lP_st, Q_st, d_st;
+  long n, i, dim, s, t, u;
+  gel(p1, 1) = cgetg(1,t_MAT); /* dummy */
+  for (i = 2; i <= nbE1; i++) /* skip 1st element = (\gamma_oo-1)g_oo */
+  {
+    GEN z = gel(singlerel, i);
+    gel(p1, i) = RgX_act_ZGl2Q(ZGl2Q_star(z), k);
+  }
+  remove = RgMV_find_non_zero_last_row(nbE1, gentor);
+  if (!remove) remove = RgMV_find_non_zero_last_row(0, p1);
+  if (!remove) pari_err_BUG("msinit [no y^k-2]");
+  remove = gel(remove,2); /* [s,t] */
+  s = remove[1];
+  t = remove[2];
+  /* +1 because of = x^(k-2), but -1 because of Manin relation */
+  dim = (k-1)*(nbE1-1) + RgMV_dim(p2) + RgMV_dim(p3);
+  /* Let (g_1,...,g_d) be the Gamma-generators of Delta, g_1 = g_oo.
+   * We describe modular symbols by the collection phi(g_1), ..., phi(g_d)
+   * \in V := Q[x,y]_{k-2}, with right Gamma action.
+   * For each i = 1, .., d, let V_i \subset V be the Q-vector space of
+   * allowed values for phi(g_i): with basis (P^{i,j}) given by the monomials
+   * x^(j-1) y^{k-2-(j-1)}, j = 1 .. k-1
+   * (g_i in E_1) or the solution of the torsion equations (1 + gamma)P = 0
+   * (g_i in T2) or (1 + gamma + gamma^2)P = 0 (g_i in T31).
+   *
+   * The Manin relation (singlerel) is of the form \sum_i \lambda_i g_i = 0,
+   * where \lambda_i = 1 if g_i in T2 or T31, and \lambda_i = (1 - \gamma_i)
+   * for g_i in E1.
+   *
+   * If phi \in Hom_Gamma(Delta, V), it is defined by phi(g_i) := P_i in V
+   * with \sum_i P_i . \lambda_i^* = 0, where (\sum n_i g_i)^* :=
+   * \sum n_i \gamma_i^(-1).
+   *
+   * We single out gamma_1 / g_1 (g_oo in Pollack-Stevens paper) and
+   * write P_{i,j} \lambda_i^* =  Q_{i,j} (\gamma_1 - 1)^* + d_{i,j} y^{k-2}
+   * where d_{i,j} is a scalar and Q_{i,j} in V; we normalize Q_{i,j} to
+   * that the coefficient of x^{k-2} is 0.
+   *
+   * There exist (s,t) such that d_{s,t} != 0.
+   * A Q-basis of the (dual) space of modular symbols is given by the
+   * functions phi_{i,j}, 2 <= i <= d, 1 <= j <= k-1, mapping
+   *  g_1 -> d_{s,t} Q_{i,j} - d_{i,j} Q_{s,t} + [(i,j)=(s,t)] x^{k-2}
+   * If i != s
+   *   g_i -> d_{s,t} P_{i,j}
+   *   g_s -> - d_{i,j} P_{s,t}
+   * If i = s, j != t
+   *   g_i -> d_{s,t} P_{i,j} - d_{i,j} P_{s,t}
+   * And everything else to 0. */
+  monomials = matid(k-1); /* represent the monomials x^{k-2}, ... , y^{k-2} */
+  if (s <= nbE1) /* in E1 */
+  {
+    P_st = gel(monomials, t);
+    lP_st = gmael(p1, s, t); /* P_{s,t} lambda_s^* */
+  }
+  else /* in T2, T31 */
+  {
+    P_st = gmael(gentor, s - nbE1, t);
+    lP_st = P_st;
+  }
+  Q_st = doo_decompose(dinv, lP_st, &d_st);
+  basis = cgetg(dim+1, t_VEC);
+  link = cgetg(nbE1 + lg(gentor), t_VEC);
+  gel(link,1) = cgetg(1,t_VECSMALL); /* dummy */
+  n = 1;
+  for (i = 2; i <= nbE1; i++)
+  {
+    GEN L = cgetg(k, t_VECSMALL);
+    long j;
+    /* link[i][j] = n gives correspondance between phi_{i,j} and basis[n] */
+    gel(link,i) = L;
+    for (j = 1; j < k; j++)
+    {
+      GEN lP_ij = gmael(p1, i, j); /* P_{i,j} lambda_i^* */
+      GEN P_ij = gel(monomials,j);
+      L[j] = n;
+      gel(basis, n) = get_phi_ij(i,j,n, s,t, P_st, Q_st, d_st, P_ij, lP_ij, dinv);
+      n++;
+    }
+  }
+  for (u = 1; u < lg(gentor); u++,i++)
+  {
+    GEN V = gel(gentor,u);
+    long j, lV = lg(V);
+    GEN L = cgetg(lV, t_VECSMALL);
+    gel(link,i) = L;
+    for (j = 1; j < lV; j++)
+    {
+      GEN lP_ij = gel(V, j); /* P_{i,j} lambda_i^* = P_{i,j} */
+      GEN P_ij = lP_ij;
+      L[j] = n;
+      gel(basis, n) = get_phi_ij(i,j,n, s,t, P_st, Q_st, d_st, P_ij, lP_ij, dinv);
+      n++;
+    }
+  }
+  invphiblock = cgetg(lg(link), t_VEC);
+  gel(invphiblock,1) = cgetg(1, t_MAT); /* dummy */
+  for (i = 2; i < lg(link); i++)
+  {
+    GEN M, inv, B = gel(link,i);
+    long j, lB = lg(B);
+    if (i == s) { B = vecsplice(B, t); lB--; } /* remove phi_st */
+    M = cgetg(lB, t_MAT);
+    for (j = 1; j < lB; j++)
+    {
+      GEN phi_ij = gel(basis, B[j]), pols = gel(phi_ij,3);
+      gel(M, j) = gel(pols, 2); /* phi_ij(g_i) */
+    }
+    if (i <= nbE1 && i != s) /* maximal rank k-1 */
+      inv = ZM_inv_denom(M);
+    else /* i = s (rank k-2) or from torsion: rank k/3 or k/2 */
+      inv = Qevproj_init(M);
+    gel(invphiblock,i) = inv;
+  }
+  return mkvec3(WN, gen_0, mkvec5(basis, mkvecsmall2(k, dim), mkvecsmall2(s,t),
+                                  link, invphiblock));
+}
+static GEN
+add_star(GEN W, long sign)
+{
+  GEN s = msstar_i(W);
+  GEN K = sign? QM_ker(gsubgs(s, sign)): cgetg(1,t_MAT);
+  gel(W,2) = mkvec3(stoi(sign), s, Qevproj_init(K));
+  return W;
+}
+/* WN = msinit_N(N) */
+static GEN
+mskinit(ulong N, long k, long sign)
+{
+  GEN WN = msinit_N(N);
+  GEN W = k == 2? mskinit_trivial(WN)
+                : mskinit_nontrivial(WN, k);
+  return add_star(W, sign);
+}
+GEN
+msinit(GEN N, GEN K, long sign)
+{
+  pari_sp av = avma;
+  GEN W;
+  long k;
+  if (typ(N) != t_INT) pari_err_TYPE("msinit", N);
+  if (typ(K) != t_INT) pari_err_TYPE("msinit", K);
+  k = itos(K);
+  if (k < 2) pari_err_DOMAIN("msinit","k", "<", gen_2,K);
+  if (odd(k)) pari_err_IMPL("msinit [odd weight]");
+  if (signe(N) <= 0) pari_err_DOMAIN("msinit","N", "<=", gen_0,N);
+  if (equali1(N)) pari_err_IMPL("msinit [ N = 1 ]");
+  W = mskinit(itou(N), k, sign);
+  return gerepilecopy(av, W);
+}
+
+/* W = msinit, xpm modular symbol attached to elliptic curve E;
+ * c t_FRAC; image of <oo->c> */
+GEN
+Q_xpm(GEN W, GEN xpm, GEN c)
+{
+  pari_sp av = avma;
+  GEN v;
+  W = get_ms(W);
+  v = init_act_trivial(W);
+  Q_log_trivial(v, W, c); /* oo -> (a:b), c = a/b */
+  return gerepileuptoint(av, RgV_dotproduct(xpm,v));
+}
+
+/* Evaluate symbol s on mspathlog B (= sum p_i g_i, p_i in Z[G]) */
+static GEN
+mseval_by_values(GEN W, GEN s, GEN p)
+{
+  long i, l, k = msk_get_weight(W);
+  GEN A, B;
+
+  if (k == 2)
+  { /* trivial represention: don't bother with Z[G] */
+    B = mspathlog_trivial(W,p);
+    return RgV_dotproduct(s,B);
+  }
+
+  A = cgetg_copy(s,&l);
+  B = mspathlog(W,p);
+  for (i=1; i<l; i++) gel(A,i) = ZGl2Q_act_s(gel(B,i), gel(s,i), k);
+  return RgV_sum(A);
+}
+/* evaluate symbol s on path p */
+GEN
+mseval(GEN W, GEN s, GEN p)
+{
+  pari_sp av = avma;
+  long i, k, l, nbgen, v = 0;
+  GEN e;
+  checkms(W);
+  k = msk_get_weight(W);
+  nbgen = ms_get_nbgen(W);
+  switch(typ(s))
+  {
+    case t_VEC: /* values s(g_i) */
+      if (lg(s)-1 != nbgen) pari_err_TYPE("mseval",s);
+      if (!p) return gcopy(s);
+      v = gvar(s);
+      break;
+    case t_COL:
+      if (k == 2) /* on the dual basis of (g_i) */
+      {
+        if (lg(s)-1 != ms_get_nbE1(W)) pari_err_TYPE("mseval",s);
+        if (!p) return gtrans(s);
+      }
+      else
+      { /* on the basis phi_{i,j} */
+        GEN basis = msk_get_basis(W);
+        l = lg(basis);
+        if (lg(s) != l) pari_err_TYPE("mseval",s);
+        e = const_vec(nbgen, gen_0);
+        for (i=1; i<l; i++)
+        {
+          GEN phi, ind, pols, c = gel(s,i);
+          long j, m;
+          if (gequal0(c)) continue;
+          phi = gel(basis,i);
+          ind = gel(phi,2); m = lg(ind);
+          pols = gel(phi,3);
+          for (j=1; j<m; j++) {
+            long t = ind[j];
+            gel(e,t) = gadd(gel(e,t), gmul(c, gel(pols,j)));
+          }
+        }
+        s = e;
+      }
+      break;
+    default: pari_err_TYPE("mseval",s);
+  }
+  if (p)
+  {
+    s = mseval_by_values(W,s,p);
+    if (k != 2 && is_vec_t(typ(s))) s = RgV_to_RgX(s, v);
+  }
+  else
+  {
+    l = lg(s);
+    for (i = 1; i < l; i++)
+    {
+      GEN c = gel(s,i);
+      if (!isintzero(c)) gel(s,i) = RgV_to_RgX(gel(s,i), v);
+    }
+  }
+  return gerepilecopy(av, s);
+}
+
+static GEN
+twistcurve(GEN e, GEN D)
+{
+  GEN D2 = sqri(D);
+  GEN a4 = mulii(mulsi(-27, D2), ell_get_c4(e));
+  GEN a6 = mulii(mulsi(-54, mulii(D, D2)), ell_get_c6(e));
+  return ellinit(mkvec2(a4,a6),NULL,DEFAULTPREC);
+}
+
+/* sum_{a <= |D|} (D/a)*xpm(E,a/|D|) */
+static GEN
+get_X(GEN W, GEN xpm, long D)
+{
+  ulong a, d = (ulong)labs(D);
+  GEN t = gen_0;
+  GEN nc, c;
+  if (d == 1) return Q_xpm(W, xpm, gen_0);
+  nc = icopy(gen_1);
+  c = mkfrac(nc, utoipos(d));
+  for (a=1; a < d; a++)
+  {
+    long s = kross(D,a);
+    GEN x;
+    if (!s) continue;
+    nc[2] = a; x = Q_xpm(W, xpm, c);
+    t = (s > 0)? addii(t, x): subii(t, x);
+  }
+  return t;
+}
+/* quotient of the Neron periods of E^(d) and E, divided by sqrt(d) */
+static long
+get_alpha_d(GEN E, long d)
+{
+  if (odd(d)) return 1;
+  if (!mpodd(ell_get_c4(E))) return 2; /* additive reduction at 2 */
+  /* reduction not additive */
+  return (d % 8 == 0 && !mpodd(ell_get_a1(E)))? 2: 1;
+}
+/* write L(E,1) = Q*w1, return the rational Q */
+static GEN
+get_Q(GEN E)
+{
+  GEN L, N, tam, T, n, w1;
+  long ex, t, t2;
+  E = ellanal_globalred_all(E, NULL, &N, &tam);
+  T = elltors(E); t = itos(gel(T,1)); t2 = t*t;
+  w1 = gel(ellR_omega(E,DEFAULTPREC), 1);
+
+  /* |Sha| = n^2 */
+  L = ellL1(E, 0, DEFAULTPREC);
+  n = sqrtr(divrr(mulru(L, t2), mulri(w1,tam)));
+  n = grndtoi(n, &ex);
+  if (ex > -5) pari_err_BUG("msfromell (can't compute analytic |Sha|)");
+  return gdivgs(mulii(tam,sqri(n)), t2);
+}
+
+/* return C such that C*L(E,1)_{xpm} = L(E,1) / w1 */
+static GEN
+ell_get_scale(GEN E, GEN W, GEN xpm, long s)
+{
+  GEN Q, X = NULL;
+  long d, N = ms_get_N(W);
+
+  /* find D = s*d such that twist by D has rank 0 */
+  for (d = 1; d < LONG_MAX; d++)
+  {
+    pari_sp av = avma;
+    if (cgcd(N, d) != 1) continue;
+    if (s < 0)
+    { if (!unegisfundamental(d)) continue; }
+    else
+    { if (!uposisfundamental(d)) continue; }
+    X = get_X(W, xpm, s < 0? -d: d);
+    if (signe(X)) break;
+    avma = av;
+  }
+  if (d == LONG_MAX) pari_err_BUG("msfromell (no suitable twist)");
+  if (s < 0) d = -d;
+  Q = get_Q(twistcurve(E, stoi(d)));
+  return gdiv(gmulsg(get_alpha_d(E,d), Q), X);
+}
+
+GEN
+msfromell(GEN E, long sign)
+{
+  pari_sp av = avma;
+  GEN cond;
+  GEN W, K, x, scale;
+  ulong p, N;
+  forprime_t T;
+
+  if (labs(sign) != 1)
+    pari_err_DOMAIN("msfromell","abs(sign)","!=",gen_1,stoi(sign));
+  E = ellminimalmodel(E, NULL);
+  cond = gel(ellglobalred(E), 1);
+  N = itou(cond);
+  W = mskinit(N, 2, sign);
+  /* linear form = 0 on Im(S - sign) */
+  K = keri(shallowtrans(gsubgs(msk_get_star(W), sign)));
+
+  /* loop for p <= count_Manin_symbols(N) / 6 would be enough */
+  (void)u_forprime_init(&T, 2, ULONG_MAX);
+  while( (p = u_forprime_next(&T)) )
+  {
+    GEN Tp, ap, M, K2;
+    if (N % p == 0) continue;
+    Tp = mshecke_i(W, p);
+    ap = ellap(E, utoipos(p));
+    M = RgM_Rg_add_shallow(Tp, negi(ap));
+    K2 = keri( ZM_mul(shallowtrans(M), K) );
+    if (lg(K2) < lg(K)) K = ZM_mul(K, K2);
+    if (lg(K2)-1 == 1) break;
+  }
+  if (!p) pari_err_BUG("msfromell: ran out of primes");
+  /* linear form = 0 on all Im(Tp - ap) and Im(S - sign) */
+  x = Q_primpart(gel(K,1));
+  scale = ell_get_scale(E, W, x, sign);
+  gmael(W,2,1) = gen_0;
+  gmael(W,2,3) = Qevproj_init(cgetg(1,t_MAT));
+  return gerepilecopy(av, mkvec2(W, RgC_Rg_mul(x, scale)));
+}
diff --git a/src/basemath/nffactor.c b/src/basemath/nffactor.c
index fa71439..f996dd0 100644
--- a/src/basemath/nffactor.c
+++ b/src/basemath/nffactor.c
@@ -153,7 +153,7 @@ FpX_ratlift(GEN P, GEN mod, GEN amax, GEN bmax, GEN denom)
 GEN
 nfgcd_all(GEN P, GEN Q, GEN T, GEN den, GEN *Pnew)
 {
-  pari_sp btop, st_lim, ltop = avma;
+  pari_sp btop, ltop = avma;
   GEN lP, lQ, M, dsol, R, bo, sol, mod = NULL;
   long vP = varn(P), vT = varn(T), dT = degpol(T), dM = 0, dR;
   forprime_t S;
@@ -168,7 +168,7 @@ nfgcd_all(GEN P, GEN Q, GEN T, GEN den, GEN *Pnew)
     den = mulii(den, gcdii(ZX_resultant(lP, T), ZX_resultant(lQ, T)));
 
   init_modular(&S);
-  btop = avma; st_lim = stack_lim(btop, 1);
+  btop = avma;
   for(;;)
   {
     ulong p = u_forprime_next(&S);
@@ -187,7 +187,7 @@ nfgcd_all(GEN P, GEN Q, GEN T, GEN den, GEN *Pnew)
     R = FlxX_to_Flm(R, dT);
     /* previous primes divided Res(P/gcd, Q/gcd)? Discard them. */
     if (!mod || dR < dM) { M = ZM_init_CRT(R, p); mod = utoipos(p); dM = dR; continue; }
-    if (low_stack(st_lim, stack_lim(btop, 1)))
+    if (gc_needed(btop, 1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"nfgcd");
       gerepileall(btop, 2, &M, &mod);
@@ -218,6 +218,23 @@ GEN
 nfgcd(GEN P, GEN Q, GEN T, GEN den)
 { return nfgcd_all(P,Q,T,den,NULL); }
 
+int
+nfissquarefree(GEN nf, GEN x)
+{
+  pari_sp av = avma;
+  GEN g, y = RgX_deriv(x);
+  if (RgX_is_rational(x))
+    g = QX_gcd(x, y);
+  else
+  {
+    GEN T = get_nfpol(nf,&nf);
+    x = liftpol_shallow(x);
+    y = liftpol_shallow(y);
+    g = nfgcd(x, y, T, nf? nf_get_index(nf): NULL);
+  }
+  avma = av; return (degpol(g) == 0);
+}
+
 /*******************************************************************/
 /*             FACTOR OVER (Z_K/pr)[X] --> FqX_factor              */
 /*******************************************************************/
@@ -340,7 +357,7 @@ get_nfsqff_data(GEN *pnf, GEN *pT, GEN *pA, GEN *pB, GEN *ptbad)
     }
   }
   (void)nfgcd_all(A, RgX_deriv(A), T, bad, pB);
-  if( ptbad) *ptbad = bad;
+  if (ptbad) *ptbad = bad;
   return den;
 }
 
@@ -359,7 +376,7 @@ nfroots(GEN nf,GEN pol)
 {
   pari_sp av = avma;
   GEN z, A, B, T, den;
-  long d;
+  long d, dT;
 
   if (!nf) return nfrootsQ(pol);
   T = get_nfpol(nf, &nf);
@@ -374,13 +391,28 @@ nfroots(GEN nf,GEN pol)
     A = mkpolmod(gneg_i(gel(A,2)), T);
     return gerepilecopy(av, mkvec(A));
   }
-  if (degpol(T) == 1) return gerepileupto(av, nfrootsQ(simplify_shallow(A)));
+  dT = degpol(T);
+  if (dT == 1) return gerepileupto(av, nfrootsQ(simplify_shallow(A)));
 
   A = Q_primpart(A);
   den = get_nfsqff_data(&nf, &T, &A, &B, NULL);
   if (degpol(B) != d) B = Q_primpart( QXQX_normalize(B, T) );
   ensure_lt_INT(B);
-  z = nfsqff(nf,B, ROOTS, den);
+  if (RgX_is_ZX(B))
+  {
+    GEN v = gel(ZX_factor(B), 1);
+    long i, l = lg(v), p = mael(factoru(dT),1,1); /* smallest prime divisor */
+    z = cgetg(1, t_VEC);
+    for (i = 1; i < l; i++)
+    {
+      GEN b = gel(v,i); /* irreducible / Q */
+      long db = degpol(b);
+      if (db != 1 && degpol(b) < p) continue;
+      z = shallowconcat(z, nfsqff(nf, b, ROOTS, den));
+    }
+  }
+  else
+    z = nfsqff(nf,B, ROOTS, den);
   z = gerepileupto(av, QXQV_to_mod(z, T));
   gen_sort_inplace(z, (void*)&cmp_RgX, &cmp_nodata, NULL);
   return z;
@@ -449,16 +481,16 @@ nf_bestlift_to_pol(GEN elt, GEN bound, nflift_t *L)
 /* return the T->powden * (lift of pol with coefficients of T2-norm <= C)
  * if it exists. */
 static GEN
-nf_pol_lift(GEN pol, GEN bound, nfcmbf_t *T)
+nf_pol_lift(GEN pol, GEN bound, nflift_t *L)
 {
   long i, l = lg(pol);
-  GEN t, x = cgetg(l,t_POL);
+  GEN x = cgetg(l,t_POL);
 
   x[1] = pol[1];
-  gel(x,l-1) = mul_content(gel(pol,l-1), T->L->topowden);
+  gel(x,l-1) = mul_content(gel(pol,l-1), L->topowden);
   for (i=l-2; i>1; i--)
   {
-    t = nf_bestlift_to_pol(gel(pol,i), bound, T->L);
+    GEN t = nf_bestlift_to_pol(gel(pol,i), bound, L);
     if (!t) return NULL;
     gel(x,i) = t;
   }
@@ -571,6 +603,19 @@ nffactor(GEN nf,GEN pol)
   if (DEBUGLEVEL>2) timer_printf(&ti, "squarefree test");
   if (degpol(B) != dA) B = Q_primpart( QXQX_normalize(B, T) );
   ensure_lt_INT(B);
+  if (RgX_is_ZX(B))
+  {
+    GEN v = gel(ZX_factor(B), 1);
+    long i, l = lg(v);
+    y = cgetg(1, t_VEC);
+    for (i = 1; i < l; i++)
+    {
+      GEN b = gel(v,i); /* irreducible / Q */
+      y = shallowconcat(y, nfsqff(nf, b, 0, den));
+    }
+  }
+  else
+    y = nfsqff(nf,B, 0, den);
   y = nfsqff(nf,B, 0, den);
   if (DEBUGLEVEL>3) err_printf("number of factor(s) found: %ld\n", lg(y)-1);
 
@@ -1041,7 +1086,7 @@ nextK:
         if (y) q = gmul(y, q);
         y = FqX_centermod(q, Tpk, pk, pks2);
       }
-      y = nf_pol_lift(y, bound, T);
+      y = nf_pol_lift(y, bound, T->L);
       if (!y)
       {
         if (DEBUGLEVEL>3) err_printf("@");
@@ -1146,7 +1191,7 @@ nf_chk_factors(nfcmbf_t *T, GEN P, GEN M_L, GEN famod, GEN pk)
     if (DEBUGLEVEL) err_printf("nf_LLL_cmbf: checking factor %ld\n", i);
     y = chk_factors_get(D.lt, famod, gel(piv,i), Tpk, pk);
 
-    if (! (y = nf_pol_lift(y, bound, T)) ) return NULL;
+    if (! (y = nf_pol_lift(y, bound, T->L)) ) return NULL;
     y = gerepilecopy(av, y);
     /* y is the candidate factor */
     pol = RgXQX_divrem(D.C2ltpol, y, nfT, ONLY_DIVIDES);
@@ -1336,7 +1381,7 @@ nf_LLL_cmbf(nfcmbf_t *T, long rec)
   long i, C, tmax, n0;
   GEN lP, Bnorm, Tra, T2, TT, CM_L, m, list, ZERO, Btra;
   double Bhigh;
-  pari_sp av, av2, lim;
+  pari_sp av, av2;
   long ti_LLL = 0, ti_CF = 0;
   pari_timer ti2, TI;
 
@@ -1353,7 +1398,7 @@ nf_LLL_cmbf(nfcmbf_t *T, long rec)
   Bnorm = dbltor( n0 * C * C + Bhigh );
   ZERO = zeromat(n0, dnf);
 
-  av = avma; lim = stack_lim(av, 1);
+  av = avma;
   TT = cgetg(n0+1, t_VEC);
   Tra  = cgetg(n0+1, t_MAT);
   for (i=1; i<=n0; i++) TT[i] = 0;
@@ -1466,7 +1511,7 @@ AGAIN:
       if (list) break;
     }
     CM_L = gerepilecopy(av2, CM_L);
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"nf_LLL_cmbf");
       gerepileall(av, L->Tpk? 9: 8,
@@ -1527,7 +1572,7 @@ nf_DDF_roots(GEN pol, GEN polred, GEN nfpol, GEN init_fa, long nbf,
     z = roots_from_deg1(z);
   }
   else
-    z = rootpadicfast(polred, L->p, L->k);
+    z = ZpX_roots(polred, L->p, L->k);
   Cltx_r = deg1pol_shallow(D.Clt? D.Clt: gen_1, NULL, varn(pol));
   for (m=1,i=1; i<lg(z); i++)
   {
@@ -1701,6 +1746,7 @@ nfsqff_trager(GEN u, GEN T, GEN dent)
       pari_err_IRREDPOL("factornf [modulus]",T);
     gel(P,i) = QXQX_normalize(F, T);
   }
+  gen_sort_inplace(P, (void*)&cmp_RgX, &gen_cmp_RgX, NULL);
   return P;
 }
 
@@ -1953,7 +1999,7 @@ nfcyclo_root(GEN nf, long n_cyclo, prklift_t *P)
 {
   pari_sp av = avma;
   GEN init_fa = NULL; /* factors mod pr */
-  GEN z, nfpol = nf_get_pol(nf), pol = polcyclo(n_cyclo, MAXVARN);
+  GEN z, nfpol = nf_get_pol(nf), pol = polcyclo(n_cyclo, 0);
   long nbf, deg = degpol(pol); /* = eulerphi(n_cyclo) */
   if (P->L->Tp)
     nbf = FqX_split_deg1(&init_fa, pol, P->L->Tp, P->L->p);
diff --git a/src/basemath/perm.c b/src/basemath/perm.c
index eea2a55..b9b6f05 100644
--- a/src/basemath/perm.c
+++ b/src/basemath/perm.c
@@ -464,7 +464,7 @@ perm_generate(GEN S, GEN H, long o)
   return L;
 }
 
-/*Return the order (cardinal) of a group */
+/*Return the order (cardinality) of a group */
 long
 group_order(GEN G)
 {
@@ -724,7 +724,7 @@ liftlistsubgroups(GEN L, GEN C, long r)
     {
       GEN p = gel(C,j);
       if (perm_relorder(p, Selt) == r && group_perm_normalize(S, p))
-        gel(R,k++) = mkvec2(vecsmall_append(gen, (long)p),
+        gel(R,k++) = mkvec2(vec_append(gen, p),
                             vecsmall_append(ord, r));
     }
   }
diff --git a/src/basemath/polarit1.c b/src/basemath/polarit1.c
index 8ecc9d8..7171911 100644
--- a/src/basemath/polarit1.c
+++ b/src/basemath/polarit1.c
@@ -243,20 +243,20 @@ Z_to_Zp(GEN x, GEN p, GEN pr, long r)
 }
 /* shallow */
 static GEN
-ZV_to_ZpV(GEN z, GEN p, long prec)
+ZV_to_ZpV(GEN z, GEN p, long r)
 {
   long i, l = lg(z);
-  GEN Z = cgetg(l, typ(z)), q = powiu(p, prec);
-  for (i=1; i<lg(z); i++) gel(Z,i) = Z_to_Zp(gel(z,i),p,q,prec);
+  GEN Z = cgetg(l, typ(z)), q = powiu(p, r);
+  for (i=1; i<lg(z); i++) gel(Z,i) = Z_to_Zp(gel(z,i),p,q,r);
   return Z;
 }
 /* shallow */
 static GEN
-ZX_to_ZpX(GEN z, GEN p, GEN q, long prec)
+ZX_to_ZpX(GEN z, GEN p, GEN q, long r)
 {
   long i, l = lg(z);
   GEN Z = cgetg(l, t_POL); Z[1] = z[1];
-  for (i=2; i<lg(z); i++) gel(Z,i) = Z_to_Zp(gel(z,i),p,q,prec);
+  for (i=2; i<lg(z); i++) gel(Z,i) = Z_to_Zp(gel(z,i),p,q,r);
   return Z;
 }
 /* return (x + O(p^r)) normalized (multiply by a unit such that leading coeff
@@ -274,12 +274,12 @@ ZX_to_ZpX_normalized(GEN x, GEN p, GEN pr, long r)
   z[1] = x[1]; return z;
 }
 static GEN
-ZXV_to_ZpXQV(GEN z, GEN T, GEN p, long prec)
+ZXV_to_ZpXQV(GEN z, GEN T, GEN p, long r)
 {
   long i, l = lg(z);
-  GEN Z = cgetg(l, typ(z)), q = powiu(p, prec);
+  GEN Z = cgetg(l, typ(z)), q = powiu(p, r);
   T = ZX_copy(T);
-  for (i=1; i<lg(z); i++) gel(Z,i) = mkpolmod(ZX_to_ZpX(gel(z,i),p,q,prec),T);
+  for (i=1; i<lg(z); i++) gel(Z,i) = mkpolmod(ZX_to_ZpX(gel(z,i),p,q,r),T);
   return Z;
 }
 /* shallow */
@@ -319,7 +319,7 @@ GEN
 ZX_Zp_root(GEN f, GEN a, GEN p, long prec)
 {
   GEN z, R, a0 = modii(a, p);
-  long i, j, k, v;
+  long i, j, k;
 
   if (signe(FpX_eval(FpX_deriv(f, p), a0, p)))
   { /* simple zero mod p, go all the way to p^prec */
@@ -328,8 +328,7 @@ ZX_Zp_root(GEN f, GEN a, GEN p, long prec)
   }
 
   f = ZX_unscale_div(RgX_translate(f,a), p); /* f(pX + a) / p */
-  v = ZX_pval(f,p);
-  if (v) f = ZX_Z_divexact(f, powiu(p,v));
+  (void)ZX_pvalrem(f,p,&f);
   z = cgetg(degpol(f)+1,t_COL);
 
   R = FpX_roots(f, p);
@@ -421,21 +420,7 @@ rootpadic(GEN f, GEN p, long prec)
     for (i=1; i<k; i++) gel(y,i) = ginv(gel(y,i));
   return gerepilecopy(av, y);
 }
-/* p is prime
- * f in a ZX, with leading term prime to p.
- * f must have no multiple roots mod p.
- *
- * return p-adics roots of f with prec p^e, as integers (implicitly mod p^e) */
-GEN
-rootpadicfast(GEN f, GEN p, long e)
-{
-  pari_sp av = avma;
-  GEN y, S = FpX_roots(f, p); /*no multiplicity*/
-  if (lg(S)==1) { avma = av; return cgetg(1,t_COL); }
-  S = gclone(S); avma = av;
-  y = ZpX_liftroots(f,S,p,e);
-  gunclone(S); return y;
-}
+
 /**************************************************************************/
 
 static void
@@ -590,46 +575,32 @@ ZX_monic_factorpadic(GEN f, GEN p, long prec)
 }
 
 GEN
-factorpadic(GEN f,GEN p,long prec)
+factorpadic(GEN f,GEN p,long r)
 {
   pari_sp av = avma;
   GEN y, P, ppow, lead, lt;
   long i, l, pr, n = degpol(f);
   int reverse = 0;
 
+  if (typ(f)!=t_POL) pari_err_TYPE("factorpadic",f);
+  if (typ(p)!=t_INT) pari_err_TYPE("factorpadic",p);
+  if (r <= 0) pari_err_DOMAIN("factorpadic", "precision", "<=",gen_0,stoi(r));
+  if (!signe(f)) return prime_fact(f);
   if (n == 0) return trivial_fact();
 
   f = QpX_to_ZX(f, p); (void)Z_pvalrem(leading_term(f), p, &lt);
-  f = pnormalize(f, p, prec, n-1, &lead, &pr, &reverse);
+  f = pnormalize(f, p, r, n-1, &lead, &pr, &reverse);
   y = ZX_monic_factorpadic(f, p, pr);
   P = gel(y,1); l = lg(P);
   if (lead != gen_1)
     for (i=1; i<l; i++) gel(P,i) = Q_primpart( RgX_unscale(gel(P,i), lead) );
-  ppow = powiu(p,prec);
+  ppow = powiu(p,r);
   for (i=1; i<l; i++)
   {
     GEN t = gel(P,i);
     if (reverse) t = normalizepol(RgX_recip_shallow(t));
-    gel(P,i) = ZX_to_ZpX_normalized(t,p,ppow,prec);
+    gel(P,i) = ZX_to_ZpX_normalized(t,p,ppow,r);
   }
   if (!gequal1(lt)) gel(P,1) = gmul(gel(P,1), lt);
   return gerepilecopy(av, sort_factor_pol(y, cmp_padic));
 }
-
-/* deprecated: backward compatibility */
-GEN
-factorpadic0(GEN f,GEN p,long r,long flag)
-{
-  if (typ(f)!=t_POL) pari_err_TYPE("factorpadic",f);
-  if (typ(p)!=t_INT) pari_err_TYPE("factorpadic",p);
-  if (!signe(f)) return prime_fact(f);
-  if (r <= 0)
-    pari_err_DOMAIN("factorpadic", "precision", "<=",gen_0,stoi(r));
-  switch(flag)
-  {
-    case 0: case 1:
-       return factorpadic(f,p,r);
-     default: pari_err_FLAG("factorpadic");
-  }
-  return NULL; /* not reached */
-}
diff --git a/src/basemath/polarit2.c b/src/basemath/polarit2.c
index 1c39a5a..d922830 100644
--- a/src/basemath/polarit2.c
+++ b/src/basemath/polarit2.c
@@ -161,12 +161,13 @@ centermod(GEN x, GEN p) { return centermod_i(x,p,NULL); }
 /**                                                                   **/
 /***********************************************************************/
 #define assign_or_fail(x,y) { GEN __x = x;\
-  if (y==NULL) y=__x; else if (!gequal(__x,y)) return 0;\
+  if (!*y) *y=__x; else if (!gequal(__x,*y)) return 0;\
 }
+#define update_prec(x,y) { long __x = x; if (__x < *y) *y=__x; }
 
 static const long tsh = 6;
 static long
-RgX_type_code(long t1, long t2) { return (t1 << tsh) | t2; }
+code(long t1, long t2) { return (t1 << tsh) | t2; }
 void
 RgX_type_decode(long x, long *t1, long *t2)
 {
@@ -177,33 +178,28 @@ int
 RgX_type_is_composite(long t) { return t >= tsh; }
 
 long
-RgX_type(GEN x, GEN *ptp, GEN *ptpol, long *ptpa)
+RgX_type(GEN x, GEN *p, GEN *pol, long *pa)
 {
-  long t[16];
-  long tx = typ(x), lx, i, j, s, pa = LONG_MAX;
-  GEN pcx=NULL, p=NULL, pol=NULL, ff=NULL;
-
+  long t[] = {0,0,0,0,0,0,0,0,0,0};
+  long tx = typ(x), lx, i, j, t2 = 0;
+  GEN ff = NULL;
+  *p = *pol = NULL; *pa = LONG_MAX;
   if (is_scalar_t(tx))
   {
     if (tx == t_POLMOD) return 0;
     x = scalarpol(x,0);
   }
-  for (i=2; i<16; i++) t[i]=0;
   /* t[0..1] unused. Other values, if set, indicate a coefficient of type
    * t[2] : t_REAL
    * t[3] : t_INTMOD
    * t[4] : t_COMPLEX of rationals (t_INT/t_FRAC)
-   * t[5] : t_COMPLEX of t_REAL
-   * t[6] : t_COMPLEX of t_INTMOD
-   * t[7] : t_COMPLEX of t_PADIC
-   * t[8] : t_PADIC
-   * t[9] : t_QUAD of rationals (t_INT/t_FRAC)
-   * t[10]: t_QUAD of t_INTMOD
-   * t[11]: t_QUAD of t_PADIC
-   * t[12]: t_POLMOD of rationals (t_INT/t_FRAC)
-   * t[13]: t_POLMOD of t_INTMOD
-   * t[14]: t_POLMOD of t_PADIC
-   * t[15]: t_FFELT */
+   * t[5] : t_FFELT
+   * t[6] : t_COMPLEX of t_REAL
+   * t[7] : t_PADIC
+   * t[8] : t_QUAD of rationals (t_INT/t_FRAC)
+   * t[9]: t_POLMOD of rationals (t_INT/t_FRAC) */
+  /* if t2 != 0: t_POLMOD/t_QUAD/t_COMPLEX of modular (t_INTMOD/t_PADIC,
+   * given by t) */
   lx = lg(x);
   for (i=2; i<lx; i++)
   {
@@ -213,65 +209,63 @@ RgX_type(GEN x, GEN *ptp, GEN *ptpol, long *ptpa)
       case t_INT: case t_FRAC:
         break;
       case t_REAL:
-        s = precision(c); if (s < pa) pa = s;
+        update_prec(precision(c), pa);
         t[2]=1; break;
       case t_INTMOD:
         assign_or_fail(gel(c,1),p);
         t[3]=1; break;
       case t_FFELT:
-        if (ff==NULL) ff=c;
-        else if (!FF_samefield(c,ff)) return 0;
+        if (!ff) ff=c; else if (!FF_samefield(c,ff)) return 0;
         assign_or_fail(FF_p_i(c),p);
-        t[15]=1; break;
+        t[5]=1; break;
       case t_COMPLEX:
-        if (!pcx) pcx = mkpoln(3, gen_1,gen_0,gen_1); /* x^2 + 1 */
         for (j=1; j<=2; j++)
         {
           GEN d = gel(c,j);
           switch(typ(d))
           {
             case t_INT: case t_FRAC:
-              assign_or_fail(pcx,pol);
               t[4]=1; break;
             case t_REAL:
-              s = precision(d); if (s < pa) pa = s;
-              t[5]=1; break;
+              update_prec(precision(d), pa);
+              t[6]=1; break;
             case t_INTMOD:
               assign_or_fail(gel(d,1),p);
-              if (!signe(p) || mod4(p) != 3) return 0;
-              assign_or_fail(pcx,pol);
-              t[6]=1; break;
+              if (!signe(*p) || mod4(*p) != 3) return 0;
+              if (!t2) t2 = t_COMPLEX;
+              t[3]=1; break;
             case t_PADIC:
-              s = precp(d) + valp(d); if (s < pa) pa = s;
+              update_prec(precp(d)+valp(d), pa);
               assign_or_fail(gel(d,2),p);
-              assign_or_fail(pcx,pol);
+              if (!t2) t2 = t_COMPLEX;
               t[7]=1; break;
             default: return 0;
           }
         }
+        if (!t[6]) assign_or_fail(mkpoln(3, gen_1,gen_0,gen_1), pol); /*x^2+1*/
         break;
       case t_PADIC:
-        s = precp(c) + valp(c); if (s < pa) pa = s;
+        update_prec(precp(c)+valp(c), pa);
         assign_or_fail(gel(c,2),p);
-        t[8]=1; break;
+        t[7]=1; break;
       case t_QUAD:
+        assign_or_fail(gel(c,1),pol);
         for (j=2; j<=3; j++)
         {
           GEN d = gel(c,j);
           switch(typ(d))
           {
             case t_INT: case t_FRAC:
-              assign_or_fail(gel(c,1),pol);
-              t[9]=1; break;
+              t[8]=1; break;
             case t_INTMOD:
               assign_or_fail(gel(d,1),p);
-              assign_or_fail(gel(c,1),pol);
-              t[10]=1; break;
+              if (t2 != t_POLMOD) t2 = t_QUAD;
+              t[3]=1; break;
             case t_PADIC:
-              s = precp(d) + valp(d); if (s < pa) pa = s;
+              update_prec(precp(d)+valp(d), pa);
               assign_or_fail(gel(d,2),p);
-              assign_or_fail(gel(c,1),pol);
-              t[11]=1; break;
+              if (t2 != t_POLMOD) t2 = t_QUAD;
+              t[7]=1; break;
             default: return 0;
           }
         }
@@ -284,9 +278,9 @@ RgX_type(GEN x, GEN *ptp, GEN *ptpol, long *ptpa)
           long pabis;
           switch(RgX_type(gel(c,j),&pbis,&polbis,&pabis))
           {
-            case t_INT: t[12]=1; break;
-            case t_INTMOD: t[13]=1; break;
-            case t_PADIC: t[14]=1; if (pabis<pa) pa=pabis; break;
+            case t_INT: t[9]=1; break;
+            case t_INTMOD: t[3]=1; t2 = t_POLMOD; break;
+            case t_PADIC: t[7]=1; t2 = t_POLMOD; update_prec(pabis,pa); break;
             default: return 0;
           }
           if (pbis) assign_or_fail(pbis,p);
@@ -296,42 +290,31 @@ RgX_type(GEN x, GEN *ptp, GEN *ptpol, long *ptpa)
       default: return 0;
     }
   }
-  if (t[5])
+  if (t[5]) /* ffelt */
   {
-    if (t[3]||t[6]||t[7]||t[8]||t[10]||t[11]||t[12]||t[13]||t[14]) return 0;
-    *ptpa=pa; return t_COMPLEX;
+    if (t2 ||t[2]||t[4]||t[6]||t[8]||t[9]) return 0;
+    *pol=ff; return t_FFELT;
   }
-  if (t[2])
+  if (t[6]) /* inexact, complex */
   {
-    if (t[3]||t[6]||t[7]||t[8]||t[10]||t[11]||t[12]||t[13]||t[14]) return 0;
-    *ptpa=pa; return t[4]?t_COMPLEX:t_REAL;
+    if (t2 ||t[3]||t[7]||t[9]) return 0;
+    return t_COMPLEX;
   }
-  if (t[6]||t[10]||t[13])
+  if (t[2]) /* inexact, real */
   {
-    *ptpol=pol; *ptp=p;
-    i = t[13]? t_POLMOD: (t[10]? t_QUAD: t_COMPLEX);
-    return RgX_type_code(i, t_INTMOD);
+    if (t2 ||t[3]||t[7]||t[9]) return 0;
+    return t[4]?t_COMPLEX:t_REAL;
   }
-  if (t[7]||t[11]||t[14])
+  if (t2) /* polmod/quad/complex of intmod/padic */
   {
-    *ptpol=pol; *ptp=p; *ptpa=pa;
-    i = t[14]? t_POLMOD: (t[11]? t_QUAD: t_COMPLEX);
-    return RgX_type_code(i, t_PADIC);
+    if (t[3]) return code(t2,t_INTMOD);
+    if (t[7]) return code(t2,t_PADIC);
   }
-  if (t[4]||t[9]||t[12])
-  {
-    *ptpol=pol;
-    i = t[12]? t_POLMOD: (t[9]? t_QUAD: t_COMPLEX);
-    return RgX_type_code(i, t_INT);
-  }
-  if (t[15])
-  {
-    if (t[8]) return 0;
-    *ptp=p; *ptpol=ff;
-    return t_FFELT;
-  }
-  if (t[3]) { *ptp=p; return t_INTMOD; }
-  if (t[8]) { *ptp=p; *ptpa=pa; return t_PADIC; }
+  if (t[9]) return code(t_POLMOD,t_INT);
+  if (t[8]) return code(t_QUAD,t_INT);
+  if (t[4]) return code(t_COMPLEX,t_INT);
+  if (t[3]) return t_INTMOD;
+  if (t[7]) return t_PADIC;
   return t_INT;
 }
 
@@ -494,7 +477,7 @@ gauss_factor(GEN x)
     exp &= 3;
   }
   if (j > 1) {
-    long k = 1;;
+    long k = 1;
     GEN P1 = cgetg(l, t_COL);
     GEN E1 = cgetg(l, t_COL);
     /* remove factors with exponent 0 */
@@ -769,13 +752,13 @@ roots_to_pol_r1(GEN a, long v, long r1)
 GEN
 divide_conquer_assoc(GEN x, void *data, GEN (*mul)(void *,GEN,GEN))
 {
-  pari_sp ltop, lim;
+  pari_sp ltop;
   long i,k,lx = lg(x);
 
   if (lx == 1) return gen_1;
   if (lx == 2) return gcopy(gel(x,1));
   x = leafcopy(x); k = lx;
-  ltop=avma; lim = stack_lim(ltop,1);
+  ltop=avma;
   while (k > 2)
   {
     if (DEBUGLEVEL>7)
@@ -784,7 +767,7 @@ divide_conquer_assoc(GEN x, void *data, GEN (*mul)(void *,GEN,GEN))
     for (i=1; i<lx-1; i+=2)
       gel(x,k++) = mul(data,gel(x,i),gel(x,i+1));
     if (i < lx) gel(x,k++) = gel(x,i);
-    if (low_stack(lim,stack_lim(ltop,1)))
+    if (gc_needed(ltop,1))
       gerepilecoeffs(ltop,x+1,k-1);
   }
   return gel(x,1);
@@ -860,12 +843,28 @@ gen_factorback(GEN L, GEN e, GEN (*_mul)(void*,GEN,GEN),
   /* p = elts, e = expo */
   lx = lg(p);
   /* check whether e is an integral vector of correct length */
-  if (!is_vec_t(typ(e)) || lx != lg(e) || !RgV_is_ZV(e))
-    pari_err_TYPE("factorback [not an exponent vector]", e);
-  if (lx == 1) return gen_1;
-  x = cgetg(lx,t_VEC);
-  for (l=1,k=1; k<lx; k++)
-    if (signe(gel(e,k))) gel(x,l++) = _pow(data, gel(p,k), gel(e,k));
+  switch(typ(e))
+  {
+    case t_VECSMALL:
+      if (lx != lg(e))
+        pari_err_TYPE("factorback [not an exponent vector]", e);
+      if (lx == 1) return gen_1;
+      x = cgetg(lx,t_VEC);
+      for (l=1,k=1; k<lx; k++)
+        if (e[k]) gel(x,l++) = _pow(data, gel(p,k), stoi(e[k]));
+      break;
+    case t_VEC: case t_COL:
+      if (lx != lg(e) || !RgV_is_ZV(e))
+        pari_err_TYPE("factorback [not an exponent vector]", e);
+      if (lx == 1) return gen_1;
+      x = cgetg(lx,t_VEC);
+      for (l=1,k=1; k<lx; k++)
+        if (signe(gel(e,k))) gel(x,l++) = _pow(data, gel(p,k), gel(e,k));
+      break;
+    default:
+      pari_err_TYPE("factorback [not an exponent vector]", e);
+      return NULL;
+  }
   x[0] = evaltyp(t_VEC) | _evallg(l);
   return gerepileupto(av, divide_conquer_assoc(x, data, _mul));
 }
@@ -1483,7 +1482,7 @@ pol_approx0(GEN r, GEN x, int exact)
 GEN
 RgX_gcd_simple(GEN x, GEN y)
 {
-  pari_sp av1, av = avma, lim = stack_lim(av, 1);
+  pari_sp av1, av = avma;
   GEN r, yorig = y;
   int exact = !(isinexactreal(x) || isinexactreal(y));
 
@@ -1499,7 +1498,7 @@ RgX_gcd_simple(GEN x, GEN y)
       return gerepileupto(av,y);
     }
     x = y; y = r;
-    if (low_stack(lim,stack_lim(av,1))) {
+    if (gc_needed(av,1)) {
       if(DEBUGMEM>1) pari_warn(warnmem,"RgX_gcd_simple");
       gerepileall(av,2, &x,&y);
     }
@@ -1558,16 +1557,16 @@ content(GEN x)
     }
 
     case t_VEC: case t_COL:
-      lx = lg(x); if (lx==1) return gen_1;
+      lx = lg(x); if (lx==1) return gen_0;
       break;
 
     case t_MAT:
     {
       long hx, j;
       lx = lg(x);
-      if (lx == 1) return gen_1;
+      if (lx == 1) return gen_0;
       hx = lgcols(x);
-      if (hx == 1) return gen_1;
+      if (hx == 1) return gen_0;
       if (lx == 2) { x = gel(x,1); lx = lg(x); break; }
       if (hx == 2) { x = row_i(x, 1, 1, lx-1); break; }
       c = content(gel(x,1));
@@ -1580,6 +1579,7 @@ content(GEN x)
     case t_POL: case t_SER:
       lx = lg(x); if (lx == 2) return gen_0;
       break;
+    case t_VECSMALL: return utoi(zv_content(x));
     case t_QFR: case t_QFI:
       lx = 4; break;
 
@@ -1721,6 +1721,8 @@ Q_denom(GEN x)
         if (D != gen_1) d = lcmii(d, D);
       }
       return gerepileuptoint(av, d);
+
+    case t_POLMOD: return Q_denom(gel(x,2));
   }
   pari_err_TYPE("Q_denom",x);
   return NULL; /* not reached */
@@ -2045,7 +2047,7 @@ subres_step(GEN *u, GEN *v, GEN *g, GEN *h, GEN *uze, GEN *um1, long *signh)
 static GEN
 subresext_i(GEN x, GEN y, GEN *U, GEN *V)
 {
-  pari_sp av, av2, lim;
+  pari_sp av, av2;
   long dx, dy, du, signh, tx = typ(x), ty = typ(y);
   GEN r, z, g, h, p1, cu, cv, u, v, um1, uze, vze;
 
@@ -2074,12 +2076,12 @@ subresext_i(GEN x, GEN y, GEN *U, GEN *V)
   av = avma;
   u = x = primitive_part(x, &cu);
   v = y = primitive_part(y, &cv);
-  g = h = gen_1; av2 = avma; lim = stack_lim(av2,1);
+  g = h = gen_1; av2 = avma;
   um1 = gen_1; uze = gen_0;
   for(;;)
   {
     if (!subres_step(&u, &v, &g, &h, &uze, &um1, &signh)) break;
-    if (low_stack(lim,stack_lim(av2,1)))
+    if (gc_needed(av2,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"subresext, dr = %ld", degpol(v));
       gerepileall(av2,6, &u,&v,&g,&h,&uze,&um1);
@@ -2143,7 +2145,7 @@ must_negate(GEN x)
 GEN
 RgX_extgcd(GEN x, GEN y, GEN *U, GEN *V)
 {
-  pari_sp av, av2, tetpil, lim;
+  pari_sp av, av2, tetpil;
   long signh; /* junk */
   long dx, dy, vx, tx = typ(x), ty = typ(y);
   GEN z, g, h, p1, cu, cv, u, v, um1, uze, vze, *gptr[3];
@@ -2166,12 +2168,12 @@ RgX_extgcd(GEN x, GEN y, GEN *U, GEN *V)
   av = avma;
   u = x = primitive_part(x, &cu);
   v = y = primitive_part(y, &cv);
-  g = h = gen_1; av2 = avma; lim = stack_lim(av2,1);
+  g = h = gen_1; av2 = avma;
   um1 = gen_1; uze = gen_0;
   for(;;)
   {
     if (!subres_step(&u, &v, &g, &h, &uze, &um1, &signh)) break;
-    if (low_stack(lim,stack_lim(av2,1)))
+    if (gc_needed(av2,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"RgX_extgcd, dr = %ld",degpol(v));
       gerepileall(av2,6,&u,&v,&g,&h,&uze,&um1);
@@ -2205,7 +2207,7 @@ RgX_extgcd(GEN x, GEN y, GEN *U, GEN *V)
 int
 RgXQ_ratlift(GEN x, GEN T, long amax, long bmax, GEN *P, GEN *Q)
 {
-  pari_sp av = avma, av2, tetpil, lim;
+  pari_sp av = avma, av2, tetpil;
   long signh; /* junk */
   long vx;
   GEN g, h, p1, cu, cv, u, v, um1, uze, *gptr[2];
@@ -2228,14 +2230,14 @@ RgXQ_ratlift(GEN x, GEN T, long amax, long bmax, GEN *P, GEN *Q)
   vx = varn(T);
   u = x = primitive_part(x, &cu);
   v = T = primitive_part(T, &cv);
-  g = h = gen_1; av2 = avma; lim = stack_lim(av2,1);
+  g = h = gen_1; av2 = avma;
   um1 = gen_1; uze = gen_0;
   for(;;)
   {
     (void) subres_step(&u, &v, &g, &h, &uze, &um1, &signh);
     if (!u || (typ(uze)==t_POL && degpol(uze)>bmax)) { avma=av; return 0; }
     if (typ(v)!=t_POL || degpol(v)<=amax) break;
-    if (low_stack(lim,stack_lim(av2,1)))
+    if (gc_needed(av2,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"RgXQ_ratlift, dr = %ld", degpol(v));
       gerepileall(av2,6,&u,&v,&g,&h,&uze,&um1);
@@ -2321,12 +2323,12 @@ nextSousResultant(GEN P, GEN Q, GEN Z, GEN s)
 {
   GEN p0, q0, h0, TMP, H, A, z0 = leading_term(Z);
   long p, q, j, lP, lQ;
-  pari_sp av, lim;
+  pari_sp av;
 
   p = degpol(P); p0 = gel(P,p+2); lP = reductum_lg(P,lg(P));
   q = degpol(Q); q0 = gel(Q,q+2); lQ = reductum_lg(Q,lg(Q));
   /* p > q. Very often p - 1 = q */
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
   /* H = RgX_neg(reductum(Z)) optimized, using Q ~ Z */
   H = RgX_neg_i(Z, lQ); /* deg H < q */
 
@@ -2345,7 +2347,7 @@ nextSousResultant(GEN P, GEN Q, GEN Z, GEN s)
       TMP = RgX_Rg_mul(H, gel(P,j+2));
       A = A? RgX_add(A, TMP): TMP;
     }
-    if (low_stack(lim,stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"nextSousResultant j = %ld/%ld",j,p);
       gerepileall(av,A?2:1,&H,&A);
@@ -2369,7 +2371,7 @@ nextSousResultant(GEN P, GEN Q, GEN Z, GEN s)
 GEN
 RgX_resultant_all(GEN P, GEN Q, GEN *sol)
 {
-  pari_sp av, av2, lim;
+  pari_sp av, av2;
   long dP, dQ, delta, sig = 1;
   GEN cP, cQ, Z, s;
 
@@ -2391,7 +2393,7 @@ RgX_resultant_all(GEN P, GEN Q, GEN *sol)
   }
   P = primitive_part(P, &cP);
   Q = primitive_part(Q, &cQ);
-  av2 = avma; lim = stack_lim(av2,1);
+  av2 = avma;
   s = gpowgs(leading_term(Q),delta);
   if (both_odd(dP, dQ)) sig = -sig;
   Z = Q;
@@ -2404,7 +2406,7 @@ RgX_resultant_all(GEN P, GEN Q, GEN *sol)
     if (both_odd(degpol(P), degpol(Q))) sig = -sig;
     Q = nextSousResultant(P, Q, Z, s);
     P = Z;
-    if (low_stack(lim,stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"resultant_all, degpol Q = %ld",degpol(Q));
       gerepileall(av2,2,&P,&Q);
@@ -2412,13 +2414,12 @@ RgX_resultant_all(GEN P, GEN Q, GEN *sol)
     s = leading_term(P);
   }
   if (!signe(Q)) { avma = av; return RgX_get_0(Q); }
-  av2 = avma;
   s = Lazard(leading_term(Q), s, degpol(P));
   if (sig == -1) s = gneg(s);
   if (cP) s = gmul(s, gpowgs(cP,dQ));
   if (cQ) s = gmul(s, gpowgs(cQ,dP));
   if (sol) { *sol = P; gerepileall(av, 2, &s, sol); return s; }
-  return (avma == av2)? gerepilecopy(av, s): gerepileupto(av, s);
+  return gerepilecopy(av, s);
 }
 /* Return resultant(P,Q). If sol != NULL: set *sol to the last non-constant
  * polynomial in the prs IF the sequence was computed, and gen_0 otherwise.
@@ -2503,35 +2504,26 @@ resultant2(GEN x, GEN y)
   av = avma; return gerepileupto(av,det(sylvestermatrix_i(x,y)));
 }
 
-/* Let vx = main variable of x. Return a polynomial in variable 0:
- * if vx is 0 and v != 0, set *mx = 1 and replace vx by pol_x(MAXVARN)
- * if vx = v, copy x, set its main variable to 0 and return
- * if vx < v, return subst(x, v, pol_x(0))
- * if vx > v, return scalarpol(x, 0) */
+/* If x a t_POL, let vx = main variable of x; return a t_POL in variable v0:
+ * if vx <= v, return subst(x, v, pol_x(v0))
+ * if vx >  v, return scalarpol(x, v0) */
 static GEN
-fix_pol(GEN x, long v, long *mx)
+fix_pol(GEN x, long v, long v0)
 {
   long vx;
   if (typ(x) != t_POL) return x;
   vx = varn(x);
   if (v == vx)
   {
-    if (v) { x = leafcopy(x); setvarn(x, 0); }
+    if (v) { x = leafcopy(x); setvarn(x, v0); }
     return x;
   }
-  if (!vx)
-  {
-    *mx = 1;
-    x = poleval(x, pol_x(MAXVARN));
-    vx = varn(x);
-    if (v == vx) { setvarn(x, 0); return x; }
-  }
   if (varncmp(v, vx) > 0)
   {
-    x = gsubst(x,v,pol_x(0));
-    if (typ(x) == t_POL && varn(x) == 0) return x;
+    x = gsubst(x,v,pol_x(v0));
+    if (typ(x) == t_POL && varn(x) == v0) return x;
   }
-  return scalarpol_shallow(x, 0);
+  return scalarpol_shallow(x, v0);
 }
 
 /* resultant of x and y with respect to variable v, or with respect to their
@@ -2539,13 +2531,14 @@ fix_pol(GEN x, long v, long *mx)
 GEN
 polresultant0(GEN x, GEN y, long v, long flag)
 {
-  long m = 0;
+  long v0 = 0;
   pari_sp av = avma;
 
   if (v >= 0)
   {
-    x = fix_pol(x,v, &m);
-    y = fix_pol(y,v, &m);
+    v0 = fetch_var_higher();
+    x = fix_pol(x,v, v0);
+    y = fix_pol(y,v, v0);
   }
   switch(flag)
   {
@@ -2554,30 +2547,26 @@ polresultant0(GEN x, GEN y, long v, long flag)
     case 1: x=resultant2(x,y); break;
     default: pari_err_FLAG("polresultant");
   }
-  if (m) x = gsubst(x,MAXVARN,pol_x(0));
+  if (v >= 0) (void)delete_var();
   return gerepileupto(av,x);
 }
 GEN
 polresultantext0(GEN x, GEN y, long v)
 {
   GEN R, U, V;
-  long m = 0;
+  long v0 = 0;
   pari_sp av = avma;
 
   if (v >= 0)
   {
-    x = fix_pol(x,v, &m);
-    y = fix_pol(y,v, &m);
+    v0 = fetch_var_higher();
+    x = fix_pol(x,v, v0);
+    y = fix_pol(y,v, v0);
   }
   R = subresext_i(x,y, &U,&V);
-  if (m)
-  {
-    U = gsubst(gsubst(U, 0, pol_x(v)), MAXVARN, pol_x(0));
-    V = gsubst(gsubst(V, 0, pol_x(v)), MAXVARN, pol_x(0));
-    R = gsubst(R,MAXVARN,pol_x(0));
-  }
-  else if (v >= 0)
+  if (v >= 0)
   {
+    (void)delete_var();
     if (typ(U) == t_POL && varn(U) != v) U = poleval(U, pol_x(v));
     if (typ(V) == t_POL && varn(V) != v) V = poleval(V, pol_x(v));
   }
@@ -2602,7 +2591,7 @@ GEN
 RgXQ_charpoly(GEN x, GEN T, long v)
 {
   pari_sp av = avma;
-  long d = degpol(T), dx, vx, vp;
+  long d = degpol(T), dx, vx, vp, v0;
   GEN ch, L;
 
   if (typ(x) != t_POL) return caract_const(av, x, v, d);
@@ -2614,17 +2603,13 @@ RgXQ_charpoly(GEN x, GEN T, long v)
   if (dx <= 0)
     return dx? monomial(gen_1, d, v): caract_const(av, gel(x,2), v, d);
 
+  v0 = fetch_var_higher();
   x = RgX_neg(x);
-  if (varn(x) == MAXVARN) { setvarn(x, 0); T = leafcopy(T); setvarn(T, 0); }
-  gel(x,2) = gadd(gel(x,2), pol_x(MAXVARN));
+  gel(x,2) = gadd(gel(x,2), pol_x(v));
+  setvarn(x, v0);
+  T = leafcopy(T); setvarn(T, v0);
   ch = resultant_all(T, x, NULL);
-  if (v != MAXVARN)
-  {
-    if (typ(ch) == t_POL && varn(ch) == MAXVARN)
-      setvarn(ch, v);
-    else
-      ch = gsubst(ch, MAXVARN, pol_x(v));
-  }
+  (void)delete_var();
   /* test for silly input: x mod (deg 0 polynomial) */
   if (typ(ch) != t_POL) { avma = av; return pol_1(v); }
 
@@ -2743,7 +2728,7 @@ GEN
 RgX_gcd(GEN x, GEN y)
 {
   long dx, dy;
-  pari_sp av, av1, lim;
+  pari_sp av, av1;
   GEN d, g, h, p1, p2, u, v;
   int simple = 0, rational = 1;
 
@@ -2772,7 +2757,7 @@ RgX_gcd(GEN x, GEN y)
     u = primitive_part(x, &p1); if (!p1) p1 = gen_1;
     v = primitive_part(y, &p2); if (!p2) p2 = gen_1;
     d = ggcd(p1,p2);
-    av1 = avma; lim = stack_lim(av1,1);
+    av1 = avma;
     g = h = gen_1;
     for(;;)
     {
@@ -2797,7 +2782,7 @@ RgX_gcd(GEN x, GEN y)
           h = gdiv(gpowgs(g,degq), gpowgs(h,degq-1));
       }
       v = RgX_Rg_div(r,p1);
-      if (low_stack(lim, stack_lim(av1,1)))
+      if (gc_needed(av1,1))
       {
         if(DEBUGMEM>1) pari_warn(warnmem,"RgX_gcd");
         gerepileall(av1,4, &u,&v,&g,&h);
@@ -2846,18 +2831,23 @@ RgX_disc(GEN x) { pari_sp av = avma; return gerepileupto(av, RgX_disc_aux(x)); }
 GEN
 poldisc0(GEN x, long v)
 {
-  long i;
   pari_sp av;
-  GEN z, D;
-
   switch(typ(x))
   {
     case t_POL:
-      av = avma; i = 0;
-      if (v >= 0 && v != varn(x)) x = fix_pol(x,v, &i);
+    {
+      GEN D;
+      long v0 = -1;
+      av = avma;
+      if (v >= 0 && v != varn(x))
+      {
+        v0 = fetch_var_higher();
+        x = fix_pol(x,v, v0);
+      }
       D = RgX_disc_aux(x);
-      if (i) D = gsubst(D, MAXVARN, pol_x(0));
+      if (v0 >= 0) (void)delete_var();
       return gerepileupto(av, D);
+    }
 
     case t_COMPLEX:
       return utoineg(4);
@@ -2871,9 +2861,12 @@ poldisc0(GEN x, long v)
       av = avma; return gerepileuptoint(av, qfb_disc(x));
 
     case t_VEC: case t_COL: case t_MAT:
-      z = cgetg_copy(x, &i);
+    {
+      long i;
+      GEN z = cgetg_copy(x, &i);
       for (i--; i; i--) gel(z,i) = poldisc0(gel(x,i), v);
       return z;
+    }
   }
   pari_err_TYPE("poldisc",x);
   return NULL; /* not reached */
@@ -2895,7 +2888,7 @@ reduceddiscsmith(GEN x)
   xp = ZX_deriv(x);
   for (j=1; j<=n; j++)
   {
-    gel(M,j) = RgX_to_RgV(xp, n);
+    gel(M,j) = RgX_to_RgC(xp, n);
     if (j<n) xp = RgX_rem(RgX_shift_shallow(xp, 1), x);
   }
   return gerepileupto(av, ZM_snf(M));
@@ -2904,16 +2897,27 @@ reduceddiscsmith(GEN x)
 /***********************************************************************/
 /**                                                                   **/
 /**                       STURM ALGORITHM                             **/
-/**              (number of real roots of x in ]a,b])                 **/
+/**              (number of real roots of x in [a,b])                 **/
 /**                                                                   **/
 /***********************************************************************/
+static int
+exact_sturm(GEN a)
+{
+  switch(typ(a))
+  {
+    case t_INT: case t_FRAC: case t_INFINITY: return 1;
+    default: return 0;
+  }
+}
 
-/* if a (resp. b) is NULL, set it to -oo (resp. +oo) */
-long
-sturmpart(GEN x, GEN a, GEN b)
+/* Deprecated: support the old format: if a (resp. b) is NULL, set it
+ * to -oo resp. +oo). ZX_sturmpart() should be preferred  */
+static long
+sturmpart_i(GEN x, GEN a, GEN b)
 {
   long sl, sr, s, t, r1;
-  pari_sp av = avma, lim = stack_lim(av, 1);
+  pari_sp av = avma;
+  int integral;
   GEN g,h,u,v;
 
   if (gequal0(x)) pari_err_ROOTS0("sturm");
@@ -2924,21 +2928,55 @@ sturmpart(GEN x, GEN a, GEN b)
     pari_err_TYPE("sturm",x);
   }
   s=lg(x); if (s==3) return 0;
-
-  sl = gsigne(leading_term(x));
+  u = primpart(x);
+  integral = RgX_is_ZX(u);
+  if (!b && a && typ(a) == t_VEC && lg(a) == 3)
+  { /* new format */
+    if (integral && exact_sturm(gel(a,1)) && exact_sturm(gel(a,2)))
+    {
+      if (!ZX_is_squarefree(u))
+        pari_err_DOMAIN("polsturm","issquarefree(pol)","=",gen_0,u);
+      return ZX_sturmpart(u, a);
+    }
+    /* but can't use new function; convert to old form */
+    integral = 0;
+    b = gel(a,2);
+    if (typ(b) == t_INFINITY)
+    {
+      if (inf_get_sign(b) < 0) return 0;
+      b = NULL;
+    }
+    a = gel(a,1);
+    if (typ(a) == t_INFINITY)
+    {
+      if (inf_get_sign(a) > 0) return 0;
+      a = NULL;
+    }
+  }
+  if (integral)
+  {
+    if (!a) a = mkmoo();
+    if (!b) b = mkoo();
+    if (exact_sturm(a) && exact_sturm(b))
+    {
+      if (!ZX_is_squarefree(u))
+        pari_err_DOMAIN("polsturm","issquarefree(pol)","=",gen_0,u);
+      return ZX_sturmpart(u, mkvec2(a,b));
+    }
+  }
+  /* legacy code: should only be used if we have a t_REAL somewhere; and even
+   * then, the calling program should be changed */
+  sl = gsigne(leading_term(u));
+  t = a? gsigne(poleval(u,a)): (odd(s)? sl: -sl);
   if (s==4)
   {
-    t = a? gsigne(poleval(x,a)): -sl;
-    if (t == 0) { avma = av; return 0; }
-    s = b? gsigne(poleval(x,b)):  sl;
-    avma = av; return (s == t)? 0: 1;
+    if (t == 0) return 1;
+    s = b? gsigne(poleval(u,b)):  sl;
+    return (s == t)? 0: 1;
   }
-  u = primpart(x);
-  v = primpart(RgX_deriv(x));
-  g=gen_1; h=gen_1;
   s = b? gsigne(poleval(u,b)): sl;
-  t = a? gsigne(poleval(u,a)): ((lg(u)&1)? sl: -sl);
-  r1=0;
+  r1= (t == 0)? 1: 0;
+  v = primpart(RgX_deriv(x));
   sr = b? gsigne(poleval(v,b)): s;
   if (sr)
   {
@@ -2951,6 +2989,7 @@ sturmpart(GEN x, GEN a, GEN b)
     if (!t) t=sr;
     else if (sr!=t) { t= -t; r1++; }
   }
+  g=gen_1; h=gen_1;
   for(;;)
   {
     GEN p1, r = RgX_pseudorem(u,v);
@@ -2971,7 +3010,7 @@ sturmpart(GEN x, GEN a, GEN b)
       if (!t) t=sr;
       else if (sr!=t) { t= -t; r1++; }
     }
-    if (dr==3) { avma=av; return r1; }
+    if (dr==3) return r1;
 
     u=v; p1 = g; g = gabs(leading_term(u),DEFAULTPREC);
     switch(degq)
@@ -2984,13 +3023,22 @@ sturmpart(GEN x, GEN a, GEN b)
         h = gdivexact(gpowgs(g,degq), gpowgs(h,degq-1));
     }
     v = RgX_Rg_divexact(r,p1);
-    if (low_stack(lim,stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"polsturm, dr = %ld",dr);
       gerepileall(av,4,&u,&v,&g,&h);
     }
   }
 }
+long
+sturmpart(GEN x, GEN a, GEN b)
+{
+  pari_sp av = avma;
+  long r = sturmpart_i(x,a,b);
+  avma = av; return r;
+}
+long
+RgX_sturmpart(GEN x, GEN ab) { return sturmpart(x, ab, NULL); }
 
 /***********************************************************************/
 /**                                                                   **/
diff --git a/src/basemath/polarit3.c b/src/basemath/polarit3.c
index b41866d..ede3ce2 100644
--- a/src/basemath/polarit3.c
+++ b/src/basemath/polarit3.c
@@ -155,7 +155,7 @@ RgM_is_FpM(GEN x, GEN *pp)
 int
 Rg_is_FpXQ(GEN x, GEN *pT, GEN *pp)
 {
-  GEN pol, mod;
+  GEN pol, mod, p;
   switch(typ(x))
   {
   case t_INTMOD:
@@ -164,6 +164,16 @@ Rg_is_FpXQ(GEN x, GEN *pT, GEN *pp)
     return 1;
   case t_POL:
     return RgX_is_FpX(x, pp);
+  case t_FFELT:
+    mod = FF_1(x); p = FF_p_i(x);
+    if (!*pp) *pp = p;
+    if (!*pT) *pT = mod;
+    if ((p != *pp && !equalii(p, *pp)) || (mod != *pT && !gequal(mod, *pT)))
+    {
+      if (DEBUGMEM) pari_warn(warner,"different moduli in Rg_is_FpXQ");
+      return 0;
+    }
+    return 1;
   case t_POLMOD:
     mod = gel(x,1); pol = gel(x, 2);
     if (!RgX_is_FpX(mod, pp)) return 0;
@@ -204,7 +214,7 @@ RgX_is_FpXQX(GEN x, GEN *pT, GEN *pp)
 GEN
 Rg_to_Fp(GEN x, GEN p)
 {
-  if (lgefint(p) == 3) return utoi(Rg_to_Fl(x, (ulong)p[2]));
+  if (lgefint(p) == 3) return utoi(Rg_to_Fl(x, uel(p,2)));
   switch(typ(x))
   {
     case t_INT: return modii(x, p);
@@ -229,11 +239,16 @@ Rg_to_Fp(GEN x, GEN p)
 GEN
 Rg_to_FpXQ(GEN x, GEN T, GEN p)
 {
-  long ta, tx = typ(x), v = varn(T);
+  long ta, tx = typ(x), v = get_FpX_var(T);
   GEN a, b;
   if (is_const_t(tx))
   {
-    if (tx == t_FFELT) return FF_to_FpXQ(x);
+    if (tx == t_FFELT)
+    {
+      GEN z = FF_to_FpXQ(x);
+      setvarn(z, v);
+      return z;
+    }
     return scalar_ZX(Rg_to_Fp(x, p), v);
   }
   switch(tx)
@@ -243,7 +258,7 @@ Rg_to_FpXQ(GEN x, GEN T, GEN p)
       a = gel(x,2); ta = typ(a);
       if (is_const_t(ta)) return scalar_ZX(Rg_to_Fp(a, p), v);
       b = RgX_to_FpX(b, p); if (varn(b) != v) break;
-      a = RgX_to_FpX(a, p); if (ZX_equal(b,T)) return a;
+      a = RgX_to_FpX(a, p); if (ZX_equal(b,get_FpX_mod(T))) return a;
       return FpX_rem(a, T, p);
     case t_POL:
       if (varn(x) != v) break;
@@ -321,7 +336,12 @@ RgX_to_FqX(GEN x, GEN T, GEN p)
 {
   long i, l = lg(x);
   GEN z = cgetg(l, t_POL); z[1] = x[1];
-  for (i = 2; i < l; i++) gel(z,i) = simplify_shallow(Rg_to_FpXQ(gel(x,i), T,p));
+  if (T)
+    for (i = 2; i < l; i++)
+      gel(z,i) = simplify_shallow(Rg_to_FpXQ(gel(x,i), T, p));
+  else
+    for (i = 2; i < l; i++)
+      gel(z,i) = Rg_to_Fp(gel(x,i), p);
   return FpXQX_renormalize(z, l);
 }
 
@@ -542,8 +562,14 @@ GEN
 Fq_neg(GEN x, GEN T/*unused*/, GEN p)
 {
   (void)T;
-  return (typ(x)==t_POL)? FpX_neg(x,p)
-                        : Fp_neg(x,p);
+  return (typ(x)==t_POL)? FpX_neg(x,p): Fp_neg(x,p);
+}
+
+GEN
+Fq_halve(GEN x, GEN T/*unused*/, GEN p)
+{
+  (void)T;
+  return (typ(x)==t_POL)? FpX_halve(x,p): Fp_halve(x,p);
 }
 
 /* If T==NULL do not reduce*/
@@ -588,7 +614,6 @@ Fq_sqr(GEN x, GEN T, GEN p)
   }
   else
     return Fp_sqr(x,p);
-  return NULL;
 }
 
 GEN
@@ -745,20 +770,19 @@ const struct bb_field *get_Fq_field(void **E, GEN T, GEN p)
 GEN
 FpX_translate(GEN P, GEN c, GEN p)
 {
-  pari_sp av = avma, lim;
+  pari_sp av = avma;
   GEN Q, *R;
   long i, k, n;
 
   if (!signe(P) || !signe(c)) return ZX_copy(P);
   Q = leafcopy(P);
   R = (GEN*)(Q+2); n = degpol(P);
-  lim = stack_lim(av, 2);
   for (i=1; i<=n; i++)
   {
     for (k=n-i; k<n; k++)
       R[k] = Fp_add(R[k], Fp_mul(c, R[k+1], p), p);
 
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"FpX_translate, i = %ld/%ld", i,n);
       Q = gerepilecopy(av, Q); R = (GEN*)Q+2;
@@ -770,7 +794,7 @@ FpX_translate(GEN P, GEN c, GEN p)
 GEN
 FqX_translate(GEN P, GEN c, GEN T, GEN p)
 {
-  pari_sp av = avma, lim;
+  pari_sp av = avma;
   GEN Q, *R;
   long i, k, n;
 
@@ -778,13 +802,12 @@ FqX_translate(GEN P, GEN c, GEN T, GEN p)
   if (!signe(P) || !signe(c)) return RgX_copy(P);
   Q = leafcopy(P);
   R = (GEN*)(Q+2); n = degpol(P);
-  lim = stack_lim(av, 2);
   for (i=1; i<=n; i++)
   {
     for (k=n-i; k<n; k++)
       R[k] = Fq_add(R[k], Fq_mul(c, R[k+1], T, p), T, p);
 
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"FqX_translate, i = %ld/%ld", i,n);
       Q = gerepilecopy(av, Q); R = (GEN*)Q+2;
@@ -972,7 +995,7 @@ FpXQV_FpX_Frobenius(GEN V, GEN P, GEN T, GEN p)
   GEN M,W,Mi;
   GEN *gptr[2];
   long lV=lg(V);
-  GEN  PV=RgX_to_RgV(P, lgpol(P));
+  GEN  PV=RgX_to_RgC(P, lgpol(P));
   M=cgetg(l+1,t_VEC);
   gel(M,1) = scalar_ZX_shallow(FpX_eval(P,gen_1,p),v);
   gel(M,2) = FpXV_FpC_mul(V,PV,p);
@@ -1059,7 +1082,7 @@ FpM_Frobenius_pow(GEN M, long d, GEN T, GEN p)
 }
 
 /* Essentially we want to compute
- * FqM_ker(MA-pol_x(MAXVARN),U,l)
+ * FqM_ker(MA-pol_x(v),U,l)
  * To avoid use of matrix in Fq we procede as follows:
  * We compute FpM_ker(U(MA),l) and then we recover
  * the eigen value by Galois action, see formula.
@@ -1094,8 +1117,10 @@ Flx_intersect_ker(GEN P, GEN MA, GEN U, ulong p)
   gel(R,1) = gel(A,1);
   gel(R,r) = Flm_Flc_mul(MA, Flc_Fl_mul(gel(A,1),ib0, p), p);
   for(i=r-1; i>1; i--)
-    gel(R,i) = Flv_add(Flm_Flc_mul(MA,gel(R,i+1),p),
-                       Flc_Fl_mul(gel(R,r), U[i+2], p), p);
+  {
+    gel(R,i) = Flm_Flc_mul(MA,gel(R,i+1),p);
+    Flv_add_inplace(gel(R,i), Flc_Fl_mul(gel(R,r), U[i+2], p), p);
+  }
   return gerepileupto(ltop, Flm_to_FlxX(Flm_transpose(R),vp,vu));
 }
 
@@ -1156,8 +1181,8 @@ Flx_ffintersect(GEN P, GEN Q, long n, ulong l,GEN *SP, GEN *SQ, GEN MA, GEN MB)
   if (n<=0 || np%n || nq%n)
     pari_err_TYPE("FpX_ffintersect [bad degrees]",stoi(n));
   e = u_lvalrem(n, l, &pg);
-  if(!MA) MA = Flxq_matrix_pow(Flxq_powu(polx_Flx(vp),l,P,l),np,np,P,l);
-  if(!MB) MB = Flxq_matrix_pow(Flxq_powu(polx_Flx(vq),l,Q,l),nq,nq,Q,l);
+  if(!MA) MA = Flx_matFrobenius(P,l);
+  if(!MB) MB = Flx_matFrobenius(Q,l);
   A = Ap = pol0_Flx(vp);
   B = Bp = pol0_Flx(vq);
   if (pg > 1)
@@ -1193,7 +1218,7 @@ Flx_ffintersect(GEN P, GEN Q, long n, ulong l,GEN *SP, GEN *SQ, GEN MA, GEN MB)
     else
     {
       GEN L, An, Bn, z, U;
-      U = gmael(Flx_factor(ZX_to_Flx(polcyclo(pg,MAXVARN),l),l),1,1);
+      U = gmael(Flx_factor(ZX_to_Flx(polcyclo(pg, fetch_var()),l),l),1,1);
       A = Flx_intersect_ker(P, MA, U, l);
       B = Flx_intersect_ker(Q, MB, U, l);
       if (DEBUGLEVEL>=4) timer_start(&T);
@@ -1207,6 +1232,7 @@ Flx_ffintersect(GEN P, GEN Q, long n, ulong l,GEN *SP, GEN *SQ, GEN MA, GEN MB)
       B = FlxqX_Flxq_mul(B,L,U,l);
       A = FlxY_evalx(A,0,l);
       B = FlxY_evalx(B,0,l);
+      (void)delete_var();
     }
   }
   if (e)
@@ -1273,8 +1299,8 @@ FpX_ffintersect(GEN P, GEN Q, long n, GEN l, GEN *SP, GEN *SQ, GEN MA, GEN MB)
   if (n<=0 || np%n || nq%n)
     pari_err_TYPE("FpX_ffintersect [bad degrees]",stoi(n));
   e = u_pvalrem(n, l, &pg);
-  if(!MA) MA = FpXQ_matrix_pow(FpXQ_pow(pol_x(vp),l,P,l),np,np,P,l);
-  if(!MB) MB = FpXQ_matrix_pow(FpXQ_pow(pol_x(vq),l,Q,l),nq,nq,Q,l);
+  if(!MA) MA = FpX_matFrobenius(P, l);
+  if(!MB) MB = FpX_matFrobenius(Q, l);
   A = Ap = pol_0(vp);
   B = Bp = pol_0(vq);
   if (pg > 1)
@@ -1309,7 +1335,7 @@ FpX_ffintersect(GEN P, GEN Q, long n, GEN l, GEN *SP, GEN *SQ, GEN MA, GEN MB)
     else
     {
       GEN L, An, Bn, z, U;
-      U = gmael(FpX_factor(polcyclo(pg,MAXVARN),l),1,1);
+      U = gmael(FpX_factor(polcyclo(pg,fetch_var()),l),1,1);
       A = FpX_intersect_ker(P, MA, U, l);
       B = FpX_intersect_ker(Q, MB, U, l);
       if (DEBUGLEVEL>=4) timer_start(&T);
@@ -1324,6 +1350,7 @@ FpX_ffintersect(GEN P, GEN Q, long n, GEN l, GEN *SP, GEN *SQ, GEN MA, GEN MB)
       B = FqX_Fq_mul(B,L,U,l);
       A = FpXY_evalx(A,gen_0,l);
       B = FpXY_evalx(B,gen_0,l);
+      (void)delete_var();
     }
   }
   if (e)
@@ -1341,7 +1368,7 @@ FpX_ffintersect(GEN P, GEN Q, long n, GEN l, GEN *SP, GEN *SQ, GEN MA, GEN MB)
       if (j)
       {
         Ay = FpXQ_mul(Ay,FpXQ_pow(Ap,lmun,P,l),P,l);
-        VP = RgX_to_RgV(Ay,np);
+        VP = RgX_to_RgC(Ay,np);
       }
       Ap = FpM_FpC_invimage(MA,VP,l);
       Ap = RgV_to_RgX(Ap,vp);
@@ -1349,7 +1376,7 @@ FpX_ffintersect(GEN P, GEN Q, long n, GEN l, GEN *SP, GEN *SQ, GEN MA, GEN MB)
       if (j)
       {
         By = FpXQ_mul(By,FpXQ_pow(Bp,lmun,Q,l),Q,l);
-        VQ = RgX_to_RgV(By,nq);
+        VQ = RgX_to_RgC(By,nq);
       }
       Bp = FpM_FpC_invimage(MB,VQ,l);
       Bp = RgV_to_RgX(Bp,vq);
@@ -1441,9 +1468,9 @@ Flx_factorff_irred(GEN P, GEN Q, ulong p)
   long np = degpol(P), nq = degpol(Q), d = cgcd(np,nq);
   long i, vp = P[1], vq = Q[1];
   if (d==1) retmkcol(Flx_to_FlxX(P, vq));
-  FQ = Flxq_matrix_pow(Flxq_powu(polx_Flx(vq),p,Q,p),nq,nq,Q,p);
+  FQ = Flx_matFrobenius(Q,p);
   av = avma;
-  FP = Flxq_matrix_pow(Flxq_powu(polx_Flx(vp),p,P,p),np,np,P,p);
+  FP = Flx_matFrobenius(P,p);
   Flx_ffintersect(P,Q,d,p,&SP,&SQ, FP, FQ);
   E = Flx_factorgalois(P,p,d,vq, FP);
   E = FlxX_to_Flm(E,np);
@@ -1489,9 +1516,9 @@ FpX_factorff_irred(GEN P, GEN Q, GEN p)
   {
     GEN SP, SQ, MP, MQ, M, FP, FQ, E, V, IR;
     long i, vp = varn(P), vq = varn(Q);
-    FQ = FpXQ_matrix_pow(FpXQ_pow(pol_x(vq),p,Q,p),nq,nq,Q,p);
+    FQ = FpX_matFrobenius(Q,p);
     av = avma;
-    FP = FpXQ_matrix_pow(FpXQ_pow(pol_x(vp),p,P,p),np,np,P,p);
+    FP = FpX_matFrobenius(P,p);
     FpX_ffintersect(P,Q,d,p,&SP,&SQ,FP,FQ);
 
     E = FpX_factorgalois(P,p,d,vq,FP);
@@ -1647,7 +1674,7 @@ static void
 Flx_resultant_set_dglist(GEN a, GEN b, GEN dglist, ulong p)
 {
   long da,db,dc, ind;
-  pari_sp av = avma, lim = stack_lim(av, 2);
+  pari_sp av = avma;
 
   if (lgpol(a)==0 || lgpol(b)==0) return;
   da = degpol(a);
@@ -1664,7 +1691,7 @@ Flx_resultant_set_dglist(GEN a, GEN b, GEN dglist, ulong p)
 
     ind++;
     if (dc > dglist[ind]) dglist[ind] = dc;
-    if (low_stack(lim,stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"Flx_resultant_all");
       gerepileall(av, 2, &a,&b);
@@ -1683,7 +1710,7 @@ Flx_resultant_all(GEN a, GEN b, long *C0, long *C1, GEN dglist, ulong p)
   long da,db,dc, ind;
   ulong lb, res, g = 1UL, h = 1UL, ca = 1UL, cb = 1UL;
   int s = 1;
-  pari_sp av = avma, lim = stack_lim(av,2);
+  pari_sp av = avma;
 
   *C0 = 1; *C1 = 0;
   if (lgpol(a)==0 || lgpol(b)==0) return 0;
@@ -1729,7 +1756,7 @@ Flx_resultant_all(GEN a, GEN b, long *C0, long *C1, GEN dglist, ulong p)
     else
       h = Fl_mul(h, Fl_powu(Fl_div(g,h,p), delta, p), p);
 
-    if (low_stack(lim,stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"Flx_resultant_all");
       gerepileall(av, 2, &a,&b);
@@ -1765,7 +1792,7 @@ polint_triv(GEN xa, GEN ya)
 {
   GEN P = NULL, Q = roots_to_pol(xa,0);
   long i, n = lg(xa);
-  pari_sp av = avma, lim = stack_lim(av, 2);
+  pari_sp av = avma;
   for (i=1; i<n; i++)
   {
     GEN T, dP, r;
@@ -1780,7 +1807,7 @@ polint_triv(GEN xa, GEN ya)
     else
       dP = gdiv(gmul(gel(ya,i), T), r);
     P = P? gadd(P, dP): dP;
-    if (low_stack(lim,stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"polint_triv2 (i = %ld)",i);
       P = gerepileupto(av, P);
@@ -1794,8 +1821,7 @@ FpV_polint(GEN xa, GEN ya, GEN p, long v)
 {
   GEN inv,T,dP, P = NULL, Q = FpV_roots_to_pol(xa, p, v);
   long i, n = lg(xa);
-  pari_sp av, lim;
-  av = avma; lim = stack_lim(av,2);
+  pari_sp av = avma;
   for (i=1; i<n; i++)
   {
     if (!signe(gel(ya,i))) continue;
@@ -1810,7 +1836,7 @@ FpV_polint(GEN xa, GEN ya, GEN p, long v)
     else
       dP = FpX_Fp_mul(T, Fp_mul(gel(ya,i),inv,p), p);
     P = P? FpX_add(P, dP, p): dP;
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"FpV_polint");
       P = gerepileupto(av, P);
@@ -1943,10 +1969,10 @@ Flx_FlxY_eval_resultant(GEN a, GEN b, ulong n, ulong p, ulong la)
   return r;
 }
 static GEN
-FpX_FpXY_eval_resultant(GEN a, GEN b, GEN n, GEN p, GEN la)
+FpX_FpXY_eval_resultant(GEN a, GEN b, GEN n, GEN p, GEN la, long db, long vX)
 {
-  GEN ev = FpXY_evalx(b, n, p);
-  long drop=lg(b)-lg(ev);
+  GEN ev = FpXY_evaly(b, n, p, vX);
+  long drop = db-degpol(ev);
   GEN r = FpX_resultant(a, ev, p);
   if (drop && !gequal1(la)) r = Fp_mul(r, Fp_powu(la, drop,p),p);
   return r;
@@ -1955,7 +1981,7 @@ FpX_FpXY_eval_resultant(GEN a, GEN b, GEN n, GEN p, GEN la)
 /* assume dres := deg(Res_X(a,b), Y) <= deg(a,X) * deg(b,Y) < p */
 /* Return a Fly */
 static GEN
-Flx_FlyX_resultant_polint(GEN a, GEN b, ulong p, ulong dres, long sx)
+Flx_FlxY_resultant_polint(GEN a, GEN b, ulong p, ulong dres, long sx)
 {
   ulong i, n, la = Flx_lead(a);
   GEN  x = cgetg(dres+2, t_VECSMALL);
@@ -1978,13 +2004,13 @@ static GEN
 FlxX_pseudorem(GEN x, GEN y, ulong p)
 {
   long vx = varn(x), dx, dy, dz, i, lx, dp;
-  pari_sp av = avma, av2, lim;
+  pari_sp av = avma, av2;
 
   if (!signe(y)) pari_err_INV("FlxX_pseudorem",y);
   (void)new_chunk(2);
   dx=degpol(x); x = RgX_recip_shallow(x)+2;
   dy=degpol(y); y = RgX_recip_shallow(y)+2; dz=dx-dy; dp = dz+1;
-  av2 = avma; lim = stack_lim(av2,1);
+  av2 = avma;
   for (;;)
   {
     gel(x,0) = Flx_neg(gel(x,0), p); dp--;
@@ -1995,7 +2021,7 @@ FlxX_pseudorem(GEN x, GEN y, ulong p)
       gel(x,i) = Flx_mul(gel(y,0), gel(x,i), p);
     do { x++; dx--; } while (dx >= 0 && lg(gel(x,0))==2);
     if (dx < dy) break;
-    if (low_stack(lim,stack_lim(av2,1)))
+    if (gc_needed(av2,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"FlxX_pseudorem dx = %ld >= %ld",dx,dy);
       gerepilecoeffs(av2,x,dx+1);
@@ -2008,7 +2034,7 @@ FlxX_pseudorem(GEN x, GEN y, ulong p)
   x = RgX_recip_shallow(x);
   if (dp)
   { /* multiply by y[0]^dp   [beware dummy vars from FpX_FpXY_resultant] */
-    GEN t = Flx_pow(gel(y,0), dp, p);
+    GEN t = Flx_powu(gel(y,0), dp, p);
     for (i=2; i<lx; i++)
       gel(x,i) = Flx_mul(gel(x,i), t, p);
   }
@@ -2019,7 +2045,7 @@ FlxX_pseudorem(GEN x, GEN y, ulong p)
 GEN
 FlxX_resultant(GEN u, GEN v, ulong p, long sx)
 {
-  pari_sp av = avma, av2, lim;
+  pari_sp av = avma, av2;
   long degq,dx,dy,du,dv,dr,signh;
   GEN z,g,h,r,p1;
 
@@ -2030,9 +2056,9 @@ FlxX_resultant(GEN u, GEN v, ulong p, long sx)
     if (both_odd(dx, dy)) signh = -signh;
   }
   if (dy < 0) return zero_Flx(sx);
-  if (dy==0) return gerepileupto(av, Flx_pow(gel(v,2),dx,p));
+  if (dy==0) return gerepileupto(av, Flx_powu(gel(v,2),dx,p));
 
-  g = h = pol1_Flx(sx); av2 = avma; lim = stack_lim(av2,1);
+  g = h = pol1_Flx(sx); av2 = avma;
   for(;;)
   {
     r = FlxX_pseudorem(u,v,p); dr = lg(r);
@@ -2045,20 +2071,20 @@ FlxX_resultant(GEN u, GEN v, ulong p, long sx)
       case 1:
         p1 = Flx_mul(h,p1, p); h = g; break;
       default:
-        p1 = Flx_mul(Flx_pow(h,degq,p), p1, p);
-        h = Flx_div(Flx_pow(g,degq,p), Flx_pow(h,degq-1,p), p);
+        p1 = Flx_mul(Flx_powu(h,degq,p), p1, p);
+        h = Flx_div(Flx_powu(g,degq,p), Flx_powu(h,degq-1,p), p);
     }
     if (both_odd(du,dv)) signh = -signh;
     v = FlxY_Flx_div(r, p1, p);
     if (dr==3) break;
-    if (low_stack(lim,stack_lim(av2,1)))
+    if (gc_needed(av2,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"resultant_all, dr = %ld",dr);
       gerepileall(av2,4, &u, &v, &g, &h);
     }
   }
   z = gel(v,2);
-  if (dv > 1) z = Flx_div(Flx_pow(z,dv,p), Flx_pow(h,dv-1,p), p);
+  if (dv > 1) z = Flx_div(Flx_powu(z,dv,p), Flx_powu(h,dv-1,p), p);
   if (signh < 0) z = Flx_neg(z,p);
   return gerepileupto(av, z);
 }
@@ -2087,7 +2113,7 @@ Flx_FlxY_resultant(GEN a, GEN b, ulong pp)
   if ((ulong)dres >= pp)
     z = FlxX_resultant(Fly_to_FlxY(a, sy), b, pp, sx);
   else
-    z = Flx_FlyX_resultant_polint(a, b, pp, (ulong)dres, sy);
+    z = Flx_FlxY_resultant_polint(a, b, pp, (ulong)dres, sy);
   return gerepileupto(ltop,z);
 }
 
@@ -2114,19 +2140,19 @@ swap_vars(GEN b0, long v)
 GEN
 FpX_FpXY_resultant(GEN a, GEN b, GEN p)
 {
-  long i,n,dres, vX = varn(b), vY = varn(a);
+  long i,n,dres, db, vY = varn(b), vX = varn(a);
   GEN la,x,y;
 
   if (lgefint(p) == 3)
   {
-    ulong pp = (ulong)p[2];
-    b = ZXX_to_FlxX(b, pp, vY);
+    ulong pp = uel(p,2);
+    b = ZXX_to_FlxX(b, pp, vX);
     a = ZX_to_Flx(a, pp);
     x = Flx_FlxY_resultant(a, b, pp);
     return Flx_to_ZX(x);
   }
-  dres = degpol(a)*degpol(b);
-  b = swap_vars(b, vY);
+  db = RgXY_degreex(b);
+  dres = degpol(a)*db;
   la = leading_term(a);
   x = cgetg(dres+2, t_VEC);
   y = cgetg(dres+2, t_VEC);
@@ -2135,42 +2161,37 @@ FpX_FpXY_resultant(GEN a, GEN b, GEN p)
   for (i=0,n = 1; i < dres; n++)
   {
     gel(x,++i) = utoipos(n);
-    gel(y,i) = FpX_FpXY_eval_resultant(a,b,gel(x,i),p,la);
+    gel(y,i) = FpX_FpXY_eval_resultant(a,b,gel(x,i),p,la,db,vY);
     gel(x,++i) = subis(p,n);
-    gel(y,i) = FpX_FpXY_eval_resultant(a,b,gel(x,i),p,la);
+    gel(y,i) = FpX_FpXY_eval_resultant(a,b,gel(x,i),p,la,db,vY);
   }
   if (i == dres)
   {
     gel(x,++i) = gen_0;
-    gel(y,i) = FpX_FpXY_eval_resultant(a,b, gel(x,i), p,la);
+    gel(y,i) = FpX_FpXY_eval_resultant(a,b, gel(x,i), p,la,db,vY);
   }
-  return FpV_polint(x,y, p, vX);
+  return FpV_polint(x,y, p, vY);
 }
 
 GEN
-FpX_direct_compositum(GEN A, GEN B, GEN p)
+FpX_direct_compositum(GEN a, GEN b, GEN p)
 {
-  GEN a, b, x;
-  a = leafcopy(A); setvarn(a, MAXVARN);
-  b = leafcopy(B); setvarn(b, MAXVARN);
-  x = deg1pol_shallow(gen_1, pol_x(MAXVARN), 0); /* x + y */
-  return FpX_FpXY_resultant(a, poleval(b,x),p);
+  GEN x = deg1pol_shallow(gen_1, pol_x(varn(a)), fetch_var_higher()); /* x+y */
+  x = FpX_FpXY_resultant(a, poleval(b,x),p);
+  (void)delete_var(); return x;
 }
 
 /* 0, 1, -1, 2, -2, ... */
 #define next_lambda(a) (a>0 ? -a : 1-a)
 GEN
-FpX_compositum(GEN A, GEN B, GEN p)
+FpX_compositum(GEN a, GEN b, GEN p)
 {
-  GEN a, b;
-  long k;
-  a = leafcopy(A); setvarn(a, MAXVARN);
-  b = leafcopy(B); setvarn(b, MAXVARN);
+  long k, v = fetch_var_higher();
   for (k = 1;; k = next_lambda(k))
   {
-    GEN x = deg1pol_shallow(gen_1, gmulsg(k, pol_x(MAXVARN)), 0); /* x + k y */
+    GEN x = deg1pol_shallow(gen_1, gmulsg(k, pol_x(v)), 0); /* x + k y */
     GEN C = FpX_FpXY_resultant(a, poleval(b,x),p);
-    if (FpX_is_squarefree(C, p)) return C;
+    if (FpX_is_squarefree(C, p)) { (void)delete_var(); return C; }
   }
 }
 
@@ -2197,15 +2218,20 @@ init_modular(forprime_t *S) { u_forprime_init(S, 27449, ULONG_MAX); }
 GEN
 ZX_ZXY_resultant_all(GEN A, GEN B0, long *plambda, GEN *LERS)
 {
-  int checksqfree = plambda? 1: 0, delvar = 0, stable;
+#ifdef LONG_IS_64BIT
+  ulong pstart = 4611686018427388039UL;
+#else
+  ulong pstart = 1073741827UL;
+#endif
+  int checksqfree = plambda? 1: 0, stable;
   long lambda = plambda? *plambda: 0, cnt = 0;
   ulong bound, p, dp;
-  pari_sp av = avma, av2 = 0, lim;
+  pari_sp av = avma, av2 = 0;
   long i,n, lb, degA = degpol(A), dres = degA*degpol(B0);
-  long vX = varn(B0), vY = varn(A); /* assume vX << vY */
+  long v = fetch_var_higher();
+  long vX = varn(B0), vY = varn(A); /* assume vY has lower priority */
   long sX = evalvarn(vX);
-  GEN x, y, dglist, dB, B, q, a, b, ev, H, H0, H1, Hp, H0p, H1p, C0, C1, L;
-  forprime_t S;
+  GEN x, y, dglist, dB, B, q, a, b, ev, H, H0, H1, Hp, H0p, H1p, C0, C1;
 
   dglist = Hp = H0p = H1p = C0 = C1 = NULL; /* gcc -Wall */
   if (LERS)
@@ -2218,28 +2244,21 @@ ZX_ZXY_resultant_all(GEN A, GEN B0, long *plambda, GEN *LERS)
   }
   x = cgetg(dres+2, t_VECSMALL);
   y = cgetg(dres+2, t_VECSMALL);
-  if (vY == MAXVARN)
-  {
-    vY = fetch_var(); delvar = 1;
-    B0 = gsubst(B0, MAXVARN, pol_x(vY));
-    A = leafcopy(A); setvarn(A, vY);
-  }
-  L = pol_x(MAXVARN);
   B0 = Q_remove_denom(B0, &dB);
-  lim = stack_lim(av,2);
-
+  if (!dB) B0 = leafcopy(B0);
+  A = leafcopy(A);
+  B = B0;
+  setvarn(A,v);
   /* make sure p large enough */
-  u_forprime_init(&S, maxuu(dres << 1, 27499), ULONG_MAX);
+  p = pstart-1;
 INIT:
-  /* allways except the first time */
+  /* always except the first time */
   if (av2) { avma = av2; lambda = next_lambda(lambda); }
-  if (checksqfree)
-  {
-    /* # + lambda */
-    L = deg1pol_shallow(stoi(lambda), pol_x(MAXVARN), vY);
-    if (DEBUGLEVEL>4) err_printf("Trying lambda = %ld\n", lambda);
-  }
-  B = poleval(B0, L); av2 = avma;
+  if (lambda) B = RgX_translate(B0, monomial(stoi(lambda), 1, vY));
+  B = swap_vars(B, vY); setvarn(B,v);
+  /* B0(lambda v + x, v) */
+  if (DEBUGLEVEL>4 && checksqfree) err_printf("Trying lambda = %ld\n", lambda);
+  av2 = avma;
 
   if (degA <= 3)
   { /* sub-resultant faster for small degrees */
@@ -2263,8 +2282,9 @@ INIT:
   bound = ZX_ZXY_ResBound(A, B, dB);
   if (DEBUGLEVEL>4) err_printf("bound for resultant coeffs: 2^%ld\n",bound);
   dp = 1;
-  while ((p = u_forprime_next(&S)))
+  while (1)
   {
+    p = unextprime(p+1);
     if (dB) { dp = smodis(dB, p); if (!dp) continue; }
 
     a = ZX_to_Flx(A, p);
@@ -2306,7 +2326,7 @@ INIT:
     else
     {
       long dropa = degA - degpol(a), dropb = lb - lg(b);
-      Hp = Flx_FlyX_resultant_polint(a, b, p, (ulong)dres, sX);
+      Hp = Flx_FlxY_resultant_polint(a, b, p, (ulong)dres, sX);
       if (dropa && dropb)
         Hp = zero_Flx(sX);
       else {
@@ -2315,7 +2335,7 @@ INIT:
           GEN c = gel(b,lb-1); /* lc(B) */
           if (!odd(lb)) c = Flx_neg(c, p); /* deg B = lb - 3 */
           if (!Flx_equal1(c)) {
-            c = Flx_pow(c, dropa, p);
+            c = Flx_powu(c, dropa, p);
             if (!Flx_equal1(c)) Hp = Flx_mul(Hp, c, p);
           }
         }
@@ -2361,16 +2381,15 @@ INIT:
     if (DEBUGLEVEL>5 && (stable ||  ++cnt==100))
     { cnt=0; err_printf("%ld%%%s ",100*expi(q)/bound,stable?"s":""); }
     if (stable && (ulong)expi(q) >= bound) break; /* DONE */
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"ZX_ZXY_rnfequation");
       gerepileall(av2, LERS? 4: 2, &H, &q, &H0, &H1);
     }
   }
-  if (!p) pari_err_OVERFLOW("ZX_ZXY_rnfequation [ran out of primes]");
 END:
   if (DEBUGLEVEL>5) err_printf(" done\n");
-  setvarn(H, vX); if (delvar) (void)delete_var();
+  setvarn(H, vX); (void)delete_var();
   if (plambda) *plambda = lambda;
   if (LERS)
   {
@@ -2446,7 +2465,7 @@ fp_resultant(GEN a, GEN b)
 {
   long da, db, dc;
   GEN res = gen_1;
-  pari_sp av, lim;
+  pari_sp av;
 
   if (lgpol(a)==0 || lgpol(b)==0) return gen_0;
   da = degpol(a);
@@ -2457,7 +2476,7 @@ fp_resultant(GEN a, GEN b)
     if (both_odd(da,db)) res = gneg(res);
   }
   else if (!da) return gen_1; /* = res * a[2] ^ db, since 0 <= db <= da = 0 */
-  av = avma; lim = stack_lim(av, 1);
+  av = avma;
   while (db)
   {
     GEN lb = gel(b,db+2), c = RgX_rem(a,b);
@@ -2467,7 +2486,7 @@ fp_resultant(GEN a, GEN b)
 
     if (both_odd(da,db)) res = gneg(res);
     res = gmul(res, gpowgs(lb, da - dc));
-    if (low_stack(lim, stack_lim(av,1))) {
+    if (gc_needed(av,1)) {
       if (DEBUGMEM>1) pari_warn(warnmem,"fp_resultant");
       gerepileall(av, 3, &a,&b,&res);
     }
@@ -2477,21 +2496,103 @@ fp_resultant(GEN a, GEN b)
   return gerepileupto(av, gmul(res, gpowgs(gel(b,2), da)));
 }
 
+static long
+get_nbprimes(ulong bound, ulong *pt_start)
+{
+#ifdef LONG_IS_64BIT
+  ulong pstart = 4611686018427388039UL;
+#else
+  ulong pstart = 1073741827UL;
+#endif
+  *pt_start = pstart;
+  return (bound/expu(pstart))+1;
+}
+
+static ulong
+ZX_resultant_prime(GEN a, GEN b, GEN dB, long degA, long degB, ulong p)
+{
+  pari_sp av = avma;
+  ulong H;
+  long dropa, dropb;
+  ulong dp = dB ? umodiu(dB, p): 1;
+  if (!b) b = Flx_deriv(a, p);
+  dropa = degA - degpol(a);
+  dropb = degB - degpol(b);
+  if (dropa && dropb) /* p | lc(A), p | lc(B) */
+  { avma = av; return 0; }
+  H = Flx_resultant(a, b, p);
+  if (dropa)
+  { /* multiply by ((-1)^deg B lc(B))^(deg A - deg a) */
+    ulong c = b[degB+2]; /* lc(B) */
+    if (odd(degB)) c = p - c;
+    c = Fl_powu(c, dropa, p);
+    if (c != 1) H = Fl_mul(H, c, p);
+  }
+  else if (dropb)
+  { /* multiply by lc(A)^(deg B - deg b) */
+    ulong c = a[degA+2]; /* lc(A) */
+    c = Fl_powu(c, dropb, p);
+    if (c != 1) H = Fl_mul(H, c, p);
+  }
+  if (dp != 1) H = Fl_mul(H, Fl_powu(Fl_inv(dp,p), degA, p), p);
+  avma = av; return H;
+}
+
+/* If B=NULL, assume B=A' */
+static GEN
+ZX_resultant_slice(GEN A, GEN B, GEN dB, ulong p, long n, ulong *plast, GEN *mod)
+{
+  pari_sp av = avma;
+  long degA, degB, i;
+  GEN H, P, T;
+
+  degA = degpol(A);
+  degB = B ? degpol(B): degA - 1;
+  if (n == 1)
+  {
+    ulong Hp;
+    GEN a, b;
+    if (dB) while (umodiu(dB, p)==0) p = unextprime(p+1);
+    a = ZX_to_Flx(A, p), b = B ? ZX_to_Flx(B, p): NULL;
+    Hp = ZX_resultant_prime(a, b, dB, degA, degB, p);
+    avma = av;
+    *plast = unextprime(p+1); *mod = utoi(p); return utoi(Hp);
+  }
+  P = cgetg(n+1, t_VECSMALL);
+  for (i=1; i <= n; i++, p = unextprime(p+1))
+  {
+    if (dB && umodiu(dB, p)==0) { i--; continue; }
+    P[i] = p;
+  }
+  T = ZV_producttree(P);
+  A = ZX_nv_mod_tree(A, P, T);
+  if (B) B = ZX_nv_mod_tree(B, P, T);
+  H = cgetg(n+1, t_VECSMALL);
+  for(i=1; i <= n; i++)
+  {
+    ulong p = P[i];
+    GEN a = gel(A, i), b = B ? gel(B, i): NULL;
+    H[i] = ZX_resultant_prime(a, b, dB, degA, degB, p);
+  }
+  H = ZV_chinese_tree(H, P, T, mod); *plast=p;
+  gerepileall(av, 2, &H, mod);
+  return H;
+}
+
 /* Res(A, B/dB), assuming the A,B in Z[X] and result is integer */
+/* if B=NULL, take B = A' */
 GEN
 ZX_resultant_all(GEN A, GEN B, GEN dB, ulong bound)
 {
-  ulong Hp, dp, p;
-  pari_sp av = avma, av2, lim;
-  long degA, degB, cnt=0;
-  int stable;
-  GEN q, a, b, H;
-  forprime_t S;
+  ulong p;
+  pari_sp av = avma;
+  long degA, n, m;
+  GEN  H, P, mod;
+  int is_disc = !B;
+  if (is_disc) B = ZX_deriv(A);
 
   if ((H = trivial_case(A,B)) || (H = trivial_case(B,A))) return H;
-  q = H = NULL;
   degA = degpol(A);
-  degB = degpol(B);
   if (!bound)
   {
     bound = ZX_ZXY_ResBound(A, B, dB);
@@ -2512,57 +2613,30 @@ ZX_resultant_all(GEN A, GEN B, GEN dB, ulong bound)
       }
     }
   }
-  if (DEBUGLEVEL>4) err_printf("bound for resultant: 2^%ld\n",bound);
-  init_modular(&S);
-  av2 = avma; lim = stack_lim(av,2);
-
-  dp = 1; /* denominator mod p */
-  while ((p = u_forprime_next(&S)))
+  n = get_nbprimes(bound+1, &p);/* +1 to account for sign */
+  if (is_disc)
+    B = NULL;
+  m = minss(degpol(A)+(B ? degpol(B): 0), n);
+  if (m == 1)
+    H = ZX_resultant_slice(A, B, dB, p, n, &p, &mod);
+  else
   {
-    long dropa, dropb;
-    if (dB) { dp = smodis(dB, p); if (!dp) continue; }
-
-    a = ZX_to_Flx(A, p); dropa = degA - degpol(a);
-    b = ZX_to_Flx(B, p); dropb = degB - degpol(b);
-    if (dropa && dropb) /* p | lc(A), p | lc(B) */
-      Hp = 0;
-    else
-    {
-      Hp = Flx_resultant(a, b, p);
-      if (dropa)
-      { /* multiply by ((-1)^deg B lc(B))^(deg A - deg a) */
-        ulong c = b[degB+2]; /* lc(B) */
-        if (odd(degB)) c = p - c;
-        c = Fl_powu(c, dropa, p);
-        if (c != 1) Hp = Fl_mul(Hp, c, p);
-      }
-      else if (dropb)
-      { /* multiply by lc(A)^(deg B - deg b) */
-        ulong c = a[degA+2]; /* lc(A) */
-        c = Fl_powu(c, dropb, p);
-        if (c != 1) Hp = Fl_mul(Hp, c, p);
-      }
-      if (dp != 1) Hp = Fl_mul(Hp, Fl_powu(Fl_inv(dp,p), degA, p), p);
-    }
-
-    if (!H)
+    long i, s = n/m, r = n - m*s;
+    if (DEBUGLEVEL > 4)
+      err_printf("ZX_resultant: bound 2^%ld, nb primes: %ld\n",bound, n);
+    H = cgetg(m+1+!!r, t_VEC); P = cgetg(m+1+!!r, t_VEC);
+    for (i=1; i<=m; i++)
     {
-      stable = 0; q = utoipos(p);
-      H = Z_init_CRT(Hp, p);
-    }
-    else /* could make it probabilistic ??? [e.g if stable twice, etc] */
-      stable = Z_incremental_CRT(&H, Hp, &q, p);
-    if (DEBUGLEVEL>5 && (stable ||  cnt++==2000))
-    { cnt=0; err_printf("%ld%%%s ",100*expi(q)/bound,stable?"s":""); }
-    if (stable && (ulong)expi(q) >= bound) break; /* DONE */
-    if (low_stack(lim, stack_lim(av,2)))
-    {
-      if (DEBUGMEM>1) pari_warn(warnmem,"ZX_resultant");
-      gerepileall(av2, 2, &H,&q);
+      gel(H, i) = ZX_resultant_slice(A, B, dB, p, s, &p, &gel(P, i));
+      if (DEBUGLEVEL>5) err_printf("%ld%% ",100*i/m);
     }
+    if (r)
+      gel(H, i) = ZX_resultant_slice(A, B, dB, p, r, &p, &gel(P, i));
+    H = ZV_chinese(H, P, &mod);
+    if (DEBUGLEVEL>5) err_printf("done\n");
   }
-  if (DEBUGLEVEL>5) err_printf("done\n");
-  return gerepileuptoint(av, icopy(H));
+  H = Fp_center(H, mod, shifti(mod,-1));
+  return gerepileuptoint(av, H);
 }
 
 /* A0 and B0 in Q[X] */
@@ -2630,7 +2704,7 @@ ZX_disc_all(GEN x, ulong bound)
   if (d <= 1) return d ? gen_1: gen_0;
   s = (d & 2) ? -1: 1;
   l = leading_term(x);
-  R = ZX_resultant_all(x, ZX_deriv(x), NULL, bound);
+  R = ZX_resultant_all(x, NULL, NULL, bound);
   if (is_pm1(l))
   { if (signe(l) < 0) s = -s; }
   else
@@ -2655,7 +2729,7 @@ QXQ_inv(GEN A, GEN B)
 {
   GEN D, cU, q, U, V;
   ulong p;
-  pari_sp av2, av = avma, avlim = stack_lim(av, 1);
+  pari_sp av2, av = avma;
   forprime_t S;
 
   if (is_scalar_t(typ(A))) return scalarpol(ginv(A), varn(B));
@@ -2696,7 +2770,7 @@ QXQ_inv(GEN A, GEN B)
       if (DEBUGLEVEL) err_printf("QXQ_inv: char 0 check failed");
     }
     q = qp;
-    if (low_stack(avlim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"QXQ_inv");
       gerepileall(av2, 3, &q,&U,&V);
@@ -2731,25 +2805,23 @@ ffinit_rand(GEN p,long n)
 static GEN
 f2init(long l)
 {
-  long i;
   GEN Q, T, S;
+  long i, v;
 
-  if (l == 1) return polcyclo(3, MAXVARN);
-
+  if (l == 1) return polcyclo(3, 0);
+  v = fetch_var_higher();
   S = mkpoln(4, gen_1,gen_1,gen_0,gen_0); /* y(y^2 + y) */
-  setvarn(S, MAXVARN);
   Q = mkpoln(3, gen_1,gen_1, S); /* x^2 + x + y(y^2+y) */
+  setvarn(Q, v);
 
   /* x^4+x+1, irred over F_2, minimal polynomial of a root of Q */
   T = mkpoln(5, gen_1,gen_0,gen_0,gen_1,gen_1);
-  for (i=2; i<l; i++)
-  { /* Q = x^2 + x + a(y) irred. over K = F2[y] / (T(y))
-     * ==> x^2 + x + a(y) b irred. over K for any root b of Q
-     * ==> x^2 + x + (b^2+b)b */
-    setvarn(T,MAXVARN);
-    T = FpX_FpXY_resultant(T, Q, gen_2); /* = minpoly of b over F2 */
-  }
-  return T;
+  setvarn(T, v);
+  /* Q = x^2 + x + a(y) irred. over K = F2[y] / (T(y))
+   * ==> x^2 + x + a(y) b irred. over K for any root b of Q
+   * ==> x^2 + x + (b^2+b)b */
+  for (i=2; i<l; i++) T = FpX_FpXY_resultant(T, Q, gen_2); /* minpoly(b) / F2*/
+  (void)delete_var(); setvarn(T,0); return T;
 }
 
 /* return an extension of degree p^l of F_p, assume l > 0
@@ -2757,19 +2829,17 @@ f2init(long l)
 GEN
 ffinit_Artin_Shreier(GEN ip, long l)
 {
-  long i, p = itos(ip);
+  long i, v, p = itos(ip);
   GEN T, Q, xp = monomial(gen_1,p,0); /* x^p */
   T = ZX_sub(xp, deg1pol_shallow(gen_1,gen_1,0)); /* x^p - x - 1 */
   if (l == 1) return T;
 
-  Q = ZX_sub(monomial(gen_1,2*p-1,MAXVARN), monomial(gen_1,p,MAXVARN));
-  Q = gsub(xp, deg1pol_shallow(gen_1, Q, 0)); /* x^p - x - (y^(2p-1)-y^p) */
-  for (i = 2; i <= l; ++i)
-  {
-    setvarn(T,MAXVARN);
-    T = FpX_FpXY_resultant(T, Q, ip);
-  }
-  return T;
+  v = fetch_var_higher();
+  setvarn(xp, v);
+  Q = ZX_sub(monomial(gen_1,2*p-1,0), monomial(gen_1,p,0));
+  Q = gsub(xp, deg1pol_shallow(gen_1, Q, v)); /* x^p - x - (y^(2p-1)-y^p) */
+  for (i = 2; i <= l; ++i) T = FpX_FpXY_resultant(T, Q, ip);
+  (void)delete_var(); setvarn(T,0); return T;
 }
 
 /* check if polsubcyclo(n,l,0) is irreducible modulo p */
diff --git a/src/basemath/polclass.c b/src/basemath/polclass.c
new file mode 100644
index 0000000..e9bb478
--- /dev/null
+++ b/src/basemath/polclass.c
@@ -0,0 +1,1136 @@
+/* Copyright (C) 2014  The PARI group.
+
+This file is part of the PARI/GP package.
+
+PARI/GP 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. It is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY WHATSOEVER.
+
+Check the License for details. You should have received a copy of it, along
+with the package; see the file 'COPYING'. If not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+#include "pari.h"
+#include "paripriv.h"
+
+
+#define dbg_printf0(lvl, fmt) \
+  do { if ((lvl) <= DEBUGLEVEL) err_printf(fmt "\n"); } while (0)
+#define dbg_printf1(lvl, fmt, a1) \
+  do { if ((lvl) <= DEBUGLEVEL) err_printf(fmt "\n", (a1)); } while (0)
+#define dbg_printf2(lvl, fmt, a1, a2) \
+  do { if ((lvl) <= DEBUGLEVEL) err_printf(fmt "\n", (a1), (a2)); } while (0)
+#define dbg_printf3(lvl, fmt, a1, a2, a3) \
+  do { if ((lvl) <= DEBUGLEVEL) err_printf(fmt "\n", (a1), (a2), (a3)); } while (0)
+#define dbg_printf4(lvl, fmt, a1, a2, a3, a4) \
+  do { if ((lvl) <= DEBUGLEVEL) err_printf(fmt  "\n", (a1), (a2), (a3), (a4)); } while (0)
+#define dbg_printf dbg_printf1
+#define dbg_puts(lvl, str) dbg_printf0(lvl, str)
+
+/**
+ * SECTION: Functions dedicated to finding a j-invariant with a given
+ * trace.
+ */
+
+/* FIXME: This code is shared with
+ * torsion_compatible_with_characteristic() in 'torsion.c'. */
+static void
+hasse_bounds(long *low, long *high, long p)
+{
+  long two_sqrt_p = usqrt(4*p);
+  *low = p + 1 - two_sqrt_p;
+  *high = p + 1 + two_sqrt_p;
+}
+
+
+/*
+ * a and b must be the result of factoru_pow(), and b must divide a
+ * exactly.
+ */
+INLINE void
+famatsmall_divexact(GEN a, GEN b)
+{
+  long i, j;
+  for (i = j = 1; j < lg(gel(a, 1)) && i < lg(gel(b, 1)); ++j)
+    if (gel(a, 1)[j] == gel(b, 1)[i])
+      gel(a, 2)[j] -= gel(b, 2)[i++];
+
+  for (i = j = 1; j < lg(gel(a, 1)); ++j) {
+    if (gel(a, 2)[j]) {
+      gel(a, 1)[i] = gel(a, 1)[j];
+      gel(a, 2)[i] = gel(a, 2)[j];
+      ++i;
+    }
+  }
+  if (i == 1) {
+    /* b == a, so a must now be 1. */
+    gel(a, 1)[1] = 1;
+    gel(a, 2)[1] = 0;
+    setlg(gel(a, 1), 2);
+    setlg(gel(a, 2), 2);
+  } else {
+    setlg(gel(a, 1), i);
+    setlg(gel(a, 2), i);
+  }
+}
+
+
+/*
+ * This is Sutherland, 2009, TestCurveOrder.
+ *
+ * [a4, a6] and p specify an elliptic curve over FF_p.  N is a
+ * two-element array containing the two possible curve orders, and n
+ * is a two-element array containg the corresponding factorisations as
+ * famats.
+ */
+static long
+test_curve_order(
+  norm_eqn_t ne, ulong a4, ulong a6,
+  long N0, long N1, GEN n0, GEN n1,
+  long hasse[2])
+{
+  pari_sp ltop = avma, av;
+  ulong a4t, a6t;
+  long m0, m1;
+  long hasse_low, hasse_high;
+  ulong p = ne->p, pi = ne->pi, T = ne->T;
+  ulong swapped = 0;
+
+  if (p <= 11) {
+    long card = (long)p + 1 - Fl_elltrace(a4, a6, p);
+    return card == N0 || card == N1;
+  }
+
+  /* [a4, a6] is the given curve and [a4t, a6t] is its quadratic
+   * twist. */
+  Fl_elltwist(a4, a6, T, p, &a4t, &a6t);
+
+  m0 = m1 = 1;
+
+  if (N0 + N1 != 2 * (long)p + 2)
+    pari_err_BUG("test_curve_order");
+
+  hasse_low = hasse[0];
+  hasse_high = hasse[1];
+
+  av = avma;
+  for ( ; ; ) {
+    GEN pt, Q, tmp;
+    long a1, x, n_s;
+
+    pt = random_Flj_pre(a4, a6, p, pi);
+    Q = Flj_mulu_pre(pt, m0, a4, p, pi);
+    /* FIXME: This is wasteful -- try to work out how to go back to
+     * using the e0. */
+    tmp = gcopy(n0);
+    famatsmall_divexact(tmp, factoru(m0));
+    n_s = Flj_order_ufact(Q, N0 / m0, tmp, a4, p, pi);
+
+    if (n_s == 0) {
+      /* If m0 divides N1 and m1 divides N0 and N0 < N1,
+       * then swap. */
+      if ( ! swapped && N1 % m0 == 0 && N0 % m1 == 0) {
+        swapspec(n0, n1, N0, N1);
+        swapped = 1;
+        continue;
+      } else {
+        avma = ltop;
+        return 0;
+      }
+    }
+
+    m0 *= n_s;
+    a1 = (2 * p + 2) % m1;
+    /* Using ceil(n/d) = (n + d - 1)/d */
+    x = (hasse_low + m0 - 1) / m0;
+    x *= m0;
+    for ( ; x <= hasse_high; x += m0) {
+      if ((x % m1) == a1 && x != N0 && x != N1)
+        break;
+    }
+    /* We exited the loop because we finished iterating, not because
+     * of the break.  That means every x in N was either N0 or N1, so
+     * we return true. */
+    if (x > hasse_high) {
+      avma = ltop;
+      return 1;
+    }
+
+    lswap(a4, a4t);
+    lswap(a6, a6t);
+    lswap(m0, m1);
+    avma = av;
+  }
+}
+
+INLINE int
+jac_eq_or_opp(GEN P, GEN Q, ulong p, ulong pi)
+{
+  /* (X1:Y1:Z1) and (X2:Y2:Z2) in Jacobian coordinates are equal
+   * or opposite iff X1 Z2^2 = X2 Z1^2. */
+  return ! Fl_sub(Fl_mul_pre(P[1], Fl_sqr_pre(Q[3], p, pi), p, pi),
+                  Fl_mul_pre(Q[1], Fl_sqr_pre(P[3], p, pi), p, pi), p);
+}
+
+
+/* This is Sutherland 2009 Algorithm 1.1 */
+static long
+find_j_inv_with_given_trace(
+  ulong *j_t, norm_eqn_t ne, long rho_inv, long max_curves)
+{
+  pari_sp ltop = avma, av;
+  long curves_tested = 0, batch_size;
+  long N0, N1, hasse[2];
+  GEN n0, n1;
+  long i, found = 0;
+  ulong p = ne->p, pi = ne->pi;
+  long t = ne->t;
+  ulong p1 = p + 1, j = 0, m, c_1728 = 1728 % p;
+  GEN A4, A6, tx, ty;
+  /* This number must be the same as LAST_X1_LEVEL in 'torsion.c', */
+  enum { MAX_X1_CURVE_LVL = 39 };
+
+  /* ellap(ellinit(ellfromj(Mod(1,2)))) == -1
+   * ellap(ellinit(ellfromj(Mod(1,3)))) ==  1
+   * ellap(ellinit(ellfromj(Mod(2,3)))) ==  2 */
+  if (p == 2 || p == 3) {
+    if (t == 0)
+      pari_err_BUG("find_j_inv_with_given_trace");
+    *j_t = t;
+    return 1;
+  }
+
+  N0 = (long)p1 - t;
+  N1 = (long)p1 + t;
+  n0 = factoru(N0);
+  n1 = factoru(N1);
+
+  /* FIXME: Select m more intelligently.  Currently just the biggest
+   * common divisor of N0 and N1 less than 39. */
+  m = cgcd(N0, N1);
+  av = avma;
+  if (m > MAX_X1_CURVE_LVL) {
+    GEN factm = factoru(m);
+    long nfactors = lg(gel(factm, 1)) - 1;
+    for (i = 1; i <= nfactors; ) {
+      m /= gel(factm, 1)[i];
+      if (m <= MAX_X1_CURVE_LVL)
+        break;
+      gel(factm, 2)[i] -= 1;
+      if (gel(factm, 2)[i] == 0)
+        ++i;
+    }
+    avma = av;
+  }
+
+  /* Select batch size so that we have roughly a 50% chance of finding
+   * a good curve in a batch. */
+  batch_size = 1.0 + rho_inv / (2.0 * m);
+  A4 = cgetg(batch_size + 1, t_VECSMALL);
+  A6 = cgetg(batch_size + 1, t_VECSMALL);
+  tx = cgetg(batch_size + 1, t_VECSMALL);
+  ty = cgetg(batch_size + 1, t_VECSMALL);
+
+  if (DEBUGLEVEL > 1) {
+    err_printf("  Selected torsion constraint m = %lu and batch "
+               "size = %ld\n", m, batch_size);
+  }
+
+  hasse_bounds(&hasse[0], &hasse[1], p);
+
+  av = avma;
+  while ( ! found && (max_curves <= 0 || curves_tested < max_curves)) {
+    random_curves_with_m_torsion((ulong *)(A4 + 1), (ulong *)(A6 + 1),
+                                 (ulong *)(tx + 1), (ulong *)(ty + 1),
+                                 batch_size, m, p);
+    for (i = 1; i <= batch_size; ++i) {
+      ulong a4, a6;
+      GEN P, p1P, tP;
+      ++curves_tested;
+      a4 = A4[i];
+      a6 = A6[i];
+      j = Fl_ellj_pre(a4, a6, p, pi);
+      if (j == 0 || j == c_1728)
+        continue;
+
+      P = random_Flj_pre(a4, a6, p, pi);
+      p1P = Flj_mulu_pre(P, p1, a4, p, pi);
+      tP = Flj_mulu_pre(P, t, a4, p, pi);
+
+      if (jac_eq_or_opp(p1P, tP, p, pi)
+          && test_curve_order(ne, a4, a6, N0, N1, n0, n1, hasse)) {
+        found = 1;
+        break;
+      }
+      avma = av;
+    }
+  }
+  *j_t = j;
+  avma = ltop;
+  return curves_tested;
+}
+
+
+/**
+ * SECTION: Functions for dealing with polycyclic presentations.
+ */
+
+/* A polycyclic presentation P is a GEN with the following structure:
+ *
+ * gel(P, 1): t_VECSMALL of generator norms
+ * gel(P, 2): t_VECSMALL of relative orders
+ * gel(P, 3): t_VECSMALL of power relations
+ * gel(P, 4): t_VEC of all QFIs
+ */
+
+#define PCP_GEN_NORMS(P) gel((P), 1)
+#define PCP_REL_ORDERS(P) gel((P), 2)
+#define PCP_POW_RELS(P) gel((P), 3)
+#define PCP_QFI_TABLE(P) gel((P), 4)
+#define PCP_NGENS(P) (lg(PCP_GEN_NORMS(P)) - 1)
+
+INLINE ulong
+pcp_order(GEN P) { return zv_prod(PCP_REL_ORDERS(P)); }
+
+static GEN
+next_prime_generator(GEN DD, long D, ulong u, ulong *p)
+{
+  pari_sp av = avma, av1;
+  GEN gen, genred;
+  long norm;
+  while (1) {
+    *p = unextprime(*p + 1);
+    if (kross(D, (long)*p) != -1 && u % *p != 0) {
+      gen = primeform_u(DD, *p);
+      av1 = avma;
+
+      /* If the reduction of gen has norm = 1, then it is the identity
+       * form and is therefore skipped. */
+      genred = redimag(gen);
+      norm = itos(gel(genred, 1));
+      avma = av1;
+      if (norm != 1)
+        break;
+      avma = av;
+    }
+  }
+  return gen;
+}
+
+
+/* These wrappers circumvent a restriction in the C89 standard which
+ * requires that, for example, (S (*)(void *)) and (S (*)(T *)) are
+ * incompatible function pointer types whenever T != void (which is at
+ * least slightly surprising).  This prevents us from using explicit
+ * casts (ulong (*)(void *)) hash_GEN and (int (*)(void *, void *))
+ * gequal in the call to hash_create and obliges us to use these
+ * wrapper functions to do the cast explicitly.
+ *
+ * Refs:
+ * - Annex J.2
+ * - Section 6.3.2.3, paragraph 8
+ * - Section 6.7.5.1, paragraph 2
+ * - Section 6.7.5.3, paragraph 15
+ */
+static ulong
+hash_GEN_wrapper(void *x)
+{
+  return hash_GEN((GEN) x);
+}
+
+static int
+gequal_wrapper(void *x, void *y)
+{
+  return gequal((GEN) x, (GEN) y);
+}
+
+/*
+ * This is Sutherland 2009, Algorithm 2.2 (p16).
+ */
+static GEN
+minimal_polycyclic_presentation(ulong h, long D, ulong u)
+{
+  pari_sp av = avma;
+  ulong curr_p = 1, nelts = 1, i;
+  GEN DD, pcp, ident, T;
+  hashtable *tbl;
+
+  pcp = cgetg(5, t_VEC);
+
+  /* Trivial presentation */
+  gel(pcp, 1) = cgetg(1, t_VECSMALL);
+  gel(pcp, 2) = cgetg(1, t_VECSMALL);
+  gel(pcp, 3) = cgetg(1, t_VECSMALL);
+  gel(pcp, 4) = cgetg(h + 1, t_VECSMALL);
+  gel(pcp, 4)[1] = 1UL; /* Identity element has a = 1*/
+
+  if (h == 1)
+    return pcp;
+
+  DD = stoi(D);
+
+  /* Hash table has a QFI as a key and the (boxed) index of that QFI
+   * in T as its value */
+  tbl = hash_create(h, hash_GEN_wrapper, gequal_wrapper, 1);
+  T = vectrunc_init(h + 1);
+  ident = redimag(primeform_u(DD, 1));
+  vectrunc_append(T, ident);
+  hash_insert(tbl, ident, gen_1);
+
+  while (nelts < h) {
+    GEN gamma_i = next_prime_generator(DD, D, u, &curr_p);
+    GEN beta = redimag(gamma_i);
+    hashentry *e;
+    ulong N = glength(T), Tlen = N, ri = 1, si;
+
+    while ((e = hash_search(tbl, beta)) == NULL) {
+      ulong j;
+      for (j = 1; j <= N; ++j) {
+        GEN tmp = gmul(beta, gel(T, j));
+        vectrunc_append(T, tmp);
+        hash_insert(tbl, tmp, stoi(++Tlen));
+      }
+      beta = gmul(beta, gamma_i);
+      ++ri;
+    }
+    if (ri > 1) {
+      long j;
+      PCP_GEN_NORMS(pcp) = vecsmall_append(PCP_GEN_NORMS(pcp), curr_p);
+      PCP_REL_ORDERS(pcp) = vecsmall_append(PCP_REL_ORDERS(pcp), ri);
+      nelts *= ri;
+
+      N = 1;
+      si = itos((GEN) e->val);
+      /* NB: This decrement is because we need indices starting at 0
+       * for the formula in the for loop to work. */
+      si--;
+      for (j = 1; j < lg(PCP_REL_ORDERS(pcp)); ++j) {
+        ulong rj = PCP_REL_ORDERS(pcp)[j];
+        PCP_POW_RELS(pcp) = vecsmall_append(PCP_POW_RELS(pcp), (si / N) % rj);
+        N *= rj;
+      }
+    }
+  }
+  /* Put the a-values in gel(pcp, 4). */
+  for (i = 2; i <= h; ++i)
+    gel(pcp, 4)[i] = itou(gmael(T, i, 1));
+  return gerepileupto(av, pcp);
+}
+
+INLINE ulong
+classno_wrapper(long D)
+{
+  pari_sp av = avma;
+  GEN clsgp;
+  ulong h;
+  clsgp = quadclassunit0(stoi(D), 0, 0, DEFAULTPREC);
+  h = itou(gel(clsgp, 1));
+  avma = av;
+  return h;
+}
+
+
+/**
+ * SECTION: Functions for calculating class polynomials.
+ */
+
+#define HALFLOGPI 0.57236494292470008707171367567653
+
+/*
+ * Based on logfac() in Sutherland's classpoly package.
+ *
+ * Ramanujan approximation to log(n!), accurate to O(1/n^3)
+ */
+INLINE double
+logfac(long n)
+{
+  return n * log(n) - (double) n +
+    log((double) n * (1.0 + 4.0 * n * (1.0 + 2.0 * n))) / 6.0 +
+    HALFLOGPI;
+}
+
+
+#define LOG2E 1.44269504088896340735992468100189
+
+
+/* This is based on Sutherland 2009, Lemma 8 (p31). */
+static double
+upper_bound_on_classpoly_coeffs(long D, GEN pcp)
+{
+  pari_sp ltop = avma;
+  ulong h = pcp_order(pcp);
+  GEN C = dbltor(2114.567);
+  double Mk, m, logbinom;
+  GEN tmp = mulrr(mppi(LOWDEFAULTPREC), sqrtr(stor(-D, LOWDEFAULTPREC)));
+  /* We treat this case separately since the table is not initialised
+   * when h = 1. This is the same as in the for loop below but with ak
+   * = 1. */
+  double log2Mk = dbllog2r(mpadd(mpexp(tmp), C));
+  double res = log2Mk;
+  ulong maxak = 1;
+  double log2Mh = log2Mk;
+
+  pari_sp btop = avma;
+  ulong k;
+  for (k = 2; k <= h; ++k) {
+    ulong ak = PCP_QFI_TABLE(pcp)[k];
+    /* Unfortunately exp(tmp/a[k]) can overflow for even moderate
+     * discriminants, so we need to do this calculation with t_REALs
+     * instead of just doubles.  Sutherland has a (much more
+     * complicated) implementation in the classpoly package which
+     * should be consulted if this ever turns out to be a bottleneck.
+     *
+     * [Note that one idea to avoid t_REALs is the following: we have
+     * log(e^x + C) - x <= log(2) ~ 0.69 for x >= log(C) ~ 0.44 and
+     * the difference is basically zero for x slightly bigger than
+     * log(C).  Hence for large discriminants, we will always have x =
+     * \pi\sqrt{-D}/ak >> log(C) and so we could approximate log(e^x +
+     * C) by x.] */
+    log2Mk = dbllog2r(mpadd(mpexp(divru(tmp, ak)), C));
+    res += log2Mk;
+    if (ak > maxak) {
+      maxak = ak;
+      log2Mh = log2Mk;
+    }
+    avma = btop;
+  }
+
+  Mk = pow(2.0, log2Mh);
+  m = floor((h + 1)/(Mk + 1.0));
+  /* This line computes "log2(itos(binomialuu(h, m)))".  The smallest
+   * fundamental discriminant for which logbinom is not zero is
+   * -1579751. */
+  logbinom = (m > 0 && m < h)
+    ? LOG2E * (logfac(h) - logfac(m) - logfac(h - m))
+    : 0;
+  avma = ltop;
+  return res + logbinom - m * log2Mh + 2.0;
+}
+
+
+/* NB: Sutherland defines V_MAX to be 1200 with saying why. */
+#define V_MAX 1200
+
+#define NSMALL_PRIMES 11
+static const long small_primes[11] = {
+    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31
+};
+
+static long
+is_smooth_enough(ulong *factors, long v)
+{
+  long i;
+  *factors = 0;
+  for (i = 0; i < NSMALL_PRIMES; ++i) {
+    long p = small_primes[i];
+    if (v % p == 0)
+      *factors |= 1 << i;
+    while (v % p == 0)
+      v /= p;
+    if (v == 1)
+      break;
+  }
+  return v == 1;
+}
+
+
+/* Hurwitz class number of |D| assuming hclassno() and associated
+ * conversion to double costs much more than unegisfundamental(). */
+INLINE double
+hclassno_wrapper(long D, GEN pcp)
+{
+  /* FIXME: Can probably calculate hurwitz faster using -D, factor(u)
+   * and classno(D). */
+  pari_sp av = avma;
+  ulong abs_D = D < 0 ? -D : D;
+  double hurwitz;
+
+  if (pcp && unegisfundamental(abs_D))
+    hurwitz = (double) pcp_order(pcp);
+  else
+    hurwitz = rtodbl(gtofp(hclassno(utoi(abs_D)), DEFAULTPREC));
+  avma = av;
+  return hurwitz;
+}
+
+
+/*
+ * This is Sutherland 2009, Algorithm 2.1 (p8).
+ *
+ * NB: This function is not gerepileupto-safe.
+ */
+static GEN
+select_classpoly_prime_pool(
+  long D, double min_prime_bits, double delta, GEN pcp)
+{
+  pari_sp av;
+  double prime_bits = 0.0, hurwitz, z;
+  ulong i;
+  /* t_min[v] will hold the lower bound of the t we need to look at
+   * for a given v. */
+  ulong t_min[V_MAX], t_size_lim;
+  GEN res;
+
+  if (delta <= 0)
+    pari_err_BUG("select_suitable_primes");
+  hurwitz = hclassno_wrapper(D, pcp);
+
+  res = cgetg(1, t_VEC);
+  /* Initialise t_min to be all 2's.  This avoids trace 0 and trace
+   * 1 curves. */
+  for (i = 0; i < V_MAX; ++i)
+    t_min[i] = 2;
+
+  /* maximum possible trace = sqrt(2^BIL - D) */
+  t_size_lim = 2.0 * sqrt((1UL << (BITS_IN_LONG - 2)) - (((ulong)-D) >> 2));
+
+  av = avma;
+  for (z = -D / (2.0 * hurwitz); ; z *= delta + 1.0) {
+    /* v_bound_aux = -4 z H(-D). */
+    double v_bound_aux = -4.0 * z * hurwitz;
+    ulong v;
+    dbg_printf(1, "z = %.2f", z);
+    for (v = 1; ; ++v) {
+      ulong pcount = 0, t, t_max, factors;
+      ulong m_vsqr_D = v * v * (ulong)(-D);
+      /* hurwitz_ratio_bound = 11 * log(log(v + 4))^2 */
+      double hurwitz_ratio_bound = log(log(v + 4.0)), max_p, H;
+      hurwitz_ratio_bound *= 11.0 * hurwitz_ratio_bound;
+
+      if (v >= v_bound_aux * hurwitz_ratio_bound / D || v >= V_MAX)
+        break;
+
+      if ( ! is_smooth_enough(&factors, v))
+        continue;
+      H = hclassno_wrapper(m_vsqr_D, 0);
+
+      /* t <= 2 sqrt(p) and p <= z H(-v^2 D) and
+       *
+       *   H(-v^2 D) < vH(-D) (11 log(log(v + 4))^2)
+       *
+       * This last term is v * hurwitz * hurwitz_ratio_bound. */
+
+      max_p = z * v * hurwitz * hurwitz_ratio_bound;
+      t_max = 2.0 * mindd(sqrt((1UL << (BITS_IN_LONG - 2)) - (m_vsqr_D >> 2)),
+                          sqrt(max_p));
+      for (t = t_min[v]; t <= t_max; ++t) {
+        ulong possible_4p = t * t + m_vsqr_D;
+        if (possible_4p % 4 == 0) {
+          ulong possible_p = possible_4p / 4;
+          if (uisprime(possible_p)) {
+            long p = possible_p;
+            double rho_inv;
+            GEN hit;
+
+            rho_inv = p / H;
+            hit = mkvecsmall4(p, t, v, (long)rho_inv);
+            /* FIXME: Avoid doing GC for every prime as here. */
+            res = gerepileupto(av, concat(res, hit));
+            prime_bits += log2(p);
+            ++pcount;
+          }
+        }
+      }
+      t_min[v] = t_max + 1;
+
+      if (pcount) {
+        dbg_printf2(2, "  Found %lu primes for v = %lu.", pcount, v);
+        if (gc_needed(av, 2))
+          res = gerepilecopy(av, res);
+      }
+      if (prime_bits > min_prime_bits) {
+        dbg_printf2(1, "Found %ld primes; total size %.2f bits.",
+                    glength(res), prime_bits);
+        return gerepilecopy(av, res);
+      }
+    }
+
+    /* Have we exhausted all possible solutions that fit in machine words? */
+    if (t_min[1] >= t_size_lim) {
+      char *err = stack_sprintf("class polynomial of discriminant %ld", D);
+      pari_err(e_ARCH, err);
+    }
+  }
+}
+
+
+static int
+primecmp(void *data, GEN v1, GEN v2)
+{
+  (void)data;
+  return v1[4] - v2[4];
+}
+
+
+static GEN
+select_classpoly_primes(
+  long D, long k, double delta, GEN pcp)
+{
+  pari_sp av = avma;
+  long i;
+  double prime_bits, min_prime_bits, b;
+  GEN prime_pool;
+
+  if (k < 2)
+    pari_err_BUG("select_suitable_primes");
+
+  b = upper_bound_on_classpoly_coeffs(D, pcp);
+  dbg_printf(1, "b = %.2f", b);
+  min_prime_bits = k * b;
+
+  prime_pool = select_classpoly_prime_pool(D, min_prime_bits, delta, pcp);
+
+  /* FIXME: Apply torsion constraints */
+  /* FIXME: Rank elts of res according to cost/benefit ratio */
+  prime_pool = gen_sort(prime_pool, 0, primecmp);
+
+  prime_bits = 0.0;
+  for (i = 1; i < lg(prime_pool); ++i) {
+    prime_bits += log2(gel(prime_pool, i)[1]);
+    if (prime_bits > b)
+      break;
+  }
+  dbg_printf(1, "Selected %ld primes.", i);
+  return gerepilecopy(av, vecslice0(prime_pool, 1, i));
+}
+
+
+/*
+ * This is Sutherland 2009 Algorithm 1.2.
+ */
+static long
+oneroot_of_classpoly(ulong *j_endo, ulong j, norm_eqn_t ne, GEN *mpdb)
+{
+  /* FIXME: Return u_compl as an indication as to whether we know that
+   * *j_endo is correct, rather than just probably correct. */
+
+  long nfactors, L_bound, i;
+  ulong p = ne->p, pi = ne->pi;
+  GEN factors, u_levels, vdepths;
+
+  if (j == 0 || j == 1728 % p)
+    pari_err_BUG("oneroot_of_classpoly");
+  if (ne->w == 1) {
+    *j_endo = j;
+    return 1;
+  }
+
+  factors = gel(ne->factw, 1);
+  u_levels = ne->u_levels;
+  vdepths = ne->vdepths;
+  nfactors = lg(factors) - 1;
+  L_bound = maxdd(log(-ne->D), (double)ne->v);
+
+  /* Iterate over the primes L dividing w */
+  for (i = 1; i <= nfactors; ++i) {
+    pari_sp av = avma;
+    GEN phi;
+    long jlvl, lvl_diff, depth = vdepths[i];
+    long L = factors[i];
+    if (L > L_bound)
+      break;
+
+    phi = polmodular_db_getp(mpdb, L, p);
+
+    /* FIXME: Can I reuse paths created in j_level_in_volcano() later
+     * in {ascend,descend}_volcano()? */
+    jlvl = j_level_in_volcano(phi, j, p, pi, L, depth);
+    lvl_diff = u_levels[i] - jlvl;
+
+    /*
+    while (vLu--)
+      u_compl /= L;
+    */
+
+    if (lvl_diff < 0) {
+      /* j's level is less than v(u) so we must ascend */
+      j = ascend_volcano(phi, j, p, pi, jlvl, L, depth, -lvl_diff);
+    } else if (lvl_diff > 0) {
+      /* Otherwise j's level is greater than v(u) so we descend */
+      j = descend_volcano(phi, j, p, pi, jlvl, L, depth, lvl_diff);
+    }
+    avma = av;
+  }
+  /* At this point the probability that j has the wrong endomorphism
+   * ring is about \sum_{p|u_compl} 1/p (and u_compl must be bigger
+   * than L_bound, so pretty big), so just return it and rely on
+   * detection code in enum_j_with_endo_ring().  Detection is that we
+   * hit a previously found j-invariant earlier than expected.  OR, we
+   * evaluate class polynomials of the suborders at j and if any are
+   * zero then j must be chosen again.  */
+  *j_endo = j;
+  return j != 0 && j != 1728 % p;
+}
+
+
+/*
+ * This is Sutherland 2009 Algorithm 1.3 (p14).
+ */
+static long
+enum_j_with_endo_ring_small_disc_r(
+  ulong *res, long scale, long offset, norm_eqn_t ne,
+  GEN *mpdb, GEN pcp, long k)
+{
+  long L = PCP_GEN_NORMS(pcp)[k];
+  long r = PCP_REL_ORDERS(pcp)[k];
+  long d = z_lval(ne->w, L); /* volcano_depth(L, u, v); */
+  long i, j_idx;
+  ulong p = ne->p, pi = ne->pi;
+
+  pari_sp av = avma;
+  long plen;
+  GEN phi = polmodular_db_getp(mpdb, L, p);
+  GEN jpath_g = cgetg(d + r + 1, t_VECSMALL);
+  ulong *jpath = (ulong *) &jpath_g[1];
+  jpath[0] = res[offset];
+  plen = walk_surface_path(jpath, phi, p, pi, L, d, r - 1);
+  if (plen != r - 1) {
+    avma = av;
+    return 0;
+  }
+
+  scale /= r;
+
+  /* j_idx = scale * i + offset */
+  for (i = 1, j_idx = scale + offset; i < r; ++i, j_idx += scale)
+    res[j_idx] = jpath[i];
+
+  avma = av;
+
+  if (k > 1) {
+    --k;
+    /* j_idx = scale * i + offset */
+    for (i = 0, j_idx = offset; i < r; ++i, j_idx += scale) {
+      long ok = enum_j_with_endo_ring_small_disc_r(
+        res, scale, j_idx, ne, mpdb, pcp, k);
+      if ( ! ok)
+        return 0;
+    }
+  }
+  return 1;
+}
+
+
+INLINE GEN
+enum_j_with_endo_ring_small_disc(
+  ulong j0, norm_eqn_t ne, GEN *mpdb, GEN pcp, long max_elts)
+{
+  pari_sp av = avma;
+  long ngens = PCP_NGENS(pcp);
+  GEN res = cgetg(max_elts + 1, t_VECSMALL);
+  res[1] = j0;
+  if (ngens > 0) {
+    long ok = enum_j_with_endo_ring_small_disc_r(
+      (ulong *)&res[1], max_elts, 0, ne, mpdb, pcp, ngens);
+    if ( ! ok) {
+      avma = av;
+      return NULL;
+    }
+  }
+  return res;
+}
+
+
+/*
+ * Given an Flx linpol, assumed to be linear, return its unique root
+ * in Fl.
+ */
+static long
+unique_root(ulong *rt, GEN linpol, ulong p)
+{
+  ulong t;
+  if (lg(linpol) > 4) {
+    /* linpol is not linear.  Should only happen when |D| is smaller
+     * than 4*L1*L2 where L1 and L2 are the prime norms of a generator
+     * of H(D). */
+    return 0;
+  }
+  t = Fl_neg(linpol[2], p);
+  if (linpol[3] == 1) {
+    *rt = t;
+    return 1;
+  }
+  *rt = Fl_div(t, linpol[3], p);
+  return 1;
+}
+
+
+/* FIXME: This comment is old; it should be updated. */
+/*
+ * Assumes M is an nrows x ncols matrix (given as an array of length
+ * nrows * ncols) whose first row is an L-thread of j-invariants and
+ * the first column is an LL-thread of j-invariants.  This function
+ * fills the (nrows-1) x (ncols-1) submatrix following Sutherland,
+ * 2012, Section 2.3.  That is, the (i,j) entry is the unique root of
+ * the gcd of
+ *
+ *   Phi_L(X, M[i, j - 1])  and  Phi_LL(X, M[i - 1, j]).
+ */
+static long
+fill_parallel_path(ulong box[], ulong p, ulong pi,
+                   GEN phi_row, GEN phi_col,
+                   ulong L_col, ulong L_row,
+                   ulong direction_scale, ulong thread_scale,
+                   ulong idx, ulong end_idx)
+{
+  pari_sp ltop = avma;
+  long ok;
+  ulong i;
+  for (i = idx + thread_scale; i < end_idx; i += thread_scale) {
+    ulong left_j = box[i - direction_scale];
+    ulong up_j   = box[i - thread_scale];
+    GEN modpol_left_j = Flm_Fl_polmodular_evalx(phi_row, L_col, left_j, p, pi);
+    GEN modpol_up_j = Flm_Fl_polmodular_evalx(phi_col, L_row, up_j, p, pi);
+    GEN next_j_pol = Flx_gcd(modpol_left_j, modpol_up_j, p);
+    ok = unique_root(box + i, next_j_pol, p);
+    avma = ltop;
+    if ( ! ok)
+      return 0;
+  }
+  return 1;
+}
+
+
+static long
+fill_box(
+  ulong box[], norm_eqn_t ne, GEN *mpdb, GEN pcp, ulong max_elts)
+{
+  pari_sp av = avma;
+  ulong ngens = PCP_NGENS(pcp);
+  long *gen_norms = &PCP_GEN_NORMS(pcp)[1];
+  long *rel_ords = &PCP_REL_ORDERS(pcp)[1];
+  ulong *m = (ulong *) new_chunk(ngens);
+  ulong i, p = ne->p, pi = ne->pi;
+  long w = ne->w, k, plen;
+  m[0] = 1;
+  for (i = 1; i < ngens; ++i)
+    m[i] = m[i - 1] * rel_ords[i - 1];
+
+  for (k = ngens - 1; k >= 0; --k) {
+    ulong L = gen_norms[k];
+    ulong r = rel_ords[k];
+    /* FIXME: We should already know d from an earlier calculation. */
+    ulong d = u_lval(w, L); /* volcano_depth(L, u, v); */
+    ulong g;
+    GEN phi_L = polmodular_db_getp(mpdb, L, p);
+    pari_sp av2 = avma;
+
+    ulong *jpath = (ulong *) new_chunk(d + r);
+    jpath[0] = box[0];
+    plen = walk_surface_path(jpath, phi_L, p, pi, L, d, r - 1);
+    if (plen != (long)r - 1) {
+      avma = av;
+      return 0;
+    }
+
+    /* Copy L-thread into box. */
+    for (i = 1; i < r; ++i)
+      box[i * m[k]] = jpath[i];
+    avma = av2;
+
+    /* Extend each existing element of the box (except box[0], hence
+     * start with i = 1 instead of i = 0) in parallel with the new
+     * thread. */
+    for (g = ngens - 1; g > (ulong)k; --g) {
+      ulong LL = gen_norms[g];
+      GEN phi_LL = polmodular_db_getp(mpdb, LL, p);
+      for (i = m[g]; i < max_elts; i += m[g]) {
+        if ((g == ngens - 1) || (i % m[g + 1] != 0)) {
+          if ( ! fill_parallel_path(box, p, pi, phi_LL, phi_L,
+                                    LL, L, m[g], m[k], i, m[k] * r + i)) {
+            avma = av;
+            return 0;
+          }
+        }
+      }
+      avma = av2;
+    }
+  }
+  avma = av;
+  return 1;
+}
+
+
+GEN
+enum_j_with_endo_ring(
+  ulong j0, norm_eqn_t ne, GEN *mpdb, GEN pcp, long max_elts)
+{
+  /* res is a matrix (or rather, a *volume*) for which the (j0, j2,
+   * .., jk)th entry is located at j0 * R1k + j1 * R2k + ... + jk
+   * where, if (r0, r2, .., rk) are the relative orders of the
+   * polycyclic presentation, Rik denotes the product of ri, .., rk. */
+  pari_sp av = avma;
+  GEN gen_norms = PCP_GEN_NORMS(pcp);
+  long ngens = PCP_NGENS(pcp);
+  GEN res = cgetg(max_elts + 1, t_VECSMALL);
+  res[1] = j0;
+
+  if (ngens == 0)
+    return res;
+
+  if (ngens > 1) {
+    /* The norms of the last two generators. */
+    long L1 = gen_norms[ngens];
+    long L2 = gen_norms[ngens - 1];
+    /* If 4 L1^2 L2^2 > |D|, */
+    if (4 * L1 * L1 * L2 * L2 > -ne->D)
+      return enum_j_with_endo_ring_small_disc(j0, ne, mpdb, pcp, max_elts);
+  }
+
+  if (fill_box((ulong *)&res[1], ne, mpdb, pcp, max_elts))
+    return res;
+  avma = av;
+  return NULL;
+}
+
+
+INLINE ulong
+select_twisting_param(ulong p)
+{
+  ulong T;
+  do
+    T = random_Fl(p);
+  while (krouu(T, p) != -1);
+  return T;
+}
+
+
+INLINE void
+setup_norm_eqn(norm_eqn_t ne, long D, long u, GEN norm_eqn)
+{
+  GEN factw;
+  long i, nfactors;
+
+  ne->D = D;
+  ne->u = u;
+  ne->t = norm_eqn[2];
+  ne->v = norm_eqn[3];
+  ne->w = u * ne->v;
+  ne->p = (ulong) norm_eqn[1];
+  ne->pi = get_Fl_red(ne->p);
+  ne->T = select_twisting_param(ne->p);
+  ne->factw = factw = factoru(u * ne->v);
+  nfactors = lg(gel(factw, 1)) - 1;
+  ne->u_levels = cgetg(nfactors + 1, t_VECSMALL);
+  for (i = 1; i <= nfactors; ++i)
+    ne->u_levels[i] = z_lval(u, gel(factw, 1)[i]);
+  ne->vdepths = gel(factw, 2);
+}
+
+
+static int
+polclass0(
+  ulong *total_curves_tested,
+  GEN norm_eqn, GEN *hilb, GEN *P, long D, long u, GEN pcp, GEN *mpdb,
+  long xvar)
+{
+  pari_sp av = avma;
+  ulong j_t = 0, j_endo = 0;
+  long found_j_endo, trace_tries = 0, endo_tries = 0, rho_inv = norm_eqn[4];
+  int stab;
+  GEN res, pol;
+  norm_eqn_t ne;
+
+  setup_norm_eqn(ne, D, u, norm_eqn);
+  dbg_printf3(2, "p = %ld, t = %ld, v = %ld", ne->p, ne->t, ne->v);
+
+  do {
+    do {
+      /* FIXME: Set batch size according to expected number of tries and
+       * experimental cost/benefit analysis. */
+      trace_tries = find_j_inv_with_given_trace(&j_t, ne, rho_inv, 0);
+      if (j_t == 0) {
+        pari_err_BUG("polclass0: "
+                     "Couldn't find j-invariant with given trace.");
+      }
+      dbg_printf4(2, "  j-invariant %ld has trace +/-%ld (%ld tries, 1/rho = %ld)",
+                  j_t, ne->t, trace_tries, rho_inv);
+      *total_curves_tested += trace_tries;
+
+      found_j_endo = oneroot_of_classpoly(&j_endo, j_t, ne, mpdb);
+      if ( ! found_j_endo) {
+        dbg_printf(1, "Couldn't find j-invariant isogenous to %lu with "
+                   "given endo ring; trying again...", j_t);
+      }
+      ++endo_tries;
+    } while ( ! found_j_endo);
+
+    res = enum_j_with_endo_ring(j_endo, ne, mpdb, pcp, pcp_order(pcp));
+  } while ( ! res);
+
+  dbg_printf2(2, "  j-invariant %ld has correct endomorphism ring "
+              "(%ld tries)", j_endo, endo_tries);
+  dbg_printf(3, "  all such j-invariants: %Ps", res);
+
+  pol = gerepileupto(av, Flv_roots_to_pol(res, ne->p, xvar));
+  dbg_printf2(3, "  Hilbert polynomial mod %ld: %Ps", ne->p, pol);
+
+  stab = ZX_incremental_CRT(hilb, pol, P, ne->p);
+  return stab;
+}
+
+GEN
+polclass(GEN DD, long xvar)
+{
+  pari_sp ltop = avma, btop;
+  long D, dummy;
+  GEN prime_lst;
+  ulong total_curves_tested = 0;
+  long nprimes, i;
+  GEN hilb = 0;  /* The Hilbert class polynomial */
+  GEN P; /* P is the product of all the p */
+  ulong u, classno;
+  GEN pcp, mpdb;
+  static const long k = 2;
+  static const double delta = 0.5;
+
+  if (xvar < 0)
+    xvar = 0;
+  check_quaddisc_imag(DD, &dummy, "polclass");
+
+  D = itos(DD);
+  if (D == -3) /* x */
+    return pol_x(xvar);
+  if (D == -4) /* x - 1728 */
+    return gerepileupto(ltop, deg1pol(gen_1, stoi(-1728), xvar));
+
+  (void) corediscs(D, &u);
+  classno = classno_wrapper(D);
+
+  dbg_printf2(1, "D = %ld, conductor = %ld", D, u);
+
+  pcp = minimal_polycyclic_presentation(classno, D, u);
+
+  prime_lst = select_classpoly_primes(D, k, delta, pcp);
+  mpdb = polmodular_db_init(0);
+
+  hilb = ZX_init_CRT(pol_0(xvar), 1L, xvar);
+  P = gen_1;
+
+  nprimes = lg(prime_lst) - 1;
+  btop = avma;
+  for (i = 1; i <= nprimes; ++i) {
+    (void) polclass0(&total_curves_tested, gel(prime_lst, i),
+                      &hilb, &P, D, u, pcp, &mpdb, xvar);
+    if (gc_needed(btop, 2))
+      gerepileall(btop, 2, &hilb, &P);
+#if 0
+    if (quit_on_first_stabilisation && stab)
+      break;
+#endif
+  }
+
+  dbg_printf(1, "Total number of curves tested: %lu",
+             total_curves_tested);
+
+  polmodular_db_clear(mpdb);
+  /* According to Sutherland, 2009, Section 6.3, the coefficients of
+   * the class polynomial lie in the interval (-P/2, P/2) when the
+   * modulus P with respect to which we are computing the class
+   * polynomial is greater than the product of all the small primes.
+   * This is called the "centred representative" and is precisely the
+   * value maintained by ZX_incremental_CRT().  We can therefore
+   * return hilb directly. */
+  return gerepilecopy(ltop, hilb);
+}
diff --git a/src/basemath/polmodular.c b/src/basemath/polmodular.c
new file mode 100644
index 0000000..0176b31
--- /dev/null
+++ b/src/basemath/polmodular.c
@@ -0,0 +1,2222 @@
+/* Copyright (C) 2014  The PARI group.
+
+This file is part of the PARI/GP package.
+
+PARI/GP 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. It is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY WHATSOEVER.
+
+Check the License for details. You should have received a copy of it, along
+with the package; see the file 'COPYING'. If not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+#include "pari.h"
+#include "paripriv.h"
+
+#define dbg_printf0(lvl, fmt) \
+  do { if ((lvl) <= DEBUGLEVEL) err_printf(fmt "\n"); } while (0)
+#define dbg_printf1(lvl, fmt, a1) \
+  do { if ((lvl) <= DEBUGLEVEL) err_printf(fmt "\n", (a1)); } while (0)
+#define dbg_printf2(lvl, fmt, a1, a2) \
+  do { if ((lvl) <= DEBUGLEVEL) err_printf(fmt "\n", (a1), (a2)); } while (0)
+#define dbg_printf3(lvl, fmt, a1, a2, a3) \
+  do { if ((lvl) <= DEBUGLEVEL) err_printf(fmt "\n", (a1), (a2), (a3)); } while (0)
+#define dbg_printf4(lvl, fmt, a1, a2, a3, a4) \
+  do { if ((lvl) <= DEBUGLEVEL) err_printf(fmt  "\n", (a1), (a2), (a3), (a4)); } while (0)
+#define dbg_printf dbg_printf1
+#define dbg_puts(lvl, str) dbg_printf0(lvl, str)
+
+/**
+ * SECTION: Fixed-length dot-product-like functions on Fl's with
+ * precomuted inverse.
+ */
+
+/* Computes x0y1 + y0x1 (mod p); assumes p < 2^63. */
+INLINE ulong
+Fl_addmul2(
+  ulong x0, ulong x1, ulong y0, ulong y1,
+  ulong p, ulong pi)
+{
+  ulong l0, l1, h0, h1;
+  LOCAL_OVERFLOW;
+  LOCAL_HIREMAINDER;
+  l0 = mulll(x0, y1); h0 = hiremainder;
+  l1 = mulll(x1, y0); h1 = hiremainder;
+  l0 = addll(l0, l1); h0 = addllx(h0, h1);
+  return remll_pre(h0, l0, p, pi);
+}
+
+
+/* Computes x0y2 + x1y1 + x2y0 (mod p); assumes p < 2^62. */
+INLINE ulong
+Fl_addmul3(
+  ulong x0, ulong x1, ulong x2, ulong y0, ulong y1, ulong y2,
+  ulong p, ulong pi)
+{
+  ulong l0, l1, h0, h1;
+  LOCAL_OVERFLOW;
+  LOCAL_HIREMAINDER;
+  l0 = mulll(x0, y2); h0 = hiremainder;
+  l1 = mulll(x1, y1); h1 = hiremainder;
+  l1 = addll(l0, l1); h1 = addllx(h0, h1);
+  l0 = mulll(x2, y0); h0 = hiremainder;
+  l1 = addll(l0, l1); h1 = addllx(h0, h1);
+  return remll_pre(h1, l1, p, pi);
+}
+
+
+/* Computes x0y3 + x1y2 + x2y1 + x3y0 (mod p); assumes p < 2^62. */
+INLINE ulong
+Fl_addmul4(
+  ulong x0, ulong x1, ulong x2, ulong x3,
+  ulong y0, ulong y1, ulong y2, ulong y3,
+  ulong p, ulong pi)
+{
+  ulong l0, l1, h0, h1;
+  LOCAL_OVERFLOW;
+  LOCAL_HIREMAINDER;
+  l0 = mulll(x0, y3); h0 = hiremainder;
+  l1 = mulll(x1, y2); h1 = hiremainder;
+  l1 = addll(l0, l1); h1 = addllx(h0, h1);
+  l0 = mulll(x2, y1); h0 = hiremainder;
+  l1 = addll(l0, l1); h1 = addllx(h0, h1);
+  l0 = mulll(x3, y0); h0 = hiremainder;
+  l1 = addll(l0, l1); h1 = addllx(h0, h1);
+  return remll_pre(h1, l1, p, pi);
+}
+
+/* Computes x0y4 + x1y3 + x2y2 + x3y1 + x4y0 (mod p); assumes p < 2^62. */
+INLINE ulong
+Fl_addmul5(
+  ulong x0, ulong x1, ulong x2, ulong x3, ulong x4,
+  ulong y0, ulong y1, ulong y2, ulong y3, ulong y4,
+  ulong p, ulong pi)
+{
+  ulong l0, l1, h0, h1;
+  LOCAL_OVERFLOW;
+  LOCAL_HIREMAINDER;
+  l0 = mulll(x0, y4); h0 = hiremainder;
+  l1 = mulll(x1, y3); h1 = hiremainder;
+  l1 = addll(l0, l1); h1 = addllx(h0, h1);
+  l0 = mulll(x2, y2); h0 = hiremainder;
+  l1 = addll(l0, l1); h1 = addllx(h0, h1);
+  l0 = mulll(x3, y1); h0 = hiremainder;
+  l1 = addll(l0, l1); h1 = addllx(h0, h1);
+  l0 = mulll(x4, y0); h0 = hiremainder;
+  l1 = addll(l0, l1); h1 = addllx(h0, h1);
+  return remll_pre(h1, l1, p, pi);
+}
+
+/*
+ * A polmodular database consists of a t_VEC whose L-th entry is 0 or a
+ * GEN pointing to Phi_L.  levels is a t_VECSMALL of levels to use to
+ * populate the database.
+ */
+GEN
+polmodular_db_init(GEN levels)
+{
+  pari_sp av = avma;
+  long levellg, maxlevel, i;
+  GEN res;
+
+  levellg = levels ? lg(levels) : 0;
+  maxlevel = levellg > 1 ? vecsmall_max(levels) : 0;
+  res = cgetg_block(maxlevel + 1, t_VEC);
+
+  for (i = 1; i <= maxlevel; ++i)
+    gel(res, i) = 0;
+
+  for (i = 1; i < levellg; ++i) {
+    long L = levels[i];
+    gel(res, L) = gclone(polmodular_ZM(L));
+  }
+
+  avma = av;
+  return res;
+}
+
+
+void
+polmodular_db_clear(GEN db)
+{
+  long i, dblg = lg(db);
+  for (i = 1; i < dblg; ++i) {
+    if (gel(db, i))
+      gunclone(gel(db, i));
+  }
+  killblock(db);
+}
+
+
+GEN
+polmodular_db_get(GEN *db, long L)
+{
+  pari_sp av = avma;
+  long max_L = lg(*db) - 1;
+  if (L > max_L) {
+    GEN newdb = cgetg_block(L + 1, t_VEC);
+    long i;
+    for (i = 1; i <= max_L; ++i)
+      gel(newdb, i) = gel(*db, i);
+    for (i = max_L + 1; i <= L; ++i)
+      gel(newdb, i) = 0;
+    killblock(*db);
+    *db = newdb;
+  }
+  /* NB: In principle, this call to polmodular_ZM could make use of db,
+   * but in practice it would gain almost nothing, and only in very
+   * rare cases.  */
+  if (gel(*db, L) == 0)
+    gel(*db, L) = gclone(polmodular_ZM(L));
+  avma = av;
+  return gel(*db, L);
+}
+
+
+/* NB: Unlike polmodular_db_get(), this function returns something on the
+ * stack that the caller must clean up. */
+GEN
+polmodular_db_getp(GEN *db, long L, ulong p)
+{
+  return ZM_to_Flm(polmodular_db_get(db, L), p);
+}
+
+
+/**
+ * SECTION: Table of discriminants to use.
+ */
+typedef struct {
+  long L;        /* modpoly level */
+  long D0;       /* fundamental discriminant */
+  long D1;       /* chosen discriminant */
+  long L0;       /* first generator norm */
+  long L1;       /* second generator norm */
+  long n1;       /* order of L0 in cl(D1) */
+  long n2;       /* order of L0 in cl(D2) where D2 = L^2 D1 */
+  long nprimes;  /* number of primes needed for D1 */
+  long dl1;      /* m such that L0^m = L in cl(D1) */
+  long dl2_0;    /* These two are (m, n) such that L0^m L1^n = form of norm L^2 in D2 */
+  long dl2_1;    /* This n is always 1 or 0. */
+} modpoly_disc_info;
+
+static const modpoly_disc_info *
+discriminant_with_classno_at_least(long *D, ulong *u, ulong *v, ulong L);
+
+/* NB: The actual table is included at the end of the file. */
+
+
+/**
+ * SECTION: Hard-coded evaluation functions for modular polynomials of
+ * small level.
+ */
+
+/*
+ * Based on phi2_eval_ff() in Sutherland's classpoly programme.
+ * Calculates Phi_2(X, j) (mod p) with 6M+7A (4 reductions, not
+ * counting those for Phi_2).
+ */
+INLINE GEN
+Flm_Fl_phi2_evalx(GEN phi2, ulong j, ulong p, ulong pi)
+{
+  GEN res = cgetg(6, t_VECSMALL);
+  ulong j2, t1;
+
+  res[1] = 0; /* variable name */
+
+  j2 = Fl_sqr_pre(j, p, pi);
+  t1 = Fl_add(j, coeff(phi2, 3, 1), p);
+  t1 = Fl_addmul2(j, j2, t1, coeff(phi2, 2, 1), p, pi);
+  res[2] = Fl_add(t1, coeff(phi2, 1, 1), p);
+
+  t1 = Fl_addmul2(j, j2, coeff(phi2, 3, 2), coeff(phi2, 2, 2), p, pi);
+  res[3] = Fl_add(t1, coeff(phi2, 2, 1), p);
+
+  t1 = Fl_mul_pre(j, coeff(phi2, 3, 2), p, pi);
+  t1 = Fl_add(t1, coeff(phi2, 3, 1), p);
+  res[4] = Fl_sub(t1, j2, p);
+
+  res[5] = 1;
+  return res;
+}
+
+
+/*
+ * Based on phi3_eval_ff() in Sutherland's classpoly programme.
+ * Calculates Phi_3(X, j) (mod p) with 13M+13A (6 reductions, not
+ * counting those for Phi_3).
+ */
+INLINE GEN
+Flm_Fl_phi3_evalx(GEN phi3, ulong j, ulong p, ulong pi)
+{
+  GEN res = cgetg(7, t_VECSMALL);
+  ulong j2, j3, t1;
+
+  res[1] = 0; /* variable name */
+
+  j2 = Fl_sqr_pre(j, p, pi);
+  j3 = Fl_mul_pre(j, j2, p, pi);
+
+  t1 = Fl_add(j, coeff(phi3, 4, 1), p);
+  res[2] = Fl_addmul3(j, j2, j3, t1,
+                      coeff(phi3, 3, 1), coeff(phi3, 2, 1), p, pi);
+
+  t1 = Fl_addmul3(j, j2, j3, coeff(phi3, 4, 2),
+                  coeff(phi3, 3, 2), coeff(phi3, 2, 2), p, pi);
+  res[3] = Fl_add(t1, coeff(phi3, 2, 1), p);
+
+  t1 = Fl_addmul3(j, j2, j3, coeff(phi3, 4, 3),
+                  coeff(phi3, 3, 3), coeff(phi3, 3, 2), p, pi);
+  res[4] = Fl_add(t1, coeff(phi3, 3, 1), p);
+
+  t1 = Fl_addmul2(j, j2, coeff(phi3, 4, 3), coeff(phi3, 4, 2), p, pi);
+  t1 = Fl_add(t1, coeff(phi3, 4, 1), p);
+  res[5] = Fl_sub(t1, j3, p);
+
+  res[6] = 1;
+
+  return res;
+}
+
+
+/*
+ * Based on phi5_eval_ff() in Sutherland's classpoly programme.
+ * Calculates Phi_5(X, j) (mod p) with 33M+31A (10 reductions, not
+ * counting those for Phi_5).
+ */
+INLINE GEN
+Flm_Fl_phi5_evalx(GEN phi5, ulong j, ulong p, ulong pi)
+{
+  GEN res = cgetg(9, t_VECSMALL);
+  ulong j2, j3, j4, j5, t1;
+
+  res[1] = 0; /* variable name */
+
+  j2 = Fl_sqr_pre(j, p, pi);
+  j3 = Fl_mul_pre(j, j2, p, pi);
+  j4 = Fl_sqr_pre(j2, p, pi);
+  j5 = Fl_mul_pre(j, j4, p, pi);
+
+  t1 = Fl_add(j, coeff(phi5, 6, 1), p);
+  t1 = Fl_addmul5(j, j2, j3, j4, j5, t1,
+                  coeff(phi5, 5, 1), coeff(phi5, 4, 1),
+                  coeff(phi5, 3, 1), coeff(phi5, 2, 1),
+                  p, pi);
+  res[2] = Fl_add(t1, coeff(phi5, 1, 1), p);
+
+  t1 = Fl_addmul5(j, j2, j3, j4, j5,
+                  coeff(phi5, 6, 2), coeff(phi5, 5, 2),
+                  coeff(phi5, 4, 2), coeff(phi5, 3, 2), coeff(phi5, 2, 2),
+                  p, pi);
+  res[3] = Fl_add(t1, coeff(phi5, 2, 1), p);
+
+  t1 = Fl_addmul5(j, j2, j3, j4, j5,
+                  coeff(phi5, 6, 3), coeff(phi5, 5, 3),
+                  coeff(phi5, 4, 3), coeff(phi5, 3, 3), coeff(phi5, 3, 2),
+                  p, pi);
+  res[4] = Fl_add(t1, coeff(phi5, 3, 1), p);
+
+  t1 = Fl_addmul5(j, j2, j3, j4, j5,
+                  coeff(phi5, 6, 4), coeff(phi5, 5, 4),
+                  coeff(phi5, 4, 4), coeff(phi5, 4, 3), coeff(phi5, 4, 2),
+                  p, pi);
+  res[5] = Fl_add(t1, coeff(phi5, 4, 1), p);
+
+  t1 = Fl_addmul5(j, j2, j3, j4, j5,
+                  coeff(phi5, 6, 5), coeff(phi5, 5, 5),
+                  coeff(phi5, 5, 4), coeff(phi5, 5, 3), coeff(phi5, 5, 2),
+                  p, pi);
+  res[6] = Fl_add(t1, coeff(phi5, 5, 1), p);
+
+  t1 = Fl_addmul4(j, j2, j3, j4,
+                  coeff(phi5, 6, 5), coeff(phi5, 6, 4),
+                  coeff(phi5, 6, 3), coeff(phi5, 6, 2),
+                  p, pi);
+  t1 = Fl_add(t1, coeff(phi5, 6, 1), p);
+  res[7] = Fl_sub(t1, j5, p);
+
+  res[8] = 1;
+
+  return res;
+}
+
+GEN
+Flm_Fl_polmodular_evalx(GEN phi, long L, ulong j, ulong p, ulong pi)
+{
+  pari_sp av = avma;
+  GEN j_powers, modpol;
+  if (L == 2)
+    return Flm_Fl_phi2_evalx(phi, j, p, pi);
+  if (L == 3)
+    return Flm_Fl_phi3_evalx(phi, j, p, pi);
+  if (L == 5)
+    return Flm_Fl_phi5_evalx(phi, j, p, pi);
+  j_powers = Fl_powers_pre(j, L + 1, p, pi);
+  modpol = Flv_to_Flx(Flm_Flc_mul_pre(phi, j_powers, p, pi), 0);
+  return gerepileupto(av, modpol);
+}
+
+
+INLINE GEN
+Flm_Fl_phi2_qevalx(GEN phi, ulong a, ulong b, ulong p, ulong pi)
+{
+    ulong J0, J1, J2, t1;
+    GEN f = cgetg(6, t_VECSMALL);
+
+    f[1] = 0;
+
+    t1 = Fl_sqr_pre(b, p, pi);
+    J1 = Fl_mul_pre(t1, a, p, pi);
+    J0 = Fl_mul_pre(t1, b, p, pi);
+    t1 = Fl_sqr_pre(a, p, pi);
+    J2 = Fl_mul_pre(t1, b, p, pi);
+
+    f[2] = Fl_addmul4(J0, J1, J2, t1, a,
+                      coeff(phi, 1, 3), coeff(phi, 1, 2), coeff(phi, 1, 1),
+                      p, pi);
+    f[3] = Fl_addmul3(J0, J1, J2,
+                      coeff(phi, 2, 3), coeff(phi, 2, 2), coeff(phi, 2, 1),
+                      p, pi);
+    t1 = Fl_addmul2(J0, J1, coeff(phi, 3, 2), coeff(phi, 3, 1), p, pi);
+    f[4] = Fl_sub(t1, J2, p);
+    f[5] = J0;
+
+    return f;
+}
+
+
+/* Get pointer to coeffs of f as a ulong*. */
+#define Flx_coeffs(f) ((ulong *)((f) + 2))
+/* Get coefficient of x^d in f, assuming f is nonzero. */
+#define Flx_coeff(f, d) ((f)[(d) + 2])
+
+
+/* Based on Sutherland's ffpolysmall.h:ff_poly_mgcd_linear_n_3().
+ *
+ * f and g are monic polynomials, f of degree greater than 3, g of
+ * degree 3.
+ */
+INLINE GEN
+Flx_mgcd_linear_n_3(GEN f, GEN g, ulong p, ulong pi)
+{
+  long i, d = degpol(f);
+  ulong s0, s1, s2, t0, t1, t2, t3, t, u;
+  GEN h = cgetg(4, t_VECSMALL);
+
+  h[1] = 0;
+
+  s0 = Flx_coeff(g, 0);
+  s1 = Flx_coeff(g, 1);
+  s2 = Flx_coeff(g, 2);
+  /* NB: Sutherland's version also handles deg(f) = 3, but we don't
+   * need it, since f will always be the evaluation of a modular
+   * polynomial of level > 2, hence of degree > 3. */
+  if (d == 4) {
+    t3 = Fl_sub(Flx_coeff(f, 3), s2, p);
+    t2 = Fl_sub(s1, Flx_coeff(f, 2), p);
+    t = Fl_mul_pre(t3, s2, p, pi);
+    t2 = Fl_add(t2, t, p);
+    t1 = Fl_sub(Flx_coeff(f, 1), s0, p);
+    t = Fl_mul_pre(t3, s1, p, pi);
+    t1 = Fl_sub(t1, t, p);
+    t = Fl_mul_pre(t3, s0, p, pi);
+    t0 = Fl_sub(Flx_coeff(f, 0), t, p);
+
+    t = Fl_mul_pre(t2, s2, p, pi);
+    s2 = Fl_add(t, t1, p);
+    t = Fl_mul_pre(t2, s1, p, pi);
+    s1 = Fl_add(t, t0, p);
+    Flx_coeff(h, 1) = Fl_addmul2(s1, s2, t1, t2, p, pi);
+    t = Fl_mul_pre(t2, s0, p, pi);
+    Flx_coeff(h, 0) = Fl_addmul2(t, s2, t0, t2, p, pi);
+    return h;
+  }
+
+  t2 = Fl_sub(Flx_coeff(f, d - 1), s2, p);
+  t1 = Fl_sub(Flx_coeff(f, d - 2), s1, p);
+  t = Fl_mul_pre(t2, s2, p, pi);
+  t1 = Fl_sub(t1, t, p);
+  t0 = Fl_sub(Flx_coeff(f, d - 3), s0, p);
+  t = Fl_addmul2(t1, t2, s1, s2, p, pi);
+  t0 = Fl_sub(t0, t, p);
+  for (i = d - 4; i > 1; --i) {
+    t = Fl_addmul3(t0, t1, t2, s0, s1, s2, p, pi);
+    t2 = t1;
+    t1 = t0;
+    t0 = Fl_sub(Flx_coeff(f, i), t, p);
+  }
+  t = Fl_addmul2(t1, t2, s0, s1, p, pi);
+  t2 = Fl_neg(t0, p);
+  u = Fl_mul_pre(t1, s0, p, pi);
+  t1 = Fl_sub(Flx_coeff(f, 1), t, p);
+  t0 = Fl_sub(Flx_coeff(f, 0), u, p);
+
+  t = Fl_mul_pre(t2, s2, p, pi);
+  s2 = Fl_add(t, t1, p);
+  t = Fl_mul_pre(t2, s1, p, pi);
+  s1 = Fl_add(t, t0, p);
+  Flx_coeff(h, 1) = Fl_addmul2(s1, s2, t1, t2, p, pi);
+  t = Fl_mul_pre(t2, s0, p, pi);
+  Flx_coeff(h, 0) = Fl_addmul2(t, s2, t0, t2, p, pi);
+  return h;
+}
+
+
+/* Based on Sutherland's ff_poly code,
+ * ffpolysmall.h:ff_poly_gcd_linear_n_2() */
+/* f deg d_f > 2, g deg 2, neither need be monic, f and g are not
+ * modified. */
+INLINE GEN
+Flx_gcd_linear_n_2(GEN f_, GEN g_, ulong p, ulong pi)
+{
+  long i;
+  ulong s0, s1, s2, t0, t1, t, d = degpol(f_);
+  ulong *f = Flx_coeffs(f_);
+  ulong *g = Flx_coeffs(g_);
+  GEN h = cgetg(4, t_VECSMALL);
+  h[1] = 0;
+
+  s0 = Fl_neg(g[0], p);
+  s1 = Fl_neg(g[1], p);
+  s2 = Fl_sqr_pre(g[2], p, pi);
+  s0 = Fl_mul_pre(s0, g[2], p, pi);
+  t1 = Fl_addmul2(s1, g[2], f[d - 1], f[d], p, pi);
+  t0 = Fl_addmul2(s1, s2, f[d - 2], t1, p, pi);
+  t0 = Fl_add(t0, s0, p);
+  for (i = d - 3; i > 0; --i) {
+    s2 = Fl_mul_pre(s2, g[2], p, pi);
+    t = Fl_addmul3(s0, s1, s2, f[i], t0, t1, p, pi);
+    t1 = t0;
+    t0 = t;
+  }
+  h[3] = t0;
+  s0 = Fl_neg(g[0], p);
+  h[2] = Fl_addmul2(s0, s2, f[0], t1, p, pi);
+
+  return h;
+}
+
+/* Computes s^2*g/(x-r/s) assuming g(r/s)=0 for a cubic g (not assumed
+ * monic) Based on Sutherland's classpoly code,
+ * phi_gcd.c:ff_poly_remove_qroot_3(). */
+INLINE GEN
+Flx_remove_cubic_qroot(GEN g, ulong r, ulong s, ulong p, ulong pi)
+{
+  ulong t1, t2;
+  GEN f = cgetg(5, t_VECSMALL);
+
+  f[1] = 0;
+
+  t2 = Fl_sqr_pre(s, p, pi);
+  t1 = Fl_addmul2(Flx_coeff(g, 2), Flx_coeff(g, 3), r, s, p, pi);
+  Flx_coeff(f, 0) = Fl_addmul2(t1, t2, Flx_coeff(g, 1), r, p, pi);
+  Flx_coeff(f, 1) = Fl_mul_pre(s, t1, p, pi);
+  Flx_coeff(f, 2) = Fl_mul_pre(t2, Flx_coeff(g, 3), p, pi);
+
+  return f;
+}
+
+
+/* Based on Sutherland's classpoly code,
+ * phi_gcd.c:phi_surface_qgcd_cycle_2_p2().
+ *
+ * box must point to space for 2n ulongs, the first n of which must
+ * point to a (surface) 2-cycle of length n, and box[n] and box[n+1]
+ * should be L-isogenous to box[0] and box[1] (with box[1] correctly
+ * oriented using gcds. */
+static void
+fill_parallel_path(
+  ulong box[],
+  long n, GEN phi_2, GEN phi_L, long L, ulong p, ulong pi)
+{
+  enum { BATCH_INVERTS = 128, E = 2 };
+  long i, j;
+  ulong d[BATCH_INVERTS + 2];
+  ulong *twocycl = box, *ppath = box + n;
+
+  i = 0;
+  j = E;
+
+  /* FIXME: Handle avs' strange case "r == r2", I think for
+   * enumerating surface elements */
+  i = j;
+
+  d[0] = 1;
+  while (j < n) {
+    long m, j0, k;
+    d[1] = 1;
+    m = minss(BATCH_INVERTS, n - j);
+    j0 = j - 2;
+    for (k = 2; k <= m + 1; ++i, ++j, ++k) {
+      pari_sp av = avma;
+      GEN f, g, h;
+      f = Flm_Fl_polmodular_evalx(phi_L, L, twocycl[i], p, pi);
+      g = Flm_Fl_phi2_qevalx(phi_2, ppath[j - 1], d[k - 1], p, pi);
+      g = Flx_remove_cubic_qroot(g, ppath[j - 2], d[k - 2], p, pi);
+      h = Flx_gcd_linear_n_2(f, g, p, pi);
+      ppath[j] = Fl_neg(Flx_coeff(h, 0), p);
+      d[k] = Flx_coeff(h, 1);
+      avma = av;
+    }
+    /* Make &d[1] into a vecsmall of m elements. Calculates the
+     * inverse of d[2] up to d[m + 2]. */
+    d[1] = evaltyp(t_VECSMALL) | _evallg(m + 1);
+    Flv_inv_pre_inplace((GEN)&d[1], p, pi);
+    for (k = 2; k <= m + 1; ++k)
+      ppath[j0 + k] = Fl_mul_pre(ppath[j0 + k], d[k], p, pi);
+  }
+}
+
+
+/* Put the common neighbour of box[1] and box[r] into box[r+1] */
+INLINE void
+fill_corner(
+  ulong box[], long r, long L, GEN phi_2, GEN phi_L, ulong p, ulong pi)
+{
+  ulong left = box[1], up = box[r];
+  GEN f, g, h;
+  f = Flm_Fl_polmodular_evalx(phi_L, L, left, p, pi);
+  g = Flm_Fl_phi2_evalx(phi_2, up, p, pi);
+  h = Flx_mgcd_linear_n_3(f, g, p, pi);
+  if (degpol(h) != 1)
+    pari_err_BUG("fill_corner: Wrong number of roots");
+  box[r + 1] = Fl_neg(Flx_coeff(h, 0), p);
+  if (Flx_coeff(h, 1) != 1)
+    box[r + 1] = Fl_div(box[r + 1], Flx_coeff(h, 1), p);
+}
+
+
+/* d is the depth of the 2-volcano, r is the order of [2] in cl(O). */
+INLINE void
+fill_box(
+  ulong box[], long L, long d2, long dL, long r,
+  GEN *mpdb, ulong p, ulong pi)
+{
+  pari_sp av = avma;
+  GEN phi_2 = polmodular_db_getp(mpdb, 2, p);
+  GEN phi_L = polmodular_db_getp(mpdb, L, p);
+  ulong *sidestep = (ulong *)new_chunk(2 + dL);
+
+  walk_surface_path(box, phi_2, p, pi, 2, d2, r - 1);
+  sidestep[0] = box[0];
+  walk_surface_path(sidestep, phi_L, p, pi, L, dL, 1);
+  box[r] = sidestep[1];
+  fill_corner(box, r, L, phi_2, phi_L, p, pi);
+  fill_parallel_path(box, r, phi_2, phi_L, L, p, pi);
+
+  avma = av;
+}
+
+
+static GEN
+enum_j_fast(ulong j0, long D, long L1, long d2, long dL, long r,
+            GEN *mpdb, ulong p, ulong pi)
+{
+  GEN res = cgetg(2 * r + 1, t_VECSMALL);
+  if (4 * 4 * L1 * L1 > -D || d2 > r || dL + 2 > r)
+    pari_err_BUG("enum_j_fast: invalid parameters");
+  res[1] = j0;
+  fill_box((ulong *)&res[1], L1, d2, dL, r, mpdb, p, pi);
+  return res;
+}
+
+
+/**
+ * SECTION: Velu's formula for the codmain curve in the case of small
+ * prime base field.
+ */
+
+INLINE ulong
+Fl_mul4(ulong x, ulong p)
+{
+  return Fl_double(Fl_double(x, p), p);
+}
+
+INLINE ulong
+Fl_mul5(ulong x, ulong p)
+{
+  return Fl_add(x, Fl_mul4(x, p), p);
+}
+
+INLINE ulong
+Fl_mul8(ulong x, ulong p)
+{
+  return Fl_double(Fl_mul4(x, p), p);
+}
+
+INLINE ulong
+Fl_mul6(ulong x, ulong p)
+{
+  return Fl_sub(Fl_mul8(x, p), Fl_double(x, p), p);
+}
+
+INLINE ulong
+Fl_mul7(ulong x, ulong p)
+{
+  return Fl_sub(Fl_mul8(x, p), x, p);
+}
+
+INLINE ulong
+uQ_calc(ulong a4, ulong a6, ulong xQ, ulong p, ulong pi)
+{
+  /* uQ = 4 xQ^3 + b2 xQ^2 + 2 b4 xQ + b6
+   *    = 4 xQ^3 + 4 a4 xQ + 4 a6
+   *    = 4 ((xQ^2 + a4) xQ + a6)
+   * (since b2 = 0, b4 = 2 a4 and b6 = 4 a6) */
+  ulong t1 = Fl_add(Fl_sqr_pre(xQ, p, pi), a4, p);
+  return Fl_mul4(Fl_add(Fl_mul_pre(t1, xQ, p, pi), a6, p), p);
+}
+
+
+/*
+ * Given an elliptic curve E = [a4, a6] over F_p and a non-zero point
+ * pt on E, return the quotient E' = E/<P> = [a4_img, a6_img].
+ *
+ * FIXME: There is an even simpler version of this algorithm in
+ * Sutherland 2012, Section 6.4.
+ */
+static void
+Fle_quotient_from_kernel_generator(
+  ulong *a4_img, ulong *a6_img, ulong a4, ulong a6, GEN pt, ulong p, ulong pi)
+{
+  pari_sp av = avma;
+  ulong t = 0, w = 0;
+  GEN Q;
+  ulong xQ, tQ, uQ;
+
+  Q = gcopy(pt);
+  /* Note that, as L is odd, say L = 2n + 1, we necessarily have
+   * [(L - 1)/2]P = [n]P = [n - L]P = -[n + 1]P = -[(L + 1)/2]P.  This is
+   * what the condition Q[1] != xQ tests, so the loop will execute n times. */
+  do {
+    xQ = Q[1];
+    /* tQ = 6 xQ^2 + b2 xQ + b4
+     *    = 6 xQ^2 + 2 a4 (since b2 = 0 and b4 = 2 a4) */
+    tQ = Fl_add(Fl_mul6(Fl_sqr_pre(xQ, p, pi), p), Fl_double(a4, p), p);
+    t = Fl_add(t, tQ, p);
+
+    uQ = uQ_calc(a4, a6, xQ, p, pi);
+    /* w += uQ + tQ * xQ */
+    w = Fl_add(w, Fl_add(uQ, Fl_mul_pre(tQ, xQ, p, pi), p), p);
+    Q = Fle_add(pt, Q, a4, p);
+  } while ((ulong)Q[1] != xQ);
+  avma = av;
+  /* a4_img = a4 - 5 * t */
+  *a4_img = Fl_sub(a4, Fl_mul5(t, p), p);
+  /* a6_img = a6 - b2 * t - 7 * w = a6 - 7 * w
+   * (since a1 = a2 = 0 ==> b2 = 0) */
+  *a6_img = Fl_sub(a6, Fl_mul7(w, p), p);
+}
+
+
+/**
+ * SECTION: Calculation of modular polynomials.
+ */
+
+/* These are the conditions that a prime is required to satisfy, if
+ * set. */
+#define FILTER_PRIME_1MOD3 1
+#define FILTER_PRIME_2MOD3 2
+#define FILTER_PRIME_1MOD4 4
+#define FILTER_PRIME_3MOD4 8
+
+INLINE int
+passes_filter(ulong p, ulong filter)
+{
+  /* filter & 3 == 3 means FILTER_PRIME_1MOD3 and FILTER_PRIME_2MOD3
+   * were both set.
+   * filter & 12 == 12 means FILTER_PRIME_1MOD4 and
+   * FILTER_PRIME_3MOD4 were both set. */
+  if (DEBUGLEVEL && ((filter & 3) == 3 || (filter & 12) == 12)) {
+    char *err = stack_sprintf("passes_filter: "
+                              "got incoherent filter: %#lx", filter);
+    pari_err_BUG(err);
+  }
+  if ((filter & FILTER_PRIME_1MOD3) && (p % 3 != 1))
+    return 0;
+  if ((filter & FILTER_PRIME_2MOD3) && (p % 3 != 2))
+    return 0;
+  if ((filter & FILTER_PRIME_1MOD4) && (p % 4 != 1))
+    return 0;
+  if ((filter & FILTER_PRIME_3MOD4) && (p % 4 != 3))
+    return 0;
+  return 1;
+}
+
+/*
+ * Select primes suitable for modpoly CRT.  See Sutherland 2012,
+ * Section 6.1.
+ *
+ * Result is a t_VECSMALL whose odd elements (starting at index 1) are
+ * the primes, and whose even elements are the corresponding traces
+ * (i.e. the t such that 4p = t^2 - v^2 L^2 D).  The sign of the trace
+ * is *correct* in the sense that t = 2 (mod L) is satisfied.
+ */
+static GEN
+select_modpoly_primes(
+  ulong v, ulong L, long D, double min_prime_bits, ulong filter)
+{
+  double prime_bits = 0.0;
+  ulong vsqr = v * v;
+  /* Note that vsqr * L * L * -D is positive since D is negative */
+  ulong m_vsqr_Lsqr_D = vsqr * L * L * -D;
+  ulong lost_primes = 0;
+
+  pari_sp av = avma;
+  long *vec = (long *)avma, veclen;
+
+  /* This funny business with abs_t, incr and other_incr provides a
+   * way to iterate over the values of t which are congruent to 2
+   * modulo L such that abs(t) is monotonically increasing (for L > 3,
+   * and close enough for L = 3).  This is achieved by alternately
+   * incrementing abs_t by 4 or L - 4.  The sequence of abs_t's we
+   * obtain is:
+   *
+   *     t      abs_t   incr
+   * ----------------------------
+   *       2        2
+   *   2 - L    L - 2   L - 4
+   *   2 + L    L + 2   4
+   *   2 - 2L  2L - 2   L - 4
+   *   2 + 2L  2L + 2   4
+   *   2 - 3L  3L - 2   L - 4
+   *   2 + 2L  3L + 2   4
+   */
+
+  /* incr will be -1 if L = 3, but otherwise positive. */
+  long incr = L - 4;
+  long other_incr = 4;
+  ulong abs_tr = 2;
+  ulong max_tr = 2.0 * sqrt((1UL << (BITS_IN_LONG - 2)) - (m_vsqr_Lsqr_D >> 2));
+  do {
+    ulong possible_4p = abs_tr * abs_tr + m_vsqr_Lsqr_D;
+    if (possible_4p % 4 == 0) {
+      ulong possible_p = possible_4p / 4;
+      if (passes_filter(possible_p, filter)
+          && uisprime(possible_p)) {
+        /* Note that we now have 4p = t^2 - v^2 L^2 D for a prime p =
+         * possible_p.  Since t = 2 (mod L) by construction, we see
+         * that, modulo L, we have
+         *
+         * p = (1/4) (t^2 - v^2 L^2 D) = t^2 / 4 = 1.
+         *
+         * From the table above we see that t = |t| iff incr = 4 was
+         * added last time.  But the condition incr = 4 is negated
+         * because we swapped incr and other_incr after adding incr to
+         * abs_tr at the bottom of the loop. */
+        int sign = incr != 4 ? 1 : -1;
+        long tr = sign * abs_tr;
+        ulong card = possible_p + 1 - tr;
+
+        ulong vL = u_lval(card, L);
+        if (vL == 0 || vL == 1) {
+          pari_err_BUG("select_modpoly_primes: "
+                       "Incorrect trace sign");
+        }
+
+        /* Exclude primes with vL > 2 to make searching for L-torsion
+         * points faster in the function compute_L_isogenous_curve()
+         * below.  We throw away (very roughly) between 1% and 3% of
+         * our primes because of this. */
+        if (vL == 2) {
+          /* Append our new prime and its trace to the end of the
+           * array. */
+          *--vec = tr;
+          *--vec = possible_p;
+
+          prime_bits += log2(possible_p);
+          /* Do we have sufficiently many primes? */
+          if (prime_bits >= min_prime_bits)
+            break;
+        } else
+          lost_primes++;
+      }
+    }
+    abs_tr += incr;
+    lswap(incr, other_incr);
+  } while (abs_tr < max_tr);
+
+  if (abs_tr >= max_tr) {
+    char *err = stack_sprintf("modular polynomial of level %lu", L);
+    pari_err(e_ARCH, err);
+  }
+
+  /* Add type information. */
+  --vec;
+  veclen = (av - (pari_sp)vec) / sizeof(long);
+  if (veclen <= 1) {
+    char *err = stack_sprintf("select_modpoly_primes: Didn't find any "
+                              "primes for L = %lu and D = %ld", L, D);
+    pari_err_BUG(err);
+  }
+
+  *vec = evaltyp(t_VECSMALL) | evallg(veclen);
+  avma = (pari_sp)vec;
+  dbg_printf(1, "Threw away %.2f%% of primes because of high L-valuation",
+             100 * lost_primes / (double)(lost_primes + veclen));
+  return (GEN)vec;
+}
+
+
+/*
+ * Given an elliptic curve [a4, a6] over FF_p, try to find a
+ * non-trivial L-torsion point on the curve by considering n times a
+ * random point; val controls the maximum L-valuation expected of n
+ * times a random point.
+ */
+static GEN
+find_L_tors_point(
+  ulong *ival,
+  ulong a4, ulong a6, ulong p, ulong pi,
+  ulong n, ulong L, ulong val)
+{
+  pari_sp av = avma;
+  ulong i;
+  GEN P, Q;
+  do {
+    Q = random_Flj_pre(a4, a6, p, pi);
+    P = Flj_mulu_pre(Q, n, a4, p, pi);
+  } while (P[3] == 0);
+
+  for (i = 0; i < val; ++i) {
+    Q = Flj_mulu_pre(P, L, a4, p, pi);
+    if (Q[3] == 0)
+      break;
+    P = Q;
+  }
+  if (ival)
+    *ival = i;
+  return gerepilecopy(av, P);
+}
+
+
+static GEN
+select_curve_with_L_tors_point(
+  ulong *a4, ulong *a6,
+  ulong L, ulong j, ulong n, ulong card, ulong val,
+  norm_eqn_t ne)
+{
+  pari_sp av = avma;
+  ulong A4, A4t, A6, A6t;
+  ulong p = ne->p, pi = ne->pi;
+  GEN P;
+  if (card % L != 0) {
+    pari_err_BUG("select_curve_with_L_tors_point: "
+                 "Cardinality not divisible by L");
+  }
+
+  Fl_ellj_to_a4a6(j, p, &A4, &A6);
+  Fl_elltwist(A4, A6, ne->T, p, &A4t, &A6t);
+
+  /* Either E = [a4, a6] or its twist has cardinality divisible by L
+   * because of the choice of p and t earlier on.  We find out which
+   * by attempting to find a point of order L on each.  See bot p16 of
+   * Sutherland 2012. */
+  while (1) {
+    ulong i;
+    P = find_L_tors_point(&i, A4, A6, p, pi, n, L, val);
+    if (i < val)
+      break;
+    avma = av;
+    lswap(A4, A4t);
+    lswap(A6, A6t);
+  }
+
+  *a4 = A4;
+  *a6 = A6;
+  return gerepilecopy(av, P);
+}
+
+
+/*
+ * Return 1 if the L-Sylow subgroup of the curve [a4, a6] (mod p) is
+ * cyclic, return 0 if it is not cyclic with "high" probability (I
+ * guess around 1/L^3 chance it is still cyclic when we return 0).
+ *
+ * NB: A return value of 1 means that [a4, a6] (mod p) is on the floor
+ * of its L-volcano.
+ *
+ * This code is based on Sutherland's
+ * velu.c:velu_verify_Sylow_cyclic() in classpoly-1.0.1.
+ */
+INLINE long
+verify_L_sylow_is_cyclic(
+  long e, ulong a4, ulong a6, ulong p, ulong pi)
+{
+  /* Number of times to try to find a point with maximal order in the
+   * L-Sylow subgroup. */
+  enum { N_RETRIES = 3 };
+  pari_sp av = avma;
+  long i, res = 0;
+  GEN P;
+  for (i = 0; i < N_RETRIES; ++i) {
+    P = random_Flj_pre(a4, a6, p, pi);
+    P = Flj_mulu_pre(P, e, a4, p, pi);
+    if (P[3] != 0) {
+      res = 1;
+      break;
+    }
+  }
+  avma = av;
+  return res;
+}
+
+
+static ulong
+find_noniso_L_isogenous_curve(
+  ulong L, ulong n,
+  norm_eqn_t ne, long e, ulong val, ulong a4, ulong a6, GEN init_pt)
+{
+  pari_sp ltop, av;
+  ulong p = ne->p, pi = ne->pi, j_res = 0;
+  GEN pt = init_pt;
+  ltop = av = avma;
+  while (1) {
+    /* c. Use Velu to calculate L-isogenous curve E' = E/<P> */
+    ulong a4_img, a6_img;
+    ulong z2 = Fl_sqr_pre(pt[3], p, pi);
+    pt = mkvecsmall2(Fl_div(pt[1], z2, p),
+                     Fl_div(pt[2], Fl_mul_pre(z2, pt[3], p, pi), p));
+    Fle_quotient_from_kernel_generator(&a4_img, &a6_img,
+                                       a4, a6, pt, p, pi);
+
+    /* d. If j(E') = j_res has a different endo ring to j(E), then
+     *    return j(E').  Otherwise, go to b. */
+    if (verify_L_sylow_is_cyclic(e, a4_img, a6_img, p, pi)) {
+      j_res = Fl_ellj_pre(a4_img, a6_img, p, pi);
+      break;
+    }
+
+    /* b. Generate random point P on E of order L */
+    avma = av;
+    pt = find_L_tors_point(0, a4, a6, p, pi, n, L, val);
+  }
+
+  avma = ltop;
+  return j_res;
+}
+
+/*
+ * Given a prime L and a j-invariant j (mod p), return the j-invariant
+ * of a curve which has a different endomorphism ring to j and is
+ * L-isogenous to j.
+ */
+INLINE ulong
+compute_L_isogenous_curve(
+  ulong L, ulong n, norm_eqn_t ne,
+  ulong j, ulong card, ulong val)
+{
+  ulong a4, a6;
+  long e;
+  GEN pt;
+
+  if (ne->p < 5 || j == 0 || j == 1728 % ne->p) {
+    char *err = stack_sprintf("compute_L_isogenous_curve: "
+                              "Invalid params j = %lu, p = %lu", j, ne->p);
+    pari_err_BUG(err);
+  }
+
+  pt = select_curve_with_L_tors_point(&a4, &a6, L, j, n, card, val, ne);
+
+  e = card / L;
+  if (e * L != card) {
+    char *err = stack_sprintf("compute_L_isogenous_curve: "
+                              "L = %lu must divide p + 1 - t = %lu",
+                              L, card);
+    pari_err_BUG(err);
+  }
+
+  return find_noniso_L_isogenous_curve(L, n, ne, e, val, a4, a6, pt);
+}
+
+
+/*
+ * Identify the cycle generated by form starting at index j_idx of
+ * j_invs.
+ */
+static GEN
+identify_L_sqr_cycle(const modpoly_disc_info *dinfo, GEN j_invs, ulong j_idx)
+{
+  long idx;
+  long m;
+  long j_exp_0, j_exp_1, e_0, e_1, i;
+  long cyc_gen_0, cyc_gen_1, cyc_elt_0, cyc_elt_1;
+  long L = dinfo->L;
+  GEN res = cgetg(L, t_VECSMALL);
+
+  m = dinfo->n2;
+  cyc_gen_0 = dinfo->dl2_0;
+  cyc_gen_1 = 1;
+  cyc_elt_0 = dinfo->dl2_0;
+  cyc_elt_1 = 1;
+
+  j_idx -= 1;
+  j_exp_1 = j_idx / m;
+  j_exp_0 = j_idx - j_exp_1 * m;
+
+  for (i = 1; i <= L - 1; ++i) {
+    e_0 = (j_exp_0 + cyc_elt_0) % m;
+    e_1 = (j_exp_1 + cyc_elt_1) % 2;
+
+    idx = (e_0 + e_1 * m) + 1;
+    res[i] = j_invs[idx];
+
+    cyc_elt_0 += cyc_gen_0;
+    cyc_elt_0 %= m;
+    cyc_elt_1 += cyc_gen_1;
+    cyc_elt_1 %= 2;
+  }
+
+  return res;
+}
+
+
+static ulong
+oneroot_of_classpoly(
+  GEN hilb, GEN factu, norm_eqn_t ne, GEN *mpdb)
+{
+  pari_sp av = avma;
+  ulong j0, p = ne->p, pi = ne->pi;
+  long i, nfactors = lg(gel(factu, 1)) - 1;
+  GEN hilbp = ZX_to_Flx(hilb, p);
+
+  j0 = Flx_oneroot_split(hilbp, p);
+  if (j0 == p) {
+    pari_err_BUG("oneroot_of_classpoly: "
+                 "Didn't find a root of the class polynomial");
+  }
+  for (i = 1; i <= nfactors; ++i) {
+    long L = gel(factu, 1)[i];
+    long val = gel(factu, 2)[i];
+    GEN phi = polmodular_db_getp(mpdb, L, p);
+    j0 = descend_volcano(phi, j0, p, pi, 0, L, val, val);
+    avma = av;
+  }
+  avma = av;
+  return j0;
+}
+
+
+static GEN
+polmodular_split_p_evalx_Flv(
+  const modpoly_disc_info *dinfo, ulong pp,
+  GEN j_invs, GEN j_pr_invs, GEN R_j_invs, ulong j_idx)
+{
+  pari_sp av = avma;
+  GEN nhbrs_of_ji, j_ik, modpoly_at_ji, L2_cycle_containing_ji_pr;
+  long k, l_idx, r_idx, njinvs = lg(j_invs) - 1;
+  long m = dinfo->dl1;
+
+  r_idx = (((j_idx - 1) + m) % njinvs) + 1; /* (j_idx + m) % njinvs */
+  l_idx = smodss((j_idx - 1) - m, njinvs) + 1; /* (j_idx - m) % njinvs */
+  nhbrs_of_ji = mkvecsmall2(j_invs[l_idx], j_invs[r_idx]);
+
+  k = vecsmall_isin(R_j_invs, j_pr_invs[j_idx]);
+  if ( ! k) {
+    pari_err_BUG("polmodular_split_p_evalx_Flv: "
+                 "Couldn't find j-invariant in list");
+  }
+
+  /* FIXME: I think I can avoid recalculating the cycle for each j_idx
+   * and instead calculate it once and then "shift" the cycle forward
+   * by 1 for each iteration (for this identify_cycle() should return
+   * indices instead of j-invariants I guess). */
+  /* FIXME: We can actually enumerate ker(\phi) very quickly using
+   * essentially the same code as in form_of_norm_L_sqr().  The L2
+   * cycle could then be obtained by applying each element of
+   * ker(\phi) to ji.  It's not clear whether that would be faster
+   * than just searching for a generator as we do now. */
+  L2_cycle_containing_ji_pr
+    = identify_L_sqr_cycle(dinfo, R_j_invs, k);
+
+  j_ik = concat(nhbrs_of_ji, L2_cycle_containing_ji_pr);
+  modpoly_at_ji = Flv_roots_to_pol(j_ik, pp, 0);
+  dbg_printf4(3, "    Phi_%lu(X, %lu) (mod %lu) = %Ps\n",
+              dinfo->L, j_invs[j_idx], pp, modpoly_at_ji);
+
+  return gerepileupto(av, modpoly_at_ji);
+}
+
+
+INLINE GEN
+enum_volcano_surface(
+  const modpoly_disc_info *dinfo, norm_eqn_t ne, ulong j0, GEN *mpdb)
+{
+  pari_sp av = avma;
+  GEN pcp = mkvec2(mkvecsmall(dinfo->L0), mkvecsmall(dinfo->n1));
+  return gerepileupto(av, enum_j_with_endo_ring(j0, ne, mpdb, pcp, dinfo->n1));
+}
+
+INLINE GEN
+find_floor_curves(ulong L, ulong  n, norm_eqn_t ne, GEN j_invs, ulong card,
+                  ulong val)
+{
+  long i, l = L+2;
+  GEN j_pr_invs = cgetg(l+1, t_VECSMALL);
+  for (i = 1; i <= l; ++i)
+    j_pr_invs[i] = compute_L_isogenous_curve(L, n, ne, j_invs[i], card, val);
+  return j_pr_invs;
+}
+
+INLINE GEN
+enum_floor_curves(
+  long L, norm_eqn_t ne, ulong j0_pr, GEN *mpdb,
+  const modpoly_disc_info *dinfo)
+{
+  /* L^2 D is the discriminant for the order R = Z + L OO. */
+  long DR = L * L * ne->D;
+  long R_cond = L * ne->u; /* conductor(DR); */
+  /* FIXME: Is this still the right v? */
+  long w = R_cond * ne->v;
+  /* FIXME: Calculate these once and for all in polmodular0_ZM(). */
+  long d2 = z_lval(w, 2);
+  long dL = z_lval(w, dinfo->L1);
+  return enum_j_fast(j0_pr, DR, dinfo->L1, d2, dL, dinfo->n2, mpdb,
+                     ne->p, ne->pi);
+}
+
+INLINE GEN
+evaluated_modpoly_coeffs(
+  long L, ulong p, const modpoly_disc_info *dinfo,
+  GEN j_invs, GEN j_pr_invs, GEN R_j_invs)
+{
+  pari_sp av;
+  long i;
+  GEN coeff_mat = zero_Flm_copy(L + 2, L + 2);
+  av = avma;
+  for (i = 1; i <= L + 2; ++i) {
+    long k;
+    GEN modpoly_at_ji =
+      polmodular_split_p_evalx_Flv(dinfo, p, j_invs, j_pr_invs, R_j_invs, i);
+    for (k = 1; k <= L + 2; ++k)
+      coeff(coeff_mat, i, k) = modpoly_at_ji[k + 1];
+    avma = av;
+  }
+  return coeff_mat;
+}
+
+INLINE void
+interpolate_coeffs(
+  GEN modpoly_modp, /* Return parameter */
+  long L, ulong p, GEN j_invs, GEN coeff_mat)
+{
+  pari_sp av = avma;
+  GEN pols = Flv_FlvV_polint(j_invs, coeff_mat, p, 0);
+  long i;
+  for (i = 1; i <= L + 2; ++i) {
+    GEN pol = gel(pols, i);
+    long k, maxk = lg(pol);
+    for (k = 2; k < maxk; ++k)
+      coeff(modpoly_modp, i, k - 1) = pol[k];
+  }
+  avma = av;
+}
+
+/*
+ * This is Sutherland 2012, Algorithm 2.1, p16.
+ */
+static GEN
+polmodular_split_p_Flm(
+  ulong L, GEN hilb, GEN factu, norm_eqn_t ne, GEN *mpdb,
+  const modpoly_disc_info *dinfo)
+{
+  ulong j0, n, card, val, p = ne->p;
+  GEN j_invs, j_pr_invs, R_j_invs, coeff_mat;
+  GEN modpoly_modp = zero_Flm_copy(L + 2, L + 2);
+  pari_sp av = avma;
+
+  /* Precomputation */
+  card = p + 1 - ne->t;
+  val = u_lvalrem(card, L, &n); /* n = card / L^{v_L(card)} */
+
+  j0 = oneroot_of_classpoly(hilb, factu, ne, mpdb);
+  j_invs = enum_volcano_surface(dinfo, ne, j0, mpdb);
+  j_pr_invs = find_floor_curves(L, n, ne, j_invs, card, val);
+  R_j_invs = enum_floor_curves(L, ne, j_pr_invs[1], mpdb, dinfo);
+  coeff_mat = evaluated_modpoly_coeffs(L, p, dinfo,
+                                       j_invs, j_pr_invs, R_j_invs);
+  setlg(j_invs, L + 2 + 1);
+  interpolate_coeffs(modpoly_modp, L, p, j_invs, coeff_mat);
+
+  dbg_printf3(3, "  Phi_%lu(X, Y) (mod %lu) = %Ps\n",
+             L, p, modpoly_modp);
+
+  avma = av;
+  return modpoly_modp;
+}
+
+
+INLINE void
+norm_eqn_init(norm_eqn_t ne, long D, long u, long v, long L)
+{
+  memset(ne, 0, sizeof(*ne));
+  ne->D = D;
+  ne->u = u;
+  ne->v = v * L;
+  ne->w = ne->u * ne->v;
+}
+
+
+INLINE void
+norm_eqn_update(norm_eqn_t ne, long t, ulong p)
+{
+  ne->t = t;
+  ne->p = p;
+  ne->pi = get_Fl_red(p);
+  /* Select twisting parameter. */
+  do
+    ne->T = random_Fl(p);
+  while (krouu(ne->T, p) != -1);
+}
+
+INLINE void
+Flv_deriv_pre_inplace(GEN v, long deg, ulong p, ulong pi)
+{
+  long i, ln = lg(v);
+  for (i = ln - 1; i > 1; --i, --deg)
+    v[i] = Fl_mul_pre(v[i - 1], deg % p, p, pi);
+  v[1] = 0;
+}
+
+/* NB: Deliberately leave a dirty stack, since the result must be
+ * gerepileupto'd straight away in any case. */
+INLINE GEN
+eval_modpoly_modp(
+  GEN modpoly_modp, GEN j_powers, norm_eqn_t ne, int compute_derivs)
+{
+  ulong p = ne->p, pi = ne->pi;
+  long L = lg(j_powers) - 3;
+  GEN j_pows_p = ZV_to_Flv(j_powers, p);
+  GEN tmp = cgetg(2 + 2 * compute_derivs, t_VEC);
+  /* We wrap the result in this t_VEC modpoly_modp to trick the
+   * ZM_*_CRT() functions into thinking it's a matrix. */
+  gel(tmp, 1) = Flm_Flc_mul_pre(modpoly_modp, j_pows_p, p, pi);
+  if (compute_derivs) {
+    Flv_deriv_pre_inplace(j_pows_p, L + 1, p, pi);
+    gel(tmp, 2) = Flm_Flc_mul_pre(modpoly_modp, j_pows_p, p, pi);
+    Flv_deriv_pre_inplace(j_pows_p, L + 1, p, pi);
+    gel(tmp, 3) = Flm_Flc_mul_pre(modpoly_modp, j_pows_p, p, pi);
+  }
+  return tmp;
+}
+
+static GEN
+polmodular0_ZM(
+  ulong L, double min_prime_bits, GEN J, GEN Q,
+  int compute_derivs,
+  int quit_on_first_stabilisation)
+{
+  pari_sp ltop = avma, btop, av;
+  long D, DK;
+  ulong cond, v;
+  GEN mpdb;
+  ulong filter;
+  GEN pt_pairs;
+  long i, pt_pairs_len;
+  norm_eqn_t ne;
+  GEN hilb, j_powers, modpoly, P;
+  GEN factu;
+  const modpoly_disc_info *dinfo;
+
+  dbg_printf1(1, "Calculating modular polynomial of level %lu", L);
+  dinfo = discriminant_with_classno_at_least(&D, &cond, &v, L);
+  factu = factoru(cond);
+
+  av = avma;
+  mpdb = polmodular_db_init(0);
+
+  dbg_printf2(1, "Selected discriminant D = %ld which has conductor u = %ld.",
+              D, cond);
+
+  filter = 0; /* Don't filter anything. */
+  pt_pairs = select_modpoly_primes(v, L, D, min_prime_bits, filter);
+  pt_pairs_len = lg(pt_pairs) - 1;
+
+  dbg_printf3(1, "Selected %ld primes in [%ld, %ld]",
+              pt_pairs_len / 2, pt_pairs[pt_pairs_len - 1], pt_pairs[1]);
+
+  DK = D / (long)(cond * cond);
+  hilb = polclass(stoi(DK), -1);
+
+  norm_eqn_init(ne, D, cond, v, L);
+
+  j_powers = 0;
+  if (J) {
+    compute_derivs = !!compute_derivs;
+    j_powers = Fp_powers(J, L + 1, Q);
+  }
+
+  btop = avma;
+  if (J)
+    modpoly = ZM_init_CRT(zero_Flm(L + 2, compute_derivs ? 3 : 1), 1);
+  else
+    modpoly = ZM_init_CRT(zero_Flm(L + 2, L + 2), 1);
+  /* P is the product of all the primes. */
+  P = gen_1;
+  for (i = 1; i <= pt_pairs_len; i += 2) {
+    ulong p = pt_pairs[i];
+    ulong t = pt_pairs[i + 1];
+    GEN modpoly_modp;
+    int stab = 0;
+
+    norm_eqn_update(ne, t, p);
+
+    av = avma;
+    modpoly_modp = polmodular_split_p_Flm(L, hilb, factu, ne, &mpdb, dinfo);
+    if (J) {
+      modpoly_modp = eval_modpoly_modp(modpoly_modp, j_powers, ne, compute_derivs);
+      modpoly_modp = gerepileupto(av, modpoly_modp);
+    }
+    stab = ZM_incremental_CRT(&modpoly, modpoly_modp, &P, p);
+
+    if (gc_needed(btop, 2))
+      gerepileall(btop, 2, &modpoly, &P);
+    if (quit_on_first_stabilisation && stab)
+      break;
+  }
+
+  polmodular_db_clear(mpdb);
+  if (J)
+    return gerepileupto(ltop, FpM_red(modpoly, Q));
+  return gerepileupto(ltop, modpoly);
+}
+
+
+/* The largest level of the "hand written" modular polynomials */
+#define MAX_INTERNAL_MODPOLY_LEVEL 7
+
+/* The definitions of these functions are at the end of the file. */
+static GEN phi2_ZV(void);
+static GEN phi3_ZV(void);
+static GEN phi5_ZV(void);
+static GEN phi7_ZV(void);
+
+
+/* NB: Result not suitable for gerepileupto(). */
+static GEN
+sympol_to_ZM(GEN phi, long L)
+{
+  GEN res = zeromatcopy(L + 2, L + 2);
+  long i, j, c = 1;
+  for (i = 1; i <= L + 1; ++i) {
+    for (j = 1; j <= i; ++j, ++c)
+      gcoeff(res, i, j) = gcoeff(res, j, i) = gel(phi, c);
+  }
+  gcoeff(res, L + 2, 1) = gcoeff(res, 1, L + 2) = gen_1;
+  return res;
+}
+
+
+GEN
+polmodular_ZM(long L)
+{
+  double c, min_prime_bits;
+  pari_sp av = avma;
+  GEN mp = 0;
+
+  /* Handle very small L separately. */
+  switch (L) {
+  case 2:
+    mp = phi2_ZV(); break;
+  case 3:
+    mp = phi3_ZV(); break;
+  case 5:
+    mp = phi5_ZV(); break;
+  case 7:
+    mp = phi7_ZV(); break;
+  }
+  if (mp)
+    return gerepilecopy(av, sympol_to_ZM(mp, L));
+
+  if (L < 2)
+    pari_err_DOMAIN("polmodular_ZM", "L", "<", gen_2, stoi(L));
+
+  /* FIXME: Handle non-prime L.  This is Algorithm 1.1 and Corollary
+   * 3.4 in Sutherland, "Class polynomials for nonholomorphic modular
+   * functions". */
+  if ( ! uisprime(L))
+    pari_err_IMPL("composite level");
+
+  /* Need \sum log2(p) >= |c|/log(2) + 2 where c = 6 * L * (log(L) +
+   * 3) is an upper bound for the logarithmic height of \Phi_L.  For L
+   * > 3187, we use the better bound c = 2 (3L + 7 sqrt(L)) log(L) +
+   * 16L. See Sutherland "On the evaluation of modular polynomials",
+   * p6. */
+  c = (L <= 3187)
+    ? 6 * L * (log(L) + 3)
+    : 2 * (3 * L + 7 * sqrt(L)) * log(L) + 16 * L;
+  min_prime_bits = c / LOG2 + 2;
+
+  return polmodular0_ZM(L, min_prime_bits, 0, 0, 0, 0);
+}
+
+
+GEN
+polmodular_ZXX(long L, long vx, long vy)
+{
+  pari_sp av = avma;
+  GEN phi = polmodular_ZM(L);
+
+  if (vx < 0) vx = 0;
+  if (vy < 0) vy = 1;
+  if (varncmp(vx, vy) >= 0)
+    pari_err_PRIORITY("polmodular_ZXX", pol_x(vx), "<=", vy);
+
+  return gerepilecopy(av, RgM_to_RgXX(phi, vx, vy));
+}
+
+INLINE GEN
+FpV_deriv(GEN v, long deg, GEN P)
+{
+  long i, ln = lg(v);
+  GEN dv = cgetg(ln, t_VEC);
+  for (i = ln - 1; i > 1; --i, --deg)
+    gel(dv, i) = Fp_mulu(gel(v, i - 1), deg, P);
+  gel(dv, 1) = gen_0;
+  return dv;
+}
+
+GEN
+Fp_polmodular_evalx(
+  long L, GEN J, GEN P, long v, int compute_derivs)
+{
+  pari_sp av = avma;
+  double c;
+  GEN phi;
+
+  if (L <= MAX_INTERNAL_MODPOLY_LEVEL) {
+    GEN tmp;
+    GEN phi = RgM_to_FpM(polmodular_ZM(L), P);
+    GEN j_powers = Fp_powers(J, L + 1, P);
+    GEN modpol = RgV_to_RgX(FpM_FpC_mul(phi, j_powers, P), v);
+    if (compute_derivs) {
+      tmp = cgetg(4, t_VEC);
+      gel(tmp, 1) = modpol;
+      j_powers = FpV_deriv(j_powers, L + 1, P);
+      gel(tmp, 2) = RgV_to_RgX(FpM_FpC_mul(phi, j_powers, P), v);
+      j_powers = FpV_deriv(j_powers, L + 1, P);
+      gel(tmp, 3) = RgV_to_RgX(FpM_FpC_mul(phi, j_powers, P), v);
+    } else {
+      tmp = modpol;
+    }
+    return gerepilecopy(av, tmp);
+  }
+
+  /* The height bound is 6 L log(L) + 18 L + log(q) + 3 log(L + 2) + log(4).
+   *                    = 3 (2L (log(L) + 3) + log(L + 2)) + log(q) + log(4) */
+  c = 3 * (2 * L * log2(L) + log2(L + 2)) + 18 * L / LOG2
+    + dbllog2r(itor(P, DEFAULTPREC)) + 2;
+  phi = polmodular0_ZM(L, c, J, P, compute_derivs, 0);
+  phi = RgM_to_RgXV(phi, v);
+  return gerepilecopy(av, compute_derivs ? phi : gel(phi, 1));
+}
+
+GEN
+polmodular(long L, GEN x, long v, int compute_derivs)
+{
+  pari_sp av = avma;
+  long tx;
+  GEN J = NULL, P = NULL, res = NULL, one = NULL;
+
+  if ( ! x || gequalX(x)) {
+    long xv = 0;
+    if (x)
+      xv = varn(x);
+    if (compute_derivs)
+      pari_err_FLAG("polmodular");
+    return polmodular_ZXX(L, xv, v);
+  }
+
+  tx = typ(x);
+  if (tx == t_INTMOD) {
+    J = gel(x, 2);
+    P = gel(x, 1);
+    one = mkintmod(gen_1, P);
+  } else if (tx == t_FFELT) {
+    J = FF_to_FpXQ_i(x);
+    if (degpol(J) > 0)
+      pari_err_DOMAIN("polmodular", "x", "not in prime subfield ", gen_0, x);
+    J = constant_term(J);
+    P = FF_p_i(x);
+    one = p_to_FF(P, 0);
+  } else {
+    pari_err_TYPE("polmodular", x);
+  }
+
+  if (v < 0) v = 1;
+  res = Fp_polmodular_evalx(L, J, P, v, compute_derivs);
+  res = gmul(res, one);
+  return gerepileupto(av, res);
+}
+
+/**
+ * SECTION: Modular polynomials of level <= MAX_INTERNAL_MODPOLY_LEVEL.
+ */
+
+/*
+ * These functions return a vector of unique coefficients of classical
+ * modular polynomials \Phi_L(X, Y) of small level L.  The number of
+ * such coefficients is (L + 1)(L + 2)/2 since \Phi is symmetric.  The
+ * i(i+1)/2-th through i(i+3)/2-th entries of the vector are the
+ * coefficients of the coefficient of X^i considered as a polynomial
+ * in Y (FIXME: this is not exactly correct).  Note that we omit the
+ * (common) coefficient of X^{L + 1} and Y^{L + 1} since it is always 1.
+ *
+ * Use GEN ZV_to_Flv(GEN v, ulong p) to reduce the polynomial modulo p.
+ */
+
+
+/*
+ *  Phi2, the modular polynomial of level 2:
+ *
+ *  X^3
+ *  + X^2 * (-Y^2 + 1488*Y - 162000)
+ *  + X * (1488*Y^2 + 40773375*Y + 8748000000)
+ *  + Y^3 - 162000*Y^2 + 8748000000*Y - 157464000000000
+ *
+ *  [[3, 0, 1],
+ *   [2, 2, -1],
+ *   [2, 1, 1488],
+ *   [2, 0, -162000],
+ *   [1, 1, 40773375],
+ *   [1, 0, 8748000000],
+ *   [0, 0, -157464000000000]],
+ */
+
+static GEN
+phi2_ZV(void)
+{
+  GEN phi2 = cgetg(7, t_VEC);
+  gel(phi2, 1) = uu32toi(36662, 1908994048);
+  setsigne(gel(phi2, 1), -1);
+  gel(phi2, 2) = uu32toi(2, 158065408);
+  gel(phi2, 3) = stoi(40773375);
+  gel(phi2, 4) = stoi(-162000);
+  gel(phi2, 5) = stoi(1488);
+  gel(phi2, 6) = gen_m1;
+  return phi2;
+}
+
+
+/*
+ * L = 3
+ *
+ * [4, 0, 1],
+ * [3, 3, -1],
+ * [3, 2, 2232],
+ * [3, 1, -1069956],
+ * [3, 0, 36864000],
+ * [2, 2, 2587918086],
+ * [2, 1, 8900222976000],
+ * [2, 0, 452984832000000],
+ * [1, 1, -770845966336000000],
+ * [1, 0, 1855425871872000000000]
+ * [0, 0, 0]
+ *
+ * X^4
+ * + X^3 (-Y^3 + 2232*Y^2 - 1069956*Y + 36864000)
+ * + X^2 (2232*Y^3 + 2587918086*Y^2 + 8900222976000*Y + 452984832000000)
+ * + X (-1069956*Y^3 + 8900222976000*Y^2 - 770845966336000000*Y + 1855425871872000000000)
+ * + Y^4 + 36864000*Y^3 + 452984832000000*Y^2 + 1855425871872000000000*Y
+ *
+ * 1855425871872000000000 == 2^32 * (100 * 2^32 + 2503270400)
+ */
+static GEN
+phi3_ZV(void)
+{
+  GEN phi3 = cgetg(11, t_VEC);
+  pari_sp av = avma;
+  gel(phi3, 1) = gen_0;
+  gel(phi3, 2) = gerepileupto(av, shifti(uu32toi(100, 2503270400UL), 32));
+  gel(phi3, 3) = uu32toi(179476562, 2147483648UL);
+  setsigne(gel(phi3, 3), -1);
+  gel(phi3, 4) = uu32toi(105468, 3221225472UL);
+  gel(phi3, 5) = uu32toi(2072, 1050738688);
+  gel(phi3, 6) = utoi(2587918086UL);
+  gel(phi3, 7) = stoi(36864000);
+  gel(phi3, 8) = stoi(-1069956);
+  gel(phi3, 9) = stoi(2232);
+  gel(phi3, 10) = gen_m1;
+  return phi3;
+}
+
+
+static GEN
+phi5_ZV(void)
+{
+  GEN phi5 = cgetg(22, t_VEC);
+  gel(phi5, 1) = mkintn(5, 0x18c2cc9cUL, 0x484382b2UL, 0xdc000000UL, 0x0UL, 0x0UL);
+  gel(phi5, 2) = mkintn(5, 0x2638fUL, 0x2ff02690UL, 0x68026000UL, 0x0UL, 0x0UL);
+  gel(phi5, 3) = mkintn(5, 0x308UL, 0xac9d9a4UL, 0xe0fdab12UL, 0xc0000000UL, 0x0UL);
+  setsigne(gel(phi5, 3), -1);
+  gel(phi5, 4) = mkintn(5, 0x13UL, 0xaae09f9dUL, 0x1b5ef872UL, 0x30000000UL, 0x0UL);
+  gel(phi5, 5) = mkintn(4, 0x1b802fa9UL, 0x77ba0653UL, 0xd2f78000UL, 0x0UL);
+  gel(phi5, 6) = mkintn(4, 0xfbfdUL, 0x278e4756UL, 0xdf08a7c4UL, 0x40000000UL);
+  gel(phi5, 7) = mkintn(4, 0x35f922UL, 0x62ccea6fUL, 0x153d0000UL, 0x0UL);
+  gel(phi5, 8) = mkintn(4, 0x97dUL, 0x29203fafUL, 0xc3036909UL, 0x80000000UL);
+  setsigne(gel(phi5, 8), -1);
+  gel(phi5, 9) = mkintn(3, 0x56e9e892UL, 0xd7781867UL, 0xf2ea0000UL);
+  gel(phi5, 10) = mkintn(3, 0x5d6dUL, 0xe0a58f4eUL, 0x9ee68c14UL);
+  setsigne(gel(phi5, 10), -1);
+  gel(phi5, 11) = mkintn(3, 0x1100dUL, 0x85cea769UL, 0x40000000UL);
+  gel(phi5, 12) = mkintn(3, 0x1b38UL, 0x43cf461fUL, 0x3a900000UL);
+  gel(phi5, 13) = mkintn(3, 0x14UL, 0xc45a616eUL, 0x4801680fUL);
+  gel(phi5, 14) = uu32toi(0x17f4350UL, 0x493ca3e0UL);
+  gel(phi5, 15) = uu32toi(0x183UL, 0xe54ce1f8UL);
+  gel(phi5, 16) = uu32toi(0x1c9UL, 0x18860000UL);
+  gel(phi5, 17) = uu32toi(0x39UL, 0x6f7a2206UL);
+  setsigne(gel(phi5, 17), -1);
+  gel(phi5, 18) = stoi(2028551200);
+  gel(phi5, 19) = stoi(-4550940);
+  gel(phi5, 20) = stoi(3720);
+  gel(phi5, 21) = gen_m1;
+  return phi5;
+}
+
+
+static GEN
+phi7_ZV(void)
+{
+  GEN phi7 = cgetg(37, t_VEC);
+  gel(phi7, 1) = gen_0;
+  gel(phi7, 2) = gen_0;
+  gel(phi7, 3) = mkintn(7, 0xb98ef8aUL, 0x5da89820UL, 0x27fcaa10UL, 0xc337ec73UL, 0xe8000000UL, 0x0UL, 0x0UL);
+  gel(phi7, 4) = mkintn(7, 0xde8a58bUL, 0xfbf60e2aUL, 0x25371391UL, 0x6b054e99UL, 0x54000000UL, 0x0UL, 0x0UL);
+  gel(phi7, 5) = mkintn(7, 0x209d2UL, 0xd2dd3b42UL, 0xf208c229UL, 0xd3f6cd61UL, 0x5aa81000UL, 0x0UL, 0x0UL);
+  setsigne(gel(phi7, 5), -1);
+  gel(phi7, 6) = mkintn(7, 0x7UL, 0x6f2fd980UL, 0x822116beUL, 0x3dd5c31aUL, 0xc177b28aUL, 0x20000000UL, 0x0UL);
+  setsigne(gel(phi7, 6), -1);
+  gel(phi7, 7) = mkintn(7, 0x864UL, 0x1e548f80UL, 0x799513d5UL, 0xbd1bf6b2UL, 0xc0855000UL, 0x0UL, 0x0UL);
+  gel(phi7, 8) = mkintn(7, 0x14UL, 0xa9082853UL, 0xf7daac9fUL, 0xd3ae375aUL, 0xb11a1708UL, 0xa0000000UL, 0x0UL);
+  setsigne(gel(phi7, 8), -1);
+  gel(phi7, 9) = mkintn(6, 0x2f287d2UL, 0xa017bd69UL, 0x4c5eb85aUL, 0xa496f0f2UL, 0x68dac000UL, 0x0UL);
+  gel(phi7, 10) = mkintn(6, 0xe6dUL, 0x2818206dUL, 0x99adaa70UL, 0x1e05f921UL, 0x26c36d89UL, 0x80000000UL);
+  setsigne(gel(phi7, 10), -1);
+  gel(phi7, 11) = mkintn(6, 0x1affb90UL, 0x75076431UL, 0x92c2d298UL, 0x18ed8fe9UL, 0x70000000UL, 0x0UL);
+  gel(phi7, 12) = mkintn(6, 0x5c6d2UL, 0xc60306c0UL, 0xd36aaa58UL, 0x1dc09f98UL, 0xccac000UL, 0x0UL);
+  gel(phi7, 13) = mkintn(6, 0xd3UL, 0x3bee42d3UL, 0x193e211UL, 0x575981bcUL, 0xa77b12beUL, 0x80000000UL);
+  gel(phi7, 14) = mkintn(5, 0x325e879UL, 0xcc292d75UL, 0x6086beceUL, 0x8c18673aUL, 0x993d0000UL);
+  gel(phi7, 15) = mkintn(5, 0x102UL, 0xb7de9305UL, 0x26c5fde5UL, 0x122a579eUL, 0x7bad0c46UL);
+  gel(phi7, 16) = mkintn(6, 0x1cUL, 0xf4fc37ccUL, 0xb61bee0cUL, 0x1aa43057UL, 0x85e38000UL, 0x0UL);
+  gel(phi7, 17) = mkintn(5, 0x7209872UL, 0xa810ac3cUL, 0xaf82d027UL, 0x19b659f6UL, 0x0UL);
+  setsigne(gel(phi7, 17), -1);
+  gel(phi7, 18) = mkintn(5, 0x815eUL, 0xfad28592UL, 0xf33facf6UL, 0x10060813UL, 0x25580000UL);
+  gel(phi7, 19) = mkintn(5, 0x2UL, 0xa6529211UL, 0xea123ef6UL, 0x7ad394d2UL, 0xabe49138UL);
+  setsigne(gel(phi7, 19), -1);
+  gel(phi7, 20) = mkintn(4, 0x2b58cUL, 0x1cbcbb65UL, 0x2ce001cfUL, 0x279429e0UL);
+  gel(phi7, 21) = mkintn(3, 0x3b2214c4UL, 0xf2b5e5fbUL, 0x1f81b4ecUL);
+  setsigne(gel(phi7, 21), -1);
+  gel(phi7, 22) = mkintn(4, 0xb3a0UL, 0x57dd5903UL, 0x23f93a5cUL, 0xc0000000UL);
+  gel(phi7, 23) = mkintn(4, 0x332eUL, 0x3435e075UL, 0xaa2299d4UL, 0x3a1e0000UL);
+  gel(phi7, 24) = mkintn(4, 0x86UL, 0xddc49282UL, 0xb81e3f32UL, 0xb5d52a1cUL);
+  gel(phi7, 25) = mkintn(3, 0x341ab0c9UL, 0x2a5aafc0UL, 0x5c470530UL);
+  gel(phi7, 26) = mkintn(3, 0x3b0a4UL, 0x2ced66eaUL, 0x97d5e888UL);
+  gel(phi7, 27) = mkintn(3, 0x9UL, 0x999bc197UL, 0x601617f0UL);
+  gel(phi7, 28) = uu32toi(0x11c4eUL, 0x9c431839UL);
+  gel(phi7, 29) = uu32toi(0x1736b97UL, 0xef4d0000UL);
+  gel(phi7, 30) = uu32toi(0x7c5237UL, 0xf1971f08UL);
+  setsigne(gel(phi7, 30), -1);
+  gel(phi7, 31) = uu32toi(0x28efdUL, 0x46d450f0UL);
+  gel(phi7, 32) = uu32toi(0x3b5UL, 0xe122f592UL);
+  setsigne(gel(phi7, 32), -1);
+  gel(phi7, 33) = uu32toi(0x2UL, 0x32877ba0UL);
+  gel(phi7, 34) = stoi(-10246068);
+  gel(phi7, 35) = stoi(5208);
+  gel(phi7, 36) = gen_m1;
+  return phi7;
+}
+
+/*
+ * This data was generated using Sutherland's modpoly_pickD() function.
+ */
+
+#ifndef LONG_IS_64BIT
+#define DISC_TABLE_LENGTH 24
+#else
+#define DISC_TABLE_LENGTH 429
+#endif
+
+/*   L         D0         D1   L0   L1      n1      n2   #P     dl1  dl2[0]  dl2[1] */
+static const modpoly_disc_info DISC_TABLE[DISC_TABLE_LENGTH] = {
+{    5,      -111,      -111,   2,   3,      8,     16,  12,      5,      4,   1 },
+{    7,      -159,      -159,   2,   3,     10,     30,  16,      6,     25,   1 },
+{   11,      -791,      -791,   2,   7,     16,     80,  21,     10,     56,   1 },
+{   13,     -6295,     -6295,   2,   5,     24,    144,  29,     17,     84,   1 },
+{   17,      -695,      -695,   2,   5,     24,    192,  34,      9,    156,   1 },
+{   19,     -1191,     -1191,   2,   3,     24,    216,  39,     20,    156,   1 },
+{   23,      -143,     -7007,   2,  11,     30,    330,  45,     18,    225,   1 },
+{   29,     -4647,     -4647,   2,   3,     32,    448,  60,      7,    240,   1 },
+{   31,     -2199,     -2199,   2,   3,     36,    540,  60,     24,    234,   1 },
+{   37,     -1655,     -1655,   2,   5,     44,    792,  67,     11,    242,   1 },
+{   41,     -1919,     -1919,   2,  19,     44,    880,  75,     37,    418,   1 },
+{   43,       -39,     -6591,   2,   3,     52,   1092,  84,     16,    442,   1 },
+{   47,       -15,    -10935,   2,   5,     54,   1242,  93,     15,    837,   1 },
+{   53,     -2495,     -2495,   2,   5,     56,   1456,  96,     19,   1428,   1 },
+{   59,    -14183,    -14183,   2,  13,     64,   1856, 114,     21,   1184,   1 },
+{   61,    -12199,    -12199,   2,  11,     64,   1920, 117,     43,    608,   1 },
+{   67,    -10551,    -10551,   2,   3,     72,   2376, 126,     54,   1260,   1 },
+{   71,       -55,    -75295,   2,  11,     76,   2660, 135,     60,   1786,   1 },
+{   73,     -4631,     -4631,   2,  11,     76,   2736, 128,     51,   2242,   1 },
+{   79,    -16311,    -16311,   2,   3,     84,   3276, 148,     28,   1218,   1 },
+{   83,     -7319,     -7319,   2,  13,     88,   3608, 147,     59,   1980,   1 },
+{   89,    -13471,    -13471,   2,  19,     92,   4048, 167,     13,   2714,   1 },
+{   97,    -10055,    -10055,   2,   5,    100,   4800, 172,     63,   3650,   1 },
+{  101,    -20487,    -20487,   2,   3,    104,   5200, 184,     63,   3692,   1 }
+
+#ifdef LONG_IS_64BIT
+                                                                                  ,
+{  103,    -10911,    -10911,   2,   3,    108,   5508, 182,     64,   4266,   1 },
+{  107,     -7895,     -7895,   2,   5,    112,   5936, 185,     97,   5208,   1 },
+{  109,    -32071,    -32071,   2,  13,    112,   6048, 203,     95,   3080,   1 },
+{  113,    -13927,   -348175,   2,  19,    120,   6720, 215,     19,   2340,   1 },
+{  127,    -40791,    -40791,   2,   3,    132,   8316, 232,    106,   7062,   1 },
+{  131,      -407,   -296703,   2,  37,    144,   9360, 243,     61,   4248,   1 },
+{  137,     -1263,   -213447,   2,   3,    140,   9520, 253,     89,   4270,   1 },
+{  139,    -42199,    -42199,   2,  19,    144,   9936, 255,     36,   7848,   1 },
+{  149,     -1119,   -135399,   2,   3,    160,  11840, 265,     21,  11440,   1 },
+{  151,    -41079,    -41079,   2,   3,    156,  11700, 270,     88,   3822,   1 },
+{  157,    -37295,    -37295,   2,   5,    160,  12480, 276,     23,   3920,   1 },
+{  163,     -5007,   -605847,   2,   3,    180,  14580, 302,    120,   8730,   1 },
+{  167,      -407,    -49247,   2,  37,    176,  14608, 296,     61,   2552,   1 },
+{  173,     -5007,   -605847,   2,   3,    180,  15480, 319,     75,  13950,   1 },
+{  179,    -43087,  -1077175,   2,  11,    192,  17088, 335,     38,   9120,   1 },
+{  181,   -184927,   -184927,   2,  19,    188,  16920, 340,      9,   1598,   1 },
+{  191,     -3959,   -320679,   2,  37,    204,  19380, 342,     51,   7242,   1 },
+{  193,     -2959,  -1849375,   2,  11,    200,  19200, 347,     27,   8300,   1 },
+{  197,     -4367,   -109175,   2,  11,    204,  19992, 333,    127,  19074,   1 },
+{  199,     -1007,   -170183,   2,  19,    210,  20790, 341,    134,  16905,   1 },
+{  211,    -33591,    -33591,   2,   3,    216,  22680, 363,     88,   7884,   1 },
+{  223,      -327,   -447663,   2,   3,    228,  25308, 399,     74,  16986,   1 },
+{  227,    -20095,  -7254295,   2,   5,    240,  27120, 404,     13,  23400,   1 },
+{  229,    -43007,    -43007,   2,  29,    232,  26448, 393,    151,  25868,   1 },
+{  233,    -14695,  -1778095,   2,   5,    240,  27840, 433,    101,  16440,   1 },
+{  239,      -871,   -460759,   2,  13,    242,  28798, 423,    185,    121,   1 },
+{  241,    -52679,    -52679,   2,  11,    244,  29280, 408,    111,  11102,   1 },
+{  251,    -27607,   -690175,   2,  19,    264,  33000, 453,     26,   9372,   1 },
+{  257,      -535,   -732415,   2,   5,    266,  34048, 463,    181,  19551,   1 },
+{  263,     -3439,   -993871,   2,  19,    270,  35370, 474,    226,  19845,   1 },
+{  269,   -116031,   -116031,   2,   3,    272,  36448, 472,     65,   7480,   1 },
+{  271,     -2823,  -1493367,   2,   3,    286,  38610, 492,    190,  27599,   1 },
+{  277,   -274207,   -274207,   2,  37,    280,  38640, 504,    241,  23380,   1 },
+{  281,    -24383,  -1975023,   2,  37,    288,  40320, 514,    211,  11664,   1 },
+{  283,   -105159,   -105159,   2,   3,    288,  40608, 496,     12,  30096,   1 },
+{  293,    -10583,   -857223,   2,  19,    300,  43800, 523,    221,  32550,   1 },
+{  307,   -190263,   -190263,   2,   3,    312,  47736, 545,     74,   8268,   1 },
+{  311,    -24343,  -4113967,   2,  11,    322,  49910, 573,     70,   2093,   1 },
+{  313,   -110255,   -110255,   2,   5,    316,  49296, 536,     85,  41554,   1 },
+{  317,     -5455,  -1969255,   2,   5,    324,  51192, 576,     17,  16038,   1 },
+{  331,   -131151,   -131151,   2,   3,    336,  55440, 574,     60,  19992,   1 },
+{  337,    -22255,  -2692855,   2,   5,    340,  57120, 614,    249,  39950,   1 },
+{  347,   -173695, -21017095,   2,   5,    360,  62280, 621,    127,  13140,   1 },
+{  349,    -74591,    -74591,   2,  11,    352,  61248, 583,     93,  45584,   1 },
+{  353,    -37703,   -942575,   2,  37,    366,  64416, 607,     89,  55083,   1 },
+{  359,    -10231,  -2956759,   2,  13,    378,  67662, 651,     37,   3591,   1 },
+{  367,    -18687,  -3158103,   2,   3,    392,  71736, 663,    358,  62524,   1 },
+{  373,   -579895,   -579895,   2,   5,    376,  69936, 679,     69,  50572,   1 },
+{  379,   -239079,   -239079,   2,   3,    384,  72576, 660,    288,  18240,   1 },
+{  383,    -16535,  -1339335,   2,   5,    390,  74490, 676,    351,   1755,   1 },
+{  389,   -112719,   -112719,   2,   3,    392,  76048, 662,    327,  61348,   1 },
+{  397,   -136295,   -136295,   2,   5,    400,  79200, 669,    211,  10600,   1 },
+{  401,      -871,  -1192399,   2,  13,    418,  83600, 700,    203,  79211,   1 },
+{  409,    -20647, -17364127,   2,  11,    434,  88536, 731,    337,  47089,   1 },
+{  419,    -25663,  -9264343,   2,  11,    432,  90288, 768,    412,  60696,   1 },
+{  421,   -149279,   -149279,   2,  13,    424,  89040, 708,    349,  48548,   1 },
+{  431,   -926863, -23171575,   2,   7,    438,  94170, 769,    270,  23871,   1 },
+{  433,   -136967,   -136967,   2,  29,    436,  94176, 725,    299,  77390,   1 },
+{  439,     -6879,  -1162551,   2,   3,    448,  98112, 759,    166,  48608,   1 },
+{  443,    -89407,  -2235175,   2,  29,    456, 100776, 789,    385,  75924,   1 },
+{  449,    -47063,  -3812103,   2,  19,    468, 104832, 801,    187,  48906,   1 },
+{  457,    -41815,  -7066735,   2,   5,    462, 105336, 830,    217, 102795,   1 },
+{  461,    -87663, -10607223,   2,   3,    468, 107640, 809,     63,  84942,   1 },
+{  463,    -73207,  -8858047,   2,  19,    470, 108570, 844,    396,  30785,   1 },
+{  467,     -3295,  -2771095,   2,   5,    480, 111840, 832,    161,  15600,   1 },
+{  479,       -87,   -570807,   2,  29,    486, 116154, 843,    375,   2187,   1 },
+{  487,     -4479,  -3766839,   2,   3,    490, 119070, 825,    412, 106085,   1 },
+{  491,     -3743,  -1081727,   2,  19,    504, 123480, 829,    410,  21924,   1 },
+{  499,   -283567, -47922823,   2,  23,    504, 125496, 886,    457, 102564,   1 },
+{  503,     -4847,  -4076327,   2,  37,    518, 130018, 844,    465,  99715,   1 },
+{  509,    -27703, -14654887,   2,  13,    528, 134112, 925,     21,  41976,   1 },
+{  521,   -175199,   -175199,   2,  19,    524, 136240, 860,    273, 115542,   1 },
+{  523,    -10119,  -1710111,   2,   3,    532, 138852, 903,     22, 118370,   1 },
+{  541,   -270023,   -270023,   2,  13,    544, 146880, 904,    117,  24208,   1 },
+{  547,    -63295, -60826495,   2,   5,    560, 152880, 957,    189,  58520,   1 },
+{  557,    -13071,  -2208999,   2,   3,    560, 155680, 966,    517, 146440,   1 },
+{  563,     -8495,  -3066695,   2,   5,    576, 161856, 970,     25, 156384,   1 },
+{  569,    -12199, -16700431,   2,  11,    576, 163584, 995,    219, 126432,   1 },
+{  571,    -27399,  -4630431,   2,   3,    588, 167580,1005,    548,   2058,   1 },
+{  577,     -4511,  -3793751,   2,  13,    588, 169344, 951,    105, 162582,   1 },
+{  587,       -39,  -3257319,   2,  13,    612, 179316,1021,    281,  44370,   1 },
+{  593,    -10495, -10085695,   2,   5,    600, 177600,1067,     19, 127500,   1 },
+{  599,    -28039,  -4738591,   2,  11,    602, 179998,1057,    310,   8127,   1 },
+{  601,   -393623,   -393623,   2,  19,    604, 181200,1011,    595,  93922,   1 },
+{  607,     -7311,  -1235559,   2,   3,    616, 186648,1022,    354, 105644,   1 },
+{  613,   -136495, -16515895,   2,   5,    640, 195840,1105,    101, 105280,   1 },
+{  617,    -91247,  -7391007,   2,  13,    624, 192192,1099,    271, 119496,   1 },
+{  619,    -15231,  -1842951,   2,   3,    640, 197760,1053,    482, 168640,   1 },
+{  631,     -8047, -11016343,   2,  13,    646, 203490,1135,    631,  72029,   1 },
+{  641,    -10743,  -3878223,   2,   3,    666, 213120,1118,    425, 192141,   1 },
+{  643,    -53247,  -6442887,   2,   3,    660, 211860,1132,    612, 152790,   1 },
+{  647,   -121543, -20540767,   2,  19,    658, 212534,1171,    638, 159565,   1 },
+{  653,     -1655,  -1391855,   2,   5,    660, 215160,1086,    601,  76890,   1 },
+{  659,   -469423, -23001727,   2,  29,    672, 221088,1190,    115, 111216,   1 },
+{  661,   -752687,   -752687,   2,  13,    664, 219120,1124,    305,  13612,   1 },
+{  673,    -43567,  -5271607,   2,  19,    690, 231840,1183,    519,  52095,   1 },
+{  677,    -31503,  -3811863,   2,   3,    680, 229840,1176,    201, 188020,   1 },
+{  683,    -42383,  -2076767,   2,  11,    696, 237336,1149,     10,  78300,   1 },
+{  691,     -7167,  -3791343,   2,   3,    704, 242880,1197,    394, 203104,   1 },
+{  701,    -93999, -11373879,   2,   3,    708, 247800,1192,     41,  23718,   1 },
+{  709,   -922727,   -922727,   2,  13,    712, 252048,1209,    361, 138484,   1 },
+{  719,   -173063,  -4326575,   2,  11,    732, 262788,1230,    628, 178974,   1 },
+{  727,   -154023, -55602303,   2,   3,    730, 264990,1277,    106, 138335,   1 },
+{  733,   -130855, -15833455,   2,   5,    740, 270840,1313,    691, 226070,   1 },
+{  739,    -29703, -15712887,   2,   3,    748, 276012,1319,    280, 268906,   1 },
+{  743,      -143,  -2234375,   2,  13,    750, 278250,1238,    285,  50625,   1 },
+{  751,     -2559,  -3503271,   2,   3,    760, 285000,1283,    498, 178220,   1 },
+{  757,   -270695,   -270695,   2,   5,    760, 287280,1234,    403,  89300,   1 },
+{  761,    -17439,  -9225231,   2,   3,    770, 292600,1334,     41,  58135,   1 },
+{  769,    -91351, -11053471,   2,  13,    790, 303360,1356,    777, 210535,   1 },
+{  773,   -102239,  -8281359,   2,  19,    780, 301080,1352,    455,  87750,   1 },
+{  787,    -20495,  -2479895,   2,   5,    800, 314400,1310,    565,  62000,   1 },
+{  797,   -486127, -12153175,   2,  29,    804, 319992,1409,    319, 224718,   1 },
+{  809,     -5631,  -2978799,   2,   3,    814, 328856,1368,    297, 121693,   1 },
+{  811,  -1057823,  -1057823,   2,  13,    816, 330480,1376,    625,  32232,   1 },
+{  821,   -176671,  -8656879,   2,  11,    828, 339480,1433,    149, 237222,   1 },
+{  823,    -15719,  -2656511,   2,  11,    826, 339486,1367,    298,  47495,   1 },
+{  827,    -46711, -63947359,   2,   7,    836, 345268,1450,    213, 199386,   1 },
+{  829,   -734831,   -734831,   2,  29,    832, 344448,1378,     85,  82784,   1 },
+{  839,   -461527, -11538175,   2,  11,    852, 356988,1477,    440, 294366,   1 },
+{  853,   -745295,   -745295,   2,   5,    856, 364656,1420,    621, 194740,   1 },
+{  857,    -50223,  -6076983,   2,   3,    860, 368080,1481,    379, 193930,   1 },
+{  859,    -66567, -11249823,   2,   3,    868, 372372,1506,    704, 207886,   1 },
+{  863,    -92135,  -7462935,   2,   5,    870, 374970,1498,    103, 231855,   1 },
+{  877,   -237295,-228040495,   2,   5,    880, 385440,1518,    275, 284680,   1 },
+{  881,   -831639,   -831639,   2,   3,    884, 388960,1487,    377, 126854,   1 },
+{  883,    -76863,  -9300423,   2,   3,    900, 396900,1539,    492, 127350,   1 },
+{  887,     -6455,  -5428655,   2,   5,    900, 398700,1500,    557, 211050,   1 },
+{  907,   -184495, -66602695,   2,   5,    920, 416760,1582,    607, 120980,   1 },
+{  911,    -56647, -20449567,   2,  37,    918, 417690,1617,    347, 407133,   1 },
+{  919,    -54543,  -9217767,   2,   3,    924, 424116,1597,    720,  30954,   1 },
+{  929,    -10671,  -5644959,   2,   3,    946, 438944,1581,    865, 216161,   1 },
+{  937,   -188095, -22759495,   2,   5,    960, 449280,1657,    105, 337440,   1 },
+{  941,    -86367, -14596023,   2,   3,    952, 447440,1649,    343,  99484,   1 },
+{  947,    -14471,  -2445599,   2,  29,    952, 450296,1554,    703, 412692,   1 },
+{  953,    -62695,  -7586095,   2,   5,    960, 456960,1647,     75,  52320,   1 },
+{  967,     -6639,  -3512031,   2,   3,    990, 478170,1617,    212, 145035,   1 },
+{  971,     -8327, -11399663,   2,  11,    988, 479180,1668,    214, 250458,   1 },
+{  977,    -75567, -12770823,   2,   3,    980, 478240,1703,    627, 143570,   1 },
+{  983,     -8327, -11399663,   2,  11,    988, 485108,1687,    482, 376922,   1 },
+{  991,    -45807, -38523687,   2,   3,    994, 492030,1703,    744, 128723,   1 },
+{  997,     -5191, -81109375,   2,  29,   1000, 498000,1739,    127, 482500,   1 },
+{ 1009,    -76999,  -9316879,   2,  13,   1030, 519120,1737,    977, 377495,   1 },
+{ 1013,   -830647, -20766175,   2,  29,   1020, 516120,1786,    767, 350370,   1 },
+{ 1019,   -116623, -33704047,   2,  13,   1044, 531396,1810,    391, 409770,   1 },
+{ 1021,    -60463, -31984927,   2,  13,   1056, 538560,1815,    475, 307824,   1 },
+{ 1031,   -210767,  -5269175,   2,  19,   1056, 543840,1723,    936, 144144,   1 },
+{ 1033,   -183367, -30989023,   2,  29,   1036, 534576,1835,    791, 114478,   1 },
+{ 1039,    -18831,  -9961599,   2,   3,   1056, 548064,1784,    202,  85008,   1 },
+{ 1049,     -9903, -13557207,   2,   3,   1064, 557536,1817,    999, 442092,   1 },
+{ 1051,    -60463, -31984927,   2,  13,   1056, 554400,1866,    145, 100848,   1 },
+{ 1061,    -18647,  -3151343,   2,  29,   1064, 563920,1744,    575, 312284,   1 },
+{ 1063,   -120031, -14523751,   2,  29,   1070, 568170,1850,    417, 400715,   1 },
+{ 1069,    -31471, -58189879,   2,  11,   1452, 775368,1819,    445, 227238,   1 },
+{ 1087,    -87319, -14756911,   2,  29,   1092, 592956,1893,    461, 410046,   1 },
+{ 1091,   -233951, -18950031,   2,  37,   1116, 608220,1896,    771, 513918,   1 },
+{ 1093,    -82255, -29694055,   2,   5,   1100, 600600,1859,    639, 472450,   1 },
+{ 1097,    -18903,  -9999687,   2,   3,   1100, 602800,1879,    131, 158950,   1 },
+{ 1103,    -88135, -14894815,   2,   5,   1106, 609406,1915,    353, 405349,   1 },
+{ 1109,    -19823, -14450967,   2,  43,   1116, 618264,1923,    853, 215946,   1 },
+{ 1117,   -288871,-180544375,   2,  11,   1120, 624960,1950,     53, 316400,   1 },
+{ 1123,   -154855,-260311255,   2,   5,   1140, 639540,1917,    749, 440610,   1 },
+{ 1129,    -44143, -60431767,   2,  11,   1140, 642960,2012,    813, 619590,   1 },
+{ 1151,    -20423, -10803767,   2,  13,   1166, 670450,1943,    825, 622061,   1 },
+{ 1153,   -435823,-157332103,   2,  37,   1210, 696960,2009,    925, 526955,   1 },
+{ 1163,   -246055, -29772655,   2,   5,   1180, 685580,2042,    151, 166970,   1 },
+{ 1171,   -201063, -33979647,   2,   3,   1176, 687960,2060,     68, 641508,   1 },
+{ 1181,   -138847, -50123767,   2,  43,   1188, 700920,2098,    665, 486486,   1 },
+{ 1187,    -67879,-149944711,   2,   7,   1196, 709228,2063,    124, 340262,   1 },
+{ 1193,    -23559,  -8504799,   2,   3,   1206, 718776,2022,    847, 390141,   1 },
+{ 1201,    -43087, -58986103,   2,  11,   1216, 729600,2134,   1181, 728992,   1 },
+{ 1213,   -370255,-355815055,   2,   5,   1300, 787800,2086,    143, 480350,   1 },
+{ 1217,    -55655,  -6734255,   2,   5,   1220, 741760,2020,    767, 735050,   1 },
+{ 1223,    -23935, -23001535,   2,   5,   1230, 751530,2141,     95, 591015,   1 },
+{ 1229,    -45791,  -7738679,   2,  29,   1232, 756448,2044,   1079, 461384,   1 },
+{ 1231,    -11103, -24526527,   2,   3,   1242, 763830,2146,    656, 358317,   1 },
+{ 1237,   -569095,-205443295,   2,   5,   1240, 766320,2156,   1005,  62620,   1 },
+{ 1249,   -422647,-152575567,   2,  43,   1260, 786240,2177,    595, 423990,   1 },
+{ 1259,   -148343, -12015783,   2,  13,   1272, 800088,2149,    601, 491628,   1 },
+{ 1277,     -9903, -21875727,   2,   3,   1288, 821744,2208,    707, 611156,   1 },
+{ 1279,    -23519,  -3974711,   2,  29,   1288, 823032,2080,    957, 146188,   1 },
+{ 1283,    -72583,-160335847,   2,   7,   1288, 825608,2233,    403, 488796,   1 },
+{ 1289,     -4791,  -6558879,   2,   3,   1292, 832048,2149,    779, 421838,   1 },
+{ 1291,    -99543, -16822767,   2,   3,   1316, 848820,2220,    424,  40138,   1 },
+{ 1297,    -73655,  -8912255,   2,   5,   1300, 842400,2162,    971, 229450,   1 },
+{ 1301,    -28047, -14836863,   2,   3,   1320, 858000,2227,   1055,  73260,   1 },
+{ 1303,   -249663, -30209223,   2,   3,   1320, 859320,2273,    758, 830940,   1 },
+{ 1307,   -506543, -12663575,   2,  29,   1320, 861960,2205,     29,  21780,   1 },
+{ 1319,     -8903, -12188207,   2,  29,   1330, 876470,2214,    809, 387695,   1 },
+{ 1321,   -240103, -40577407,   2,  19,   1414, 933240,2320,   1327, 382487,   1 },
+{ 1327,    -22615, -30959935,   2,   5,   1330, 881790,2319,    261, 629755,   1 },
+{ 1361,    -66567, -35213943,   2,   3,   1364, 927520,2376,     17, 759066,   1 },
+{ 1367,     -3935,  -7275815,   2,   5,   1386, 946638,2259,     17, 104643,   1 },
+{ 1373,    -32455, -31189255,   2,   5,   1380, 946680,2391,    559, 531990,   1 },
+{ 1381,    -33407, -61769543,   2,  11,   1428, 985320,2266,    127,   4998,   1 },
+{ 1399,    -85551, -71948391,   2,   3,   1414, 988386,2380,    110, 687911,   1 },
+{ 1409,   -192679, -32562751,   2,  19,   1414, 995456,2451,    377, 897183,   1 },
+{ 1423,    -20039,  -3386591,   2,  29,   1428,1015308,2341,    473, 270606,   1 },
+{ 1427,   -390895, -47298295,   2,   5,   1440,1026720,2505,    673,  48240,   1 },
+{ 1429,    -68167, -93320623,   2,  11,   1596,1139544,2524,    983, 473214,   1 },
+{ 1433,     -8207,  -5129375,   2,  29,   1440,1031040,2326,    677, 464400,   1 },
+{ 1439,     -4631,  -6339839,   2,  11,   1444,1038236,2352,    808, 392046,   1 },
+{ 1447,     -1983, -56636463,   2,   3,   1456,1052688,2540,    598,  69160,   1 },
+{ 1451,   -337111, -56971759,   2,  23,   1456,1055600,2457,   1213,1035944,   1 },
+{ 1453,   -375055,-315421255,   2,   5,   1460,1059960,2490,   1235, 898630,   1 },
+{ 1459,    -24663, -54480567,   2,   3,   1472,1073088,2558,    226, 140576,   1 },
+{ 1471,     -6999, -15460791,   2,   3,   1518,1115730,2484,    390, 820479,   1 },
+{ 1481,    -26279, -19157391,   2,  11,   1494,1105560,2518,    979, 859797,   1 },
+{ 1483,   -365727, -44252967,   2,   3,   1500,1111500,2577,    124, 261750,   1 },
+{ 1487,   -142063, -41056207,   2,  19,   1494,1110042,2595,    158, 463887,   1 },
+{ 1489,   -120031,-221937319,   2,  29,   1498,1114512,2538,    477, 250915,   1 },
+{ 1493,     -2407, -37609375,   2,  29,   1500,1119000,2601,   1403, 489750,   1 },
+{ 1499,   -299167,-107999287,   2,  11,   1512,1132488,2657,    604, 327348,   1 },
+{ 1511,    -79607, -13453583,   2,  11,   1526,1152130,2518,    108, 997241,   1 },
+{ 1523,   -273151, -46162519,   2,  29,   1540,1171940,2653,    117, 467390,   1 },
+{ 1531,    -48567, -25691943,   2,   3,   1540,1178100,2631,    336, 476630,   1 },
+{ 1543,     -6023,  -8245487,   2,  19,   1558,1201218,2538,   1278, 985435,   1 },
+{ 1549,    -95903, -16207607,   2,  29,   1596,1235304,2586,    711,   8778,   1 },
+{ 1553,    -73663, -46039375,   2,  19,   1560,1210560,2714,    125,  95940,   1 },
+{ 1559,   -252367, -42650023,   2,  43,   1568,1221472,2716,    800, 513520,   1 },
+{ 1567,   -104079, -12593559,   2,   3,   1580,1237140,2628,   1322,  60830,   1 },
+{ 1571,    -94303,-174366247,   2,  11,   1584,1243440,2713,    716, 460152,   1 },
+{ 1579,    -10551, -23307159,   2,   3,   1656,1306584,2685,    986, 348588,   1 },
+{ 1583,     -1007,  -2828663,   2,  19,   1590,1257690,2619,     30,1194885,   1 },
+{ 1597,   -107495, -90403295,   2,   5,   1600,1276800,2619,   1535, 815200,   1 },
+{ 1601,   -279071, -22604751,   2,  13,   1608,1286400,2723,    505, 565212,   1 },
+{ 1607,   -431215, -72875335,   2,   5,   1610,1292830,2821,    175, 900795,   1 },
+{ 1609,   -145447,-408560623,   2,  37,   1612,1296048,2791,   1401, 895466,   1 },
+{ 1613,    -37543,-105458287,   2,  11,   1620,1305720,2847,   1435, 859410,   1 },
+{ 1619,   -180791, -14644071,   2,  13,   1632,1320288,2720,    493, 880464,   1 },
+{ 1621,     -2279,  -6401711,   2,  43,   2968,2404080,2695,    499, 292348,   1 },
+{ 1627,   -500095, -60511495,   2,   5,   1640,1333320,2848,    649, 394420,   1 },
+{ 1637,    -42095, -15196295,   2,   5,   1656,1354608,2727,    419,1305756,   1 },
+{ 1657,   -352855, -42695455,   2,   5,   1660,1374480,2874,     91,1010110,   1 },
+{ 1663,   -119199, -20144631,   2,   3,   1680,1396080,2804,    782,1240680,   1 },
+{ 1667,    -92695, -77956495,   2,   5,   1680,1399440,2926,    973, 435960,   1 },
+{ 1669,   -160927, -85130383,   2,  13,   1804,1504536,2925,    459, 910118,   1 },
+{ 1693,   -229855, -27812455,   2,   5,   1700,1438200,2901,    645,1199350,   1 },
+{ 1697,    -56271,  -9509799,   2,   3,   1708,1448384,2806,    557, 313418,   1 },
+{ 1699,    -56271,  -9509799,   2,   3,   1708,1450092,2806,    364, 393694,   1 },
+{ 1709,   -380263,-703106287,   2,  13,   1716,1465464,2954,    563,  38610,   1 },
+{ 1721,   -377807, -30602367,   2,  37,   1728,1486080,2945,     53, 616032,   1 },
+{ 1723,   -325855, -39428455,   2,   5,   1740,1498140,2967,   1127,1144050,   1 },
+{ 1733,    -69487, -43429375,   2,  11,   1740,1506840,2995,    631, 573330,   1 },
+{ 1741,    -63751,-140825959,   2,  37,   3680,3201600,2966,   1737,1433360,   1 },
+{ 1747,   -385527, -46648767,   2,   3,   1760,1536480,3019,     22,1371920,   1 },
+{ 1753,    -73223, -12374687,   2,  37,   1778,1557528,2915,    643,1286383,   1 },
+{ 1759,   -125679, -21239751,   2,   3,   1764,1550556,2972,   1024,1306242,   1 },
+{ 1777,   -279655, -33838255,   2,   5,   1780,1580640,3048,   1465,  20470,   1 },
+{ 1783,   -396327, -47955567,   2,   3,   1800,1603800,3081,    884, 917100,   1 },
+{ 1787,    -27151, -26092111,   2,  19,   1800,1607400,3044,   1334, 706500,   1 },
+{ 1789,   -143767, -76052743,   2,  13,   1804,1612776,3131,    891, 855998,   1 },
+{ 1801,     -2407, -68746327,   2,  29,   1820,1638000,3140,    103, 452270,   1 },
+{ 1811,  -2047687, -51192175,   2,  19,   1824,1650720,3138,    934,1489296,   1 },
+{ 1823,    -11735, -11277335,   2,   5,   1830,1667130,3076,    473,1549095,   1 },
+{ 1831,   -106719, -89750679,   2,   3,   1834,1678110,3080,   1076,1436939,   1 },
+{ 1847,       -55, -50793655,   2,   5,   1860,1716780,3187,    511, 614730,   1 },
+{ 1861,    -71159,-131572991,   2,  11,   1932,1796760,3101,    693,  28014,   1 },
+{ 1867,   -925303,-156376207,   2,  29,   1876,1750308,3292,    145,1655570,   1 },
+{ 1871,  -1019959, -49977991,   2,  29,   1884,1761540,3224,   1407,1557126,   1 },
+{ 1873,   -640495,-538656295,   2,   5,   1904,1782144,3239,   1259, 855848,   1 },
+{ 1877,   -286887, -34713327,   2,   3,   1880,1763440,3200,    845, 343100,   1 },
+{ 1879,    -83863, -44363527,   2,  13,   1892,1776588,3233,    845,  12298,   1 },
+{ 1889,    -35431, -48505039,   2,  11,   1900,1793600,3252,    933,1741350,   1 },
+{ 1901,    -27399, -60524391,   2,   3,   1932,1835400,3275,    715,1625778,   1 },
+{ 1907,    -15095, -14506295,   2,   5,   1920,1829760,3229,    251,1316160,   1 },
+{ 1913,   -294535, -49776415,   2,   5,   1918,1833608,3297,   1279,1082711,   1 },
+{ 1931,     -6383, -41878863,   2,  13,   1944,1875960,3303,   1001,1076004,   1 },
+{ 1933,   -103655, -12542255,   2,   5,   1940,1874040,3287,    813, 623710,   1 },
+{ 1949,   -195807, -23692647,   2,   3,   1960,1909040,3285,    113, 553700,   1 },
+{ 1951,   -173487, -29319303,   2,   3,   1960,1911000,3303,    446, 510580,   1 },
+{ 1973,    -31071, -16436559,   2,   3,   1980,1952280,3304,    765,1549350,   1 },
+{ 1979,   -385799, -31249719,   2,  37,   1992,1970088,3346,   1881,1660332,   1 },
+{ 1987,    -96095, -11627495,   2,   5,   2000,1986000,3377,    949,1669000,   1 },
+{ 1993,   -126695, -15330095,   2,   5,   2000,1992000,3389,   1295,1381000,   1 },
+{ 1997,    -96095, -11627495,   2,   5,   2000,1996000,3398,   1207,1361000,   1 },
+{ 1999,   -222623, -37623287,   2,  19,   2002,1999998,3365,    430, 865865,   1 },
+{ 2003,   -239695, -86529895,   2,   5,   2016,2018016,3486,   1033, 789264,   1 },
+{ 2011,   -105159, -17771871,   2,   3,   2016,2026080,3382,   1624, 763056,   1 },
+{ 2017,    -55135, -75479815,   2,   5,   2090,2106720,3491,   1763, 107635,   1 },
+{ 2027,   -165895,-139517695,   2,   5,   2040,2066520,3552,   1995, 823140,   1 },
+{ 2029,   -101047,-223212823,   2,  37,   2208,2238912,3569,    813,  51888,   1 },
+{ 2039,     -1351,-176063671,   2,   7,   2052,2090988,3463,   1936,2020194,   1 },
+{ 2053,    -97655, -11816255,   2,   5,   2060,2113560,3497,   1677,1305010,   1 },
+{ 2063,   -198095, -23969495,   2,   5,   2080,2144480,3508,    925, 720720,   1 },
+{ 2069,    -63191, -10679279,   2,  29,   2072,2142448,3518,   1493,1449364,   1 },
+{ 2081,    -66407, -23972927,   2,  11,   2088,2171520,3538,    147, 232812,   1 },
+{ 2083,   -258591, -43701879,   2,   3,   2100,2186100,3544,    278, 610050,   1 },
+{ 2087,    -18823,-275587543,   2,   7,   2090,2179870,3584,    839,1054405,   1 },
+{ 2089,   -266807, -32283647,   2,  37,   2100,2192400,3511,    311, 435750,   1 },
+{ 2099,   -193999,-102625471,   2,  13,   2112,2215488,3651,   1525,2159520,   1 },
+{ 2111,   -378991, -64049479,   2,  37,   2114,2230270,3639,   1993,2022041,   1 },
+{ 2113,    -90215, -15246335,   2,   5,   2142,2261952,3610,    263, 328797,   1 },
+{ 2129,    -38751, -20499279,   2,   3,   2134,2270576,3605,    319, 287023,   1 },
+{ 2131,   -170319, -28783911,   2,   3,   2156,2296140,3581,    370,2239006,   1 },
+{ 2137,   -163015, -27549535,   2,   5,   2142,2287656,3613,   1659,2209473,   1 },
+{ 2141,   -597143, -48368583,   2,  37,   2148,2298360,3659,    363,1826874,   1 },
+{ 2143,      -247, -32189287,   2,  13,   2166,2319786,3772,   1207,1762041,   1 },
+{ 2153,   -170319, -28783911,   2,   3,   2156,2319856,3624,   1609, 527142,   1 },
+{ 2161,    -52519,-147525871,   2,  29,   2184,2358720,3648,    683,2327052,   1 },
+{ 2179,     -7271,  -9953999,   2,  11,   2204,2400156,3687,    752,2183062,   1 },
+{ 2203,   -248511, -30069831,   2,   3,   2220,2444220,3723,    910, 926850,   1 },
+{ 2207,  -2240743,-271129903,   2,  29,   2210,2437630,3881,    561,1963585,   1 },
+{ 2213,   -538743, -65187903,   2,   3,   2220,2455320,3794,    291, 589410,   1 },
+{ 2221,   -506623,-426069943,   2,  13,   2296,2548560,3817,   1551,2046884,   1 },
+{ 2237,    -71751, -37956279,   2,   3,   2244,2508792,3773,   1031, 968286,   1 },
+{ 2239,    -51159, -27063111,   2,   3,   2244,2511036,3809,    832,1132098,   1 },
+{ 2243,  -1101503, -89221743,   2,  13,   2256,2528976,3866,   1183,   3384,   1 },
+{ 2251,    -42791, -58580879,   2,   7,   2280,2565000,3816,   1803, 717060,   1 },
+{ 2267,  -1564823,-126750663,   2,  13,   2280,2583240,3937,   1563,1346340,   1 },
+{ 2269,    -84839, -30626879,   2,  43,   2400,2721600,3830,   1021, 632400,   1 },
+{ 2273,    -89407, -55879375,   2,  29,   2280,2590080,3883,   2229,1145700,   1 },
+{ 2281,    -96967, -51295543,   2,  13,   2288,2608320,3900,    523,2401256,   1 },
+{ 2287,   -301503, -50954007,   2,   3,   2296,2624328,3890,   1592,1068788,   1 },
+{ 2293,   -413047, -69804943,   2,  29,   2296,2631216,3944,    473, 790972,   1 },
+{ 2297,    -51063, -31914375,   2,   3,   2310,2651880,3903,   1375,2569875,   1 },
+{ 2309,   -572279, -46354599,   2,  37,   2316,2672664,3898,   1205,1075782,   1 },
+{ 2311,    -56607,-125044863,   2,   3,   2346,2709630,4002,   2186,1709061,   1 },
+{ 2333,    -40055, -38492855,   2,   5,   2340,2728440,4001,   1899,1664910,   1 },
+{ 2339,   -372479, -30170799,   2,  37,   2352,2749488,3998,   2227,2070936,   1 },
+{ 2341,   -319783,-169165207,   2,  29,   2508,2934360,4079,   1787,2097942,   1 },
+{ 2347,    -39743, -54408167,   2,  11,   2356,2763588,3999,   1968,1294622,   1 },
+{ 2351,   -205231, -74088391,   2,  13,   2358,2770650,4027,   1403, 173313,   1 },
+{ 2357,  -1889263, -47231575,   2,  29,   2376,2798928,4007,   2133, 588060,   1 },
+{ 2371,   -357303,-189013287,   2,   3,   2376,2815560,4130,   1800,1982772,   1 },
+{ 2377,   -602815,-101875735,   2,   5,   2394,2844072,4107,    575,1897245,   1 },
+{ 2381,  -1360823,-110226663,   2,  37,   2388,2841720,4104,    837,2410686,   1 },
+{ 2383,    -74335,-101764615,   2,   5,   2394,2851254,4121,     97,2160585,   1 },
+{ 2389,  -1544983,-557738863,   2,  11,   2400,2865600,4105,    593,2751600,   1 },
+{ 2393,     -1943, -30359375,   2,  29,   2400,2870400,4122,    393,2634000,   1 },
+{ 2399,   -519607,-187578127,   2,  11,   2412,2891988,4190,   1488, 334062,   1 },
+{ 2411,   -331799, -26875719,   2,  13,   2424,2920920,4117,   2135,2461572,   1 },
+{ 2417,    -73551, -38908479,   2,   3,   2420,2923360,4127,   1277,1692790,   1 },
+{ 2423,      -815, -48124935,   2,   5,   2430,2942730,4134,   1957, 579555,   1 },
+{ 2437,   -688039,-430024375,   2,  11,   2460,2996280,4180,    347,1578090,   1 },
+{ 2441,   -139647, -73873263,   2,   3,   2464,3006080,4171,   1989, 582736,   1 },
+{ 2447,  -1497463,-253071247,   2,  11,   2450,2996350,4287,   1872,2022475,   1 },
+{ 2459,   -869999, -70469919,   2,  13,   2472,3038088,4177,   1527,1934340,   1 },
+{ 2467,   -534063, -64621623,   2,   3,   2480,3057840,4199,   2082, 536920,   1 },
+{ 2473,   -319783,-169165207,   2,  29,   2508,3099888,4306,   1067,   8778,   1 },
+{ 2477,    -22759, -63930031,   2,  11,   2484,3075192,4219,    465,2301426,   1 },
+{ 2503,   -329335, -55657615,   2,   5,   2506,3135006,4264,   1727,1254253,   1 },
+{ 2521,    -96367,-131926423,   2,  29,   2622,3303720,4354,   1879, 667299,   1 },
+{ 2531,  -1163807, -29095175,   2,  19,   2544,3218160,4361,   1804,2832744,   1 },
+{ 2539,   -271191, -45831279,   2,   3,   2548,3233412,4354,   1876,2330146,   1 },
+{ 2543,     -4303, -67234375,   2,  13,   2550,3241050,4334,    495,1521075,   1 },
+{ 2549,   -132407, -47798927,   2,  11,   2556,3256344,4403,   1839,2651850,   1 },
+{ 2551,   -292143, -49372167,   2,   3,   2576,3284400,4363,   2342,2721544,   1 },
+{ 2557,     -5855, -29515055,   2,   5,   2660,3399480,4393,   2513,2288930,   1 },
+{ 2579,     -6071, -39831831,   2,  13,   2592,3341088,4429,   1539,2938032,   1 },
+{ 2591,  -3409303, -85232575,   2,  19,   2604,3372180,4444,   1038,3251094,   1 },
+{ 2593,   -211895, -25639295,   2,   5,   2600,3369600,4450,   2155,1522300,   1 },
+{ 2609,    -56247,-124249623,   2,   3,   2622,3419088,4488,   1055,1359507,   1 },
+{ 2617,   -272591, -98405351,   2,  11,   2620,3426960,4445,   2395, 643210,   1 },
+{ 2621,    -86567, -63107343,   2,  13,   2628,3442680,4504,     31,3023514,   1 },
+{ 2633,   -939263, -76080303,   2,  13,   2640,3474240,4510,   1189,1904760,   1 },
+{ 2647,  -1627567,-196935607,   2,  29,   2650,3505950,4610,    601, 128525,   1 },
+{ 2657,   -158871, -26849199,   2,   3,   2660,3532480,4544,    131,2557590,   1 },
+{ 2659,   -164687, -19927127,   2,  37,   2680,3561720,4544,   1219,1400300,   1 },
+{ 2663,   -113927, -95812607,   2,  11,   2670,3553770,4588,   1570,1384395,   1 },
+{ 2671,    -87231, -46145199,   2,   3,   2684,3583140,4587,   1194,1601006,   1 },
+{ 2677,   -191623,-538269007,   2,  37,   3328,4452864,4543,   2209,2204800,   1 },
+{ 2683,   -807655, -97726255,   2,   5,   2700,3620700,4601,    261,2965950,   1 },
+{ 2687,    -68063, -93178247,   2,  29,   2698,3623414,4633,     31,   1349,   1 },
+{ 2689,  -1892743,-683280223,   2,  29,   2710,3642240,4614,   2085,2163935,   1 },
+{ 2693,     -7543,-117859375,   2,  19,   2700,3634200,4639,   1269, 687150,   1 },
+{ 2699,    -47927,-134626943,   2,  11,   2704,3647696,4604,    106,3129880,   1 },
+{ 2707,   -103655, -87173855,   2,   5,   2716,3674748,4601,    983,2934638,   1 },
+{ 2711,   -175487, -63350807,   2,  13,   2718,3682890,4693,   1931, 775989,   1 },
+{ 2713,   -575495, -69634895,   2,   5,   2720,3688320,4689,    527, 654160,   1 },
+{ 2719,    -94551,-265593759,   2,   3,   2730,3710070,4611,   2684,  99645,   1 },
+{ 2729,   -334927, -96793903,   2,  43,   2736,3731904,4670,   1957,3128616,   1 },
+{ 2731,    -66583, -91152127,   2,  11,   2736,3734640,4682,   1782, 452808,   1 },
+{ 2741,    -86159, -14560871,   2,  29,   2744,3759280,4700,   1551,3746932,   1 },
+{ 2749,    -89687, -47444423,   2,  13,   2772,3808728,4754,   1181,2634786,   1 },
+{ 2753,    -24807, -54798663,   2,   3,   2760,3797760,4720,   1107, 335340,   1 },
+{ 2767,   -255287, -43143503,   2,  29,   2772,3833676,4777,    877,3782394,   1 },
+{ 2777,    -84935, -81622535,   2,   5,   2790,3872520,4808,   2671,1315485,   1 },
+{ 2789,   -311511, -52645359,   2,   3,   2800,3903200,4793,   1757,1281000,   1 },
+{ 2791,   -180087, -95266023,   2,   3,   2794,3897630,4788,   2518,3605657,   1 },
+{ 2797,    -81743,-229616087,   2,  43,   2808,3925584,4781,   1475,1818180,   1 },
+{ 2801,    -36447, -80511423,   2,   3,   2806,3928400,4813,   1779,1042429,   1 },
+{ 2803,   -447807, -54184647,   2,   3,   2820,3950820,4794,   2584,2096670,   1 },
+{ 2819,   -350831, -28417311,   2,  13,   2832,3990288,4853,   1375,3575400,   1 },
+{ 2833,   -414695, -50178095,   2,   5,   2840,4021440,4898,   2347,1574780,   1 },
+{ 2837,   -414695, -50178095,   2,   5,   2840,4027120,4910,    231,1844580,   1 },
+{ 2843,       -95, -12380495,   2,   5,   2888,4103848,4947,     87, 680124,   1 },
+{ 2851,   -399783, -67563327,   2,   3,   2856,4069800,4890,   1272, 469812,   1 },
+{ 2857,   -145151, -17563271,   2,  37,   2860,4084080,4899,    897,2555410,   1 },
+{ 2861,    -9903,-2771265423,   2,   3,   3864,5525520,3552,   3823,3904572,   1 },
+{ 2879,   -646207,-341843503,   2,  29,   2882,4147198,5032,    753,3491543,   1 },
+{ 2887,  -1648207,-278546983,   2,  11,   2898,4181814,5030,   2012,1702575,   1 },
+{ 2897,     -5583,-159456063,   2,   3,   2912,4216576,4981,   1227,2383472,   1 },
+{ 2903,   -484255,-174816055,   2,   5,   2916,4231116,5011,   1811,2159298,   1 },
+{ 2909,    -12407, -81402327,   2,  19,   2916,4239864,5032,   2551,2984526,   1 },
+{ 2917,   -238895, -28906295,   2,   5,   2920,4257360,5025,   2405,4022300,   1 },
+{ 2927,   -122735, -89473815,   2,   5,   2934,4292442,5062,   2061,1568223,   1 },
+{ 2939,     -2279,  -6401711,   2,  43,   2968,4359992,5089,     42,1423156,   1 },
+{ 2953,   -272215,-503325535,   2,   5,   2970,4383720,5047,   1531,3865455,   1 },
+{ 2957,   -259599, -43872231,   2,   3,   2968,4386704,5069,   1509,4189332,   1 },
+{ 2963,  -1660879, -81383071,   2,  11,   2976,4407456,5111,    384,2837616,   1 },
+{ 2969,   -505623, -61180383,   2,   3,   2980,4422320,5089,    999,4346330,   1 },
+{ 2971,    -26351, -74019959,   2,  13,   3016,4478760,5066,   1031,2740036,   1 },
+{ 2999,   -118639, -62760031,   2,  29,   3014,4517986,5170,   2281,3117983,   1 },
+{ 3001,   -295279,-248329639,   2,  19,   3010,4515000,5122,     77,3384745,   1 }
+#endif
+};
+
+static const modpoly_disc_info *
+get_disc_info_for_level(long L)
+{
+  long imin, imax, imid;
+  if (L < 5)
+    pari_err_BUG("get_disc_info_for_level");
+
+  if (L > 3001)
+    pari_err_IMPL("Do not yet have discriminants for L > 3001");
+
+  /* Binary search for L. */
+  imin = 0;
+  imax = DISC_TABLE_LENGTH;
+  while (imin < imax) {
+    imid = (imin + imax) / 2;
+    if (DISC_TABLE[imid].L < L)
+      imin = imid + 1;
+    else
+      imax = imid;
+  }
+  if (imax != imin || DISC_TABLE[imin].L != L) {
+    pari_err_BUG("get_disc_info_for_level: "
+                 "Did not find given level in discriminant table "
+                 "(are you sure it's prime?)");
+  }
+  return &DISC_TABLE[imin];
+}
+
+
+static const modpoly_disc_info *
+discriminant_with_classno_at_least(
+  long *D, ulong *u, ulong *v, /* GEN *alpha, GEN *beta, */ ulong L)
+{
+  const modpoly_disc_info *dinfo = 0;
+  pari_sp av = avma;
+
+  dinfo = get_disc_info_for_level(L);
+  *D = dinfo->D1;
+
+  (void) corediscs(*D, u);
+  avma = av;
+
+  *v = (-*D % 8 == 7) ? 2 : 1;
+  dbg_printf2(2, "-D %% 8 == %lu, selecting vsqr = %lu",
+              -*D % 8, *v * *v);
+  return dinfo;
+}
diff --git a/src/basemath/prime.c b/src/basemath/prime.c
index 931abf7..acd5753 100644
--- a/src/basemath/prime.c
+++ b/src/basemath/prime.c
@@ -91,18 +91,18 @@ Fl_MR_Jaeschke_ok(Fl_MR_Jaeschke_t *S, ulong c)
 static int
 bad_for_base(MR_Jaeschke_t *S, GEN a)
 {
-  long r, lim, av = avma;
+  pari_sp av = avma;
+  long r;
   GEN c2, c = Fp_pow(a, S->t1, S->n);
 
   if (is_pm1(c) || equalii(S->t, c)) return 0;
 
-  lim = stack_lim(av,1);
   /* go fishing for -1, not for 1 (saves one squaring) */
   for (r = S->r1 - 1; r; r--) /* r1 - 1 squarings */
   {
     c2 = c; c = remii(sqri(c), S->n);
     if (equalii(S->t, c)) return MR_Jaeschke_ok(S, c2);
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"Rabin-Miller");
       c = gerepileuptoint(av, c);
@@ -139,7 +139,7 @@ millerrabin(GEN n, long k)
   if (typ(n) != t_INT) pari_err_TYPE("millerrabin",n);
   if (signe(n)<=0) return 0;
   /* If |n| <= 3, check if n = +- 1 */
-  if (lgefint(n)==3 && (ulong)(n[2])<=3) return (n[2] != 1);
+  if (lgefint(n)==3 && uel(n,2)<=3) return uel(n,2) != 1;
 
   if (!mod2(n)) return 0;
   init_MR_Jaeschke(&S, n); av2 = avma;
@@ -231,7 +231,7 @@ MR_Jaeschke(GEN n, long k)
   long i;
   MR_Jaeschke_t S;
 
-  if (lgefint(n) == 3) return Fl_MR_Jaeschke((ulong)n[2], k);
+  if (lgefint(n) == 3) return Fl_MR_Jaeschke(uel(n,2), k);
 
   if (!mod2(n)) return 0;
   if      (k == 16) { p = pr+13; k = 4; } /* 2,13,23,1662803 */
@@ -257,7 +257,7 @@ MR_Jaeschke(GEN n, long k)
 static GEN
 LucasMod(GEN n, ulong P, GEN N)
 {
-  pari_sp av = avma, lim = stack_lim(av, 1);
+  pari_sp av = avma;
   GEN nd = int_MSW(n);
   long i, m = *nd, j = 1+bfffo((ulong)m);
   GEN v = utoipos(P), v1 = utoipos(P*P - 2);
@@ -279,7 +279,7 @@ LucasMod(GEN n, ulong P, GEN N)
       }
       v = modii(v, N);
       v1= modii(v1,N);
-      if (low_stack(lim,stack_lim(av,1)))
+      if (gc_needed(av,1))
       {
         if(DEBUGMEM>1) pari_warn(warnmem,"LucasMod");
         gerepileall(av, 2, &v,&v1);
@@ -348,7 +348,7 @@ uislucaspsp(ulong n)
 static int
 IsLucasPsP(GEN N)
 {
-  pari_sp av = avma, lim = stack_lim(av, 1);
+  pari_sp av = avma;
   GEN N_2, m, z;
   long i, v;
   ulong b;
@@ -369,7 +369,7 @@ IsLucasPsP(GEN N)
     if (!signe(z)) return 1;
     z = modii(subis(sqri(z), 2), N);
     if (equaliu(z, 2)) return 0;
-    if (low_stack(lim,stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"IsLucasPsP");
       z = gerepileupto(av, z);
@@ -513,7 +513,7 @@ BPSW_psp(GEN N)
 
   if (typ(N) != t_INT) pari_err_TYPE("BPSW_psp",N);
   if (signe(N) <= 0) return 0;
-  if (lgefint(N) == 3) return uisprime((ulong)N[2]);
+  if (lgefint(N) == 3) return uisprime(uel(N,2));
   if (!mod2(N)) return 0;
 #ifdef LONG_IS_64BIT
   /* 16294579238595022365 = 3*5*7*11*13*17*19*23*29*31*37*41*43*47*53
@@ -563,7 +563,7 @@ BPSW_psp_nosmalldiv(GEN N)
   long l = lgefint(N);
   int k;
 
-  if (l == 3) return uisprime_661((ulong)N[2]);
+  if (l == 3) return uisprime_661(uel(N,2));
   av = avma;
   /* N large: test for pure power, rarely succeeds, but requires < 1% of
    * compositeness test times */
@@ -632,7 +632,7 @@ pl831(GEN N, GEN p)
     if (!equalii(g,N)) return 0;
   }
 }
-/* Assume x BPSW pseudoprime. Return gen_0 if not prime, and a primality
+/* Assume x BPSW pseudoprime. Return NULL if not prime, and a primality
  * certificate otherwise */
 static GEN isprimePL(GEN N);
 static GEN
@@ -640,7 +640,7 @@ check_prime(GEN p)
 {
   if (BPSW_isprime_small(p)) return gen_1;
   if (expi(p) <= 250) return isprimePL(p);
-  return isprimeAPRCL(p)? gen_2: gen_0;
+  return isprimeAPRCL(p)? gen_2: NULL;
 }
 /* initialize Selfridge / Pocklington-Lehmer test, return 0
  * if proven composite */
@@ -670,7 +670,7 @@ isprimePL(GEN N)
   pari_sp ltop = avma;
   long i, l;
   int eps;
-  GEN C, P, W, R, F, f;
+  GEN P, W, R, F, f;
 
   if (typ(N) != t_INT) pari_err_TYPE("isprimePL",N);
   eps = cmpis(N,2);
@@ -683,86 +683,79 @@ isprimePL(GEN N)
     err_printf("Pocklington-Lehmer: N-1 factored up to %Ps! (%.3Ps%%)\n", f, divri(itor(f,LOWDEFAULTPREC), N));
     err_printf("Pocklington-Lehmer: N-1 smooth enough! Computing certificate\n");
   }
-  C = cgetg(4,t_MAT); l = lg(F);
-  gel(C,1) = P = cgetg(l,t_COL);
-  gel(C,2) = W = cgetg(l,t_COL);
-  gel(C,3) = R = cgetg(l,t_COL);
+  l = lg(F);
+  P = cgetg(l,t_COL);
+  W = cgetg(l,t_COL);
+  R = cgetg(l,t_COL);
   for(i=1; i<l; i++)
   {
     GEN p = gel(F,i);
     ulong witness = pl831(N,p);
 
     if (!witness) { avma = ltop; return gen_0; }
-    gel(P,i) = icopy(p);
+    gel(P,i) = p;
     gel(W,i) = utoipos(witness);
     gel(R,i) = check_prime(p);
-    if (gel(R,i) == gen_0)
+    if (!gel(R,i))
     { /* composite in prime factorisation ! */
       err_printf("Not a prime: %Ps", p);
       pari_err_BUG("isprimePL [false prime number]");
     }
   }
-  return gerepileupto(ltop,C);
+  return gerepilecopy(ltop, mkmat3(P,W,R));
 }
 
-/* F is a vector of BPSW pseudoprimes of N. For each of then, find a PL witness,
- * then prove primality. If (avoid_last) do not apply test to last entry */
+/* F is a vector whose n first entries are primes. For each of them,
+ * find a PL witness */
 static long
-isprimeSelfridge(GEN N, GEN F, int avoid_last)
+isprimeSelfridge(GEN N, GEN F, long n)
 {
-  long i, l = lg(F);
-  if (avoid_last) l--;
-  for(i = 1; i < l; i++)
-  {
-    GEN p = gel(F,i);
-    if (! pl831(N, p)) return 0;
-    if (DEBUGLEVEL>3)
-      err_printf("Pocklington-Lehmer: recursively proving primality of p = %Ps\n", p);
-    if (!BPSW_isprime(p)) return 0;
-  }
+  long i;
+  for(i = 1; i <= n; i++)
+    if (! pl831(N, gel(F,i))) return 0;
   return 1;
 }
 
-/* assume N a BPSW pseudoprime, in particular, it is odd > 2 */
-long
-BPSW_isprime(GEN N)
+/* BPSW_psp(N) && !BPSW_isprime_small(N). Prove N prime  */
+static long
+BPSW_isprime_big(GEN N)
 {
-  pari_sp av = avma;
-  long l, res;
-  ulong B;
-  GEN fa, P, E, p, U, F, N_1;
+  ulong B = minuu(1UL<<19, maxprime());
+  GEN E, p, U, F, N_1 = subiu(N,1);
+  GEN fa = Z_factor_limit(N_1, B), P = gel(fa,1);
+  long n = lg(P)-1;
+
+  p = gel(P,n);
+  /* fully factored */
+  if (cmpiu(p,B) <= 0 ||
+      (BPSW_psp_nosmalldiv(p)
+      && (BPSW_isprime_small(N) || BPSW_isprime_big(p))))
+    return isprimeSelfridge(N,P, n);
 
-  if (BPSW_isprime_small(N)) return 1;
-  N_1 = subis(N,1);
-  B = minuu(1UL<<19, maxprime());
-  fa = Z_factor_limit(N_1, B);
-  P = gel(fa,1);
   E = gel(fa,2);
-  l = lg(P)-1;
-  p = gel(P,l);
-  U = powii(p, gel(E,l)); /* (possibly) unfactored part of N-1 */
-  if (cmpiu(U, B) <= 0) { U = gen_1; F = N_1; }
+  U = powii(p, gel(E,n)); /* unfactored part of N-1 */
+  /* n >= 2, since 2 and p divide  N-1 */
+  if (n == 2)
+    F = powii(gel(P,1), gel(E,1));
   else
-  { /* l >= 2, since 2 and U divide  N-1 */
-    if (l == 2)
-      F = powii(gel(P,1), gel(E,1));
-    else
-      F = diviiexact(N_1,  U);
-  }
+    F = diviiexact(N_1,  U);
+
   /* N-1 = F U, F factored, U possibly composite */
-  if (U == gen_1) /* smooth */
-    res = isprimeSelfridge(N, P, 0);
-  else if (cmpii(F, U) >= 0) /* 1/2-smooth */
-    res = isprimeSelfridge(N, P, 1);
-  else if (cmpii(sqri(F), U) >= 0) /* 1/3-smooth */
-  {
-    res = BLS_test(N, F);
-    if (res) res = isprimeSelfridge(N, P, 1);
-  }
-  else if (BPSW_psp_nosmalldiv(p)) /* smooth after all */
-    res = isprimeSelfridge(N, P, 0);
-  else
-    res = isprimeAPRCL(N);
+  if (cmpii(F, U) >= 0) /* 1/2-smooth */
+    return isprimeSelfridge(N,P, n-1);
+  if (cmpii(sqri(F), U) >= 0) /* 1/3-smooth */
+    return BLS_test(N, F) && isprimeSelfridge(N,P, n-1);
+  return isprimeAPRCL(N);
+}
+
+/* assume N a BPSW pseudoprime, in particular, it is odd > 2 */
+long
+BPSW_isprime(GEN N)
+{
+  pari_sp av;
+  long res;
+  if (BPSW_isprime_small(N)) return 1;
+  av = avma; res = BPSW_isprime_big(N);
   avma = av; return res;
 }
 
@@ -947,7 +940,7 @@ randomprime(GEN N)
       b = subiu(N,1); /* between 2 and N-1 */
       d = subiu(N,2);
       if (signe(d) <= 0)
-        pari_err_DOMAIN("randomprime","N", "<", gen_2, N);
+        pari_err_DOMAIN("randomprime","N", "<=", gen_2, N);
       break;
     case t_VEC:
       if (lg(N) != 3) pari_err_TYPE("randomprime",N);
@@ -1183,8 +1176,17 @@ primes_interval(GEN a, GEN b)
   forprime_t S;
   long i, n;
   GEN y, d, p;
-  if (typ(a) != t_INT) a = gceil(a);
-  if (typ(b) != t_INT) b = gfloor(b);
+  if (typ(a) != t_INT)
+  {
+    a = gceil(a);
+    if (typ(a) != t_INT) pari_err_TYPE("primes_interval",a);
+  }
+  if (typ(b) != t_INT)
+  {
+    b = gfloor(b);
+    if (typ(b) != t_INT) pari_err_TYPE("primes_interval",b);
+  }
+  if (signe(a) < 0) a = gen_2;
   d = subii(b, a);
   if (signe(d) < 0 || signe(b) <= 0) { avma = av; return cgetg(1, t_VEC); }
   if (lgefint(b) == 3)
@@ -1230,7 +1232,11 @@ primes_interval_zv(ulong a, ulong b)
   if (!a) return primes_upto_zv(b);
   if (b < a) return cgetg(1, t_VECSMALL);
   d = b - a;
-  if (d > 100000UL) d = primepi_upper_bound(b) - primepi_lower_bound(a);
+  if (d > 100000UL)
+  {
+    ulong D = (ulong)ceil(primepi_upper_bound(b)-primepi_lower_bound(a));
+    if (D < d) d = D;
+  }
   return primes_interval_i(a, b, d);
 }
 GEN
@@ -1238,7 +1244,7 @@ primes_upto_zv(ulong b)
 {
   ulong d;
   if (b < 2) return cgetg(1, t_VECSMALL);
-  d = (b > 100000UL)? primepi_upper_bound(b): b;
+  d = (b > 100000UL)? (ulong)primepi_upper_bound(b): b;
   return primes_interval_i(2, b, d);
 }
 
diff --git a/src/basemath/qfisom.c b/src/basemath/qfisom.c
index 3d13487..a788e8f 100644
--- a/src/basemath/qfisom.c
+++ b/src/basemath/qfisom.c
@@ -323,16 +323,15 @@ init_bacher(long bachdep, struct fingerprint *fp, struct qfauto *qf)
 
 /* checks, whether the vector v[I] has the Bacher-polynomial pol  */
 static long
-bachcomp(GEN pol, long I, long S, GEN V, GEN W, GEN Fv)
+bachcomp(GEN pol, long I, GEN V, GEN W, GEN Fv)
 {
   pari_sp av = avma;
   GEN co, list, listxy, vI;
   long i, j, k;
   long nlist, nxy, count;
-  long n = lg(V)-1;
+  const long n = lg(V)-1, S = mael(W,I,1) / 2;
   long sum = mael(pol,1,1), mind = mael(pol,1,2), maxd = mael(pol,1,3);
   GEN coef = gel(pol,2);
-  I = labs(I);
   vI = gel(V,I);
   list = zero_Flv(sum);
   /* nlist should be equal to pol.sum */
@@ -654,8 +653,8 @@ stab(long I, struct group *G, struct fingerprint *fp, GEN V, ulong p)
            generator is applied to a random point of the orbit to get Rest more
            stabilizer elements */
       {
-        cnd = 1+(long)(pari_rand() % len);
-        i = 1+(long)(pari_rand() % nH);
+        cnd = 1+(long)random_Fl(len);
+        i = 1+(long)random_Fl(nH);
       }
       im = operate(orb[cnd], gel(H,i), V);
       if (flag[im+n+1] == 0)
@@ -822,10 +821,9 @@ qfisom_candidates(GEN CI, long I, GEN x, struct qfauto *qf,
   long DEP = qfcand->cdep, len = f * DEP;
   if (I >= 2  &&  I <= lg(qfcand->bacher_pol))
   {
-    long BACHSCP = mael(W,labs(x[I-1]),1) / 2;
+    long t = labs(x[I-1]);
     GEN bpolI = gel(qfcand->bacher_pol,I-1);
-    if (bachcomp(bpolI, x[I-1], BACHSCP, V, W, gel(v,1)) == 0)
-      return 0;
+    if (bachcomp(bpolI, t, V, W, gel(v,1)) == 0) return 0;
   }
   if (I==1 || DEP ==0)
     return qfisom_candidates_novec(CI,I,x,qf,qff,fp);
@@ -1574,13 +1572,13 @@ isostab(long pt, GEN G, GEN V, long Maxfail, ulong p)
         if (!zvV_equal(B, gel(w,im+n+1)))
         {
           gel(H,nH+1) = zm_divmod(gel(w,im+n+1),B,p);
-          rpt = 1+(long)(pari_rand() % n);
+          rpt = 1+(long)random_Fl(n);
           tmplen = orbitlen(rpt, 2*n, H, nH+1, V);
           while (tmplen < orblen)
             /* the orbit of this vector is shorter than a previous one, hence
                choose a new random vector */
           {
-            rpt = 1+(long)(pari_rand() % n);
+            rpt = 1+(long)random_Fl(n);
             tmplen = orbitlen(rpt, 2*n, H, nH+1, V);
           }
           if (tmplen > orblen)
diff --git a/src/basemath/qfsolve.c b/src/basemath/qfsolve.c
new file mode 100644
index 0000000..bf258c7
--- /dev/null
+++ b/src/basemath/qfsolve.c
@@ -0,0 +1,1090 @@
+/* Copyright (C) 2000-2004  The PARI group.
+
+This file is part of the PARI/GP package.
+
+PARI/GP 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. It is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY WHATSOEVER.
+
+Check the License for details. You should have received a copy of it, along
+with the package; see the file 'COPYING'. If not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+/* Copyright (C) 2014 Denis Simon
+ * Adapted from qfsolve.gp v. 09/01/2014
+ *   http://www.math.unicaen.fr/~simon/qfsolve.gp
+ *
+ * Author: Denis SIMON <simon at math.unicaen.fr> */
+
+#include "pari.h"
+#include "paripriv.h"
+
+/* LINEAR ALGEBRA */
+/* complete by 0s, assume l-1 <= n */
+static GEN
+vecextend(GEN v, long n)
+{
+  long i, l = lg(v);
+  GEN w = cgetg(n+1, t_COL);
+  for (i = 1; i < l; i++) gel(w,i) = gel(v,i);
+  for (     ; i <=n; i++) gel(w,i) = gen_0;
+  return w;
+}
+
+/* Gives a unimodular matrix with the last column(s) equal to Mv.
+ * Mv can be a column vector or a rectangular matrix.
+ * redflag = 0 or 1. If redflag = 1, LLL-reduce the n-#v first columns. */
+static GEN
+completebasis(GEN Mv, long redflag)
+{
+  GEN U;
+  long m, n;
+
+  if (typ(Mv) == t_COL) Mv = mkmat(Mv);
+  n = lg(Mv)-1;
+  m = nbrows(Mv); /* m x n */
+  if (m == n) return Mv;
+  (void)ZM_hnfall(shallowtrans(Mv), &U, 0);
+  U = ZM_inv(shallowtrans(U), gen_1);
+  if (m==1 || !redflag) return U;
+  /* LLL-reduce the m-n first columns */
+  return shallowconcat(ZM_lll(vecslice(U,1,m-n), 0.99, LLL_INPLACE),
+                       vecslice(U, m-n+1,m));
+}
+
+/* Compute the kernel of M mod p.
+ * returns [d,U], where
+ * d = dim (ker M mod p)
+ * U in GLn(Z), and its first d columns span the kernel. */
+static GEN
+kermodp(GEN M, GEN p, long *d)
+{
+  long j, l;
+  GEN K, B, U;
+
+  K = FpM_center(FpM_ker(M, p), p, shifti(p,-1));
+  B = completebasis(K,0);
+  l = lg(M); U = cgetg(l, t_MAT);
+  for (j =  1; j < l; j++) gel(U,j) = gel(B,l-j);
+  *d = lg(K)-1; return U;
+}
+
+/* INVARIANTS COMPUTATIONS */
+
+static GEN
+principal_minor(GEN G, long  i)
+{ return rowslice(vecslice(G,1,i), 1,i); }
+static GEN
+det_minors(GEN G)
+{
+  long i, l = lg(G);
+  GEN v = cgetg(l+1, t_VEC);
+  gel(v,1) = gen_1;
+  for (i = 2; i <= l; i++) gel(v,i) = ZM_det(principal_minor(G,i-1));
+  return v;
+}
+
+/* Given a symmetric matrix G over Z, compute the Witt invariant
+ *  of G at the prime p (at real place if p = NULL)
+ * Assume that none of the determinant G[1..i,1..i] is 0. */
+static long
+qflocalinvariant(GEN G, GEN p)
+{
+  long i, j, c, l = lg(G);
+  GEN diag, v = det_minors(G);
+  /* Diagonalize G first. */
+  diag = cgetg(l, t_VEC);
+  for (i = 1; i < l; i++) gel(diag,i) = mulii(gel(v,i+1), gel(v,i));
+
+  /* Then compute the product of the Hilbert symbols */
+  /* (diag[i],diag[j])_p for i < j */
+  c = 1;
+  for (i = 1; i < l-1; i++)
+    for (j = i+1; j < l; j++)
+      if (hilbertii(gel(diag,i), gel(diag,j), p) < 0) c = -c;
+  return c;
+}
+
+static GEN
+hilberts(GEN a, GEN b, GEN P, long lP)
+{
+  GEN v = cgetg(lP, t_VECSMALL);
+  long i;
+  for (i = 1; i < lP; i++) v[i] = hilbertii(a, b, gel(P,i)) < 0;
+  return v;
+}
+
+/* G symmetrix matrix or qfb or list of quadratic forms with same discriminant.
+ * P must be equal to factor(-abs(2*matdet(G)))[,1]. */
+static GEN
+qflocalinvariants(GEN G, GEN P)
+{
+  GEN sol;
+  long i, j, l, lP = lg(P);
+
+  /* convert G into a vector of symmetric matrices */
+  G = (typ(G) == t_VEC)? shallowcopy(G): mkvec(G);
+  l = lg(G);
+  for (j = 1; j < l; j++)
+  {
+    GEN g = gel(G,j);
+    if (typ(g) == t_QFI || typ(g) == t_QFR) gel(G,j) = gtomat(g);
+  }
+  sol = cgetg(l, t_MAT);
+  if (lg(gel(G,1)) == 3)
+  { /* in dimension 2, each invariant is a single Hilbert symbol. */
+    GEN d = negi(ZM_det(gel(G,1)));
+    for (j = 1; j < l; j++)
+    {
+      GEN a = gcoeff(gel(G,j),1,1);
+      gel(sol,j) = hilberts(a, d, P, lP);
+    }
+  }
+  else /* in dimension n > 2, we compute a product of n Hilbert symbols. */
+    for (j = 1; j <l; j++)
+    {
+      GEN g = gel(G,j), v = det_minors(g), w = cgetg(lP, t_VECSMALL);
+      long n = lg(v);
+      gel(sol,j) = w;
+      for (i = 1; i < lP; i++)
+      {
+        GEN p = gel(P,i);
+        long k = n-2, h = hilbertii(gel(v,k), gel(v,k+1),p);
+        for (k--; k >= 1; k--)
+          if (hilbertii(negi(gel(v,k)), gel(v,k+1),p) < 0) h = -h;
+        w[i] = h < 0;
+      }
+    }
+  return sol;
+}
+
+/* QUADRATIC FORM REDUCTION */
+static GEN
+qfb(GEN D, GEN a, GEN b, GEN c)
+{
+  if (signe(D) < 0) return mkqfi(a,b,c);
+  retmkqfr(a,b,c,real_0(DEFAULTPREC));
+}
+
+/* Gauss reduction of the binary quadratic form
+ * Q = a*X^2+2*b*X*Y+c*Y^2 of discriminant D (divisible by 4)
+ * returns the reduced form */
+static GEN
+qfbreduce(GEN D, GEN Q)
+{
+  GEN a = gel(Q,1), b = shifti(gel(Q,2),-1), c = gel(Q,3);
+  while (signe(a))
+  {
+    GEN r, q, nexta, nextc;
+    q = dvmdii(b,a, &r); /* FIXME: export as dvmdiiround ? */
+    if (signe(r) > 0 && absi_cmp(shifti(r,1), a) > 0) {
+      r = subii(r, absi(a)); q = addis(q, signe(a));
+    }
+    nextc = a; nexta = subii(c, mulii(q, addii(r,b)));
+    if (absi_cmp(nexta, a) >= 0) break;
+    c = nextc; b = negi(r); a = nexta;
+  }
+  return qfb(D,a,shifti(b,1),c);
+}
+
+/* private version of qfgaussred:
+ * - early abort if k-th principal minor is singular, return stoi(k)
+ * - else return a matrix whose upper triangular part is qfgaussred(a) */
+static GEN
+partialgaussred(GEN a)
+{
+  long n = lg(a)-1, k;
+  a = RgM_shallowcopy(a);
+  for(k = 1; k < n; k++)
+  {
+    GEN ak, p = gcoeff(a,k,k);
+    long i, j;
+    if (isintzero(p)) return stoi(k);
+    ak = row(a, k);
+    for (i=k+1; i<=n; i++) gcoeff(a,k,i) = gdiv(gcoeff(a,k,i), p);
+    for (i=k+1; i<=n; i++)
+    {
+      GEN c = gel(ak,i);
+      if (gequal0(c)) continue;
+      for (j=i; j<=n; j++)
+        gcoeff(a,i,j) = gsub(gcoeff(a,i,j), gmul(c,gcoeff(a,k,j)));
+    }
+  }
+  if (isintzero(gcoeff(a,n,n))) return stoi(n);
+  return a;
+}
+
+/* LLL-reduce a positive definite qf QD bounding the indefinite G, dim G > 1.
+ * Then finishes by looking for trivial solution */
+static GEN qftriv(GEN G, GEN z, long base);
+static GEN
+qflllgram_indef(GEN G, long base)
+{
+  GEN M, R, g, DM, S, dR;
+  long i, j, n = lg(G)-1;
+
+  R = partialgaussred(G);
+  if (typ(R) == t_INT) return qftriv(G, R, base);
+  R = Q_remove_denom(R, &dR); /* avoid rational arithmetic */
+  M = zeromatcopy(n,n);
+  DM = zeromatcopy(n,n);
+  for (i = 1; i <= n; i++)
+  {
+    GEN d = absi_shallow(gcoeff(R,i,i));
+    if (dR) {
+      gcoeff(M,i,i) = dR;
+      gcoeff(DM,i,i) = mulii(d,dR);
+    } else {
+      gcoeff(M,i,i) = gen_1;
+      gcoeff(DM,i,i) = d;
+    }
+    for (j = i+1; j <= n; j++)
+    {
+      gcoeff(M,i,j) = gcoeff(R,i,j);
+      gcoeff(DM,i,j) = mulii(d, gcoeff(R,i,j));
+    }
+  }
+  /* G = M~*D*M, D diagonal, DM=|D|*M, g =  M~*|D|*M */
+  g = ZM_transmultosym(M,DM);
+  S = lllgramint(Q_primpart(g));
+  R = qftriv(qf_apply_ZM(G,S), NULL, base);
+  switch(typ(R))
+  {
+    case t_COL: return ZM_ZC_mul(S,R);
+    case t_MAT: return mkvec2(R, S);
+    default:
+      gel(R,2) = ZM_mul(S, gel(R,2));
+      return R;
+  }
+}
+
+/* G symmetric, i < j, let E = E_{i,j}(a), G <- E~*G*E,  U <- U*E.
+ * Everybody integral */
+static void
+qf_apply_transvect_Z(GEN G, GEN U, long i, long j, GEN a)
+{
+  long k, n = lg(G)-1;
+  gel(G, j) =  ZC_lincomb(gen_1, a, gel(G,j), gel(G,i));
+  for (k = 1; k < n; k++) gcoeff(G, j, k) = gcoeff(G, k, j);
+  gcoeff(G,j,j) = addmulii(gcoeff(G,j,j), a,
+                           addmulii(gcoeff(G,i,j), a,gcoeff(G,i,i)));
+  gel(U, j) =  ZC_lincomb(gen_1, a, gel(U,j), gel(U,i));
+}
+
+/* LLL reduction of the quadratic form G (Gram matrix)
+ * where we go on, even if an isotropic vector is found. */
+static GEN
+qflllgram_indefgoon(GEN G)
+{
+  GEN red, U, A, U1,U2,U3,U5,U6, V, B, G2,G3,G4,G5, G6, a, g;
+  long i, j, n = lg(G)-1;
+
+  red = qflllgram_indef(G,1);
+  if (typ(red)==t_MAT) return red; /*no isotropic vector found: nothing to do*/
+  /* otherwise a solution is found: */
+  U1 = gel(red,2);
+  G2 = gel(red,1); /* G2[1,1] = 0 */
+  U2 = gel(mathnf0(row(G2,1), 4), 2);
+  G3 = qf_apply_ZM(G2,U2);
+  U = ZM_mul(U1,U2); /* qf_apply(G,U) = G3 */
+  /* G3[1,] = [0,...,0,g], g^2 | det G */
+  g = gcoeff(G3,1,n);
+  a = diviiround(negi(gcoeff(G3,n,n)), shifti(g,1));
+  if (signe(a)) qf_apply_transvect_Z(G3,U,1,n,a);
+  /* G3[n,n] reduced mod 2g */
+  if (n == 2) return mkvec2(G3,U);
+  V = rowpermute(vecslice(G3, 2,n-1), mkvecsmall2(1,n));
+  A = mkmat2(mkcol2(gcoeff(G3,1,1),gcoeff(G3,1,n)),
+             mkcol2(gcoeff(G3,1,n),gcoeff(G3,2,2)));
+  B = ground(RgM_neg(RgM_mul(RgM_inv(A), V)));
+  U3 = matid(n);
+  for (j = 2; j < n; j++)
+  {
+    gcoeff(U3,1,j) = gcoeff(B,1,j-1);
+    gcoeff(U3,n,j) = gcoeff(B,2,j-1);
+  }
+  G4 = qf_apply_ZM(G3,U3); /* the last column of G4 is reduced */
+  U = ZM_mul(U,U3);
+  if (n == 3) return mkvec2(G4,U);
+
+  red = qflllgram_indefgoon(rowslice(vecslice(G4,2,n-1),2,n-1));
+  if (typ(red) == t_MAT) return mkvec2(G4,U);
+  /* Let U5:=matconcat(diagonal[1,red[2],1])
+   * return [qf_apply_ZM(G5, U5), U*U5] */
+  G5 = gel(red,1);
+  U5 = gel(red,2);
+  G6 = cgetg(n+1,t_MAT);
+  gel(G6,1) = gel(G4,1);
+  gel(G6,n) = gel(G4,n);
+  for (j=2; j<n; j++)
+  {
+    gel(G6,j) = cgetg(n+1,t_COL);
+    gcoeff(G6,1,j) = gcoeff(G4,j,1);
+    gcoeff(G6,n,j) = gcoeff(G4,j,n);
+    for (i=2; i<n; i++) gcoeff(G6,i,j) = gcoeff(G5,i-1,j-1);
+  }
+  U6 = mkvec3(mkmat(gel(U,1)), ZM_mul(vecslice(U,2,n-1),U5), mkmat(gel(U,n)));
+  return mkvec2(G6, shallowconcat1(U6));
+}
+
+/* qf_apply_ZM(G,H),  where H = matrix of \tau_{i,j}, i != j */
+static GEN
+qf_apply_tau(GEN G, long i, long j)
+{
+  long l = lg(G), k;
+  G = RgM_shallowcopy(G);
+  swap(gel(G,i), gel(G,j));
+  for (k = 1; k < l; k++) swap(gcoeff(G,i,k), gcoeff(G,j,k));
+  return G;
+}
+
+/* LLL reduction of the quadratic form G (Gram matrix)
+ * in dim 3 only, with detG = -1 and sign(G) = [2,1]; */
+static GEN
+qflllgram_indefgoon2(GEN G)
+{
+  GEN red, G2, a, b, c, d, e, f, u, v, r, r3, U2, G3;
+
+  red = qflllgram_indef(G,1); /* always find an isotropic vector. */
+  G2 = qf_apply_tau(gel(red,1),1,3); /* G2[3,3] = 0 */
+  r = row(gel(red,2), 3);
+  swap(gel(r,1), gel(r,3)); /* apply tau_{1,3} */
+  a = gcoeff(G2,3,1);
+  b = gcoeff(G2,3,2);
+  d = bezout(a,b, &u,&v);
+  if (!is_pm1(d))
+  {
+    a = diviiexact(a,d);
+    b = diviiexact(b,d);
+  }
+  /* for U2 = [-u,-b,0;-v,a,0;0,0,1]
+   * G3 = qf_apply_ZM(G2,U2) has known last row (-d, 0, 0),
+   * so apply to principal_minor(G3,2), instead */
+  U2 = mkmat2(mkcol2(negi(u),negi(v)), mkcol2(negi(b),a));
+  G3 = qf_apply_ZM(principal_minor(G2,2),U2);
+  r3 = gel(r,3);
+  r = ZV_ZM_mul(mkvec2(gel(r,1),gel(r,2)),U2);
+
+  a = gcoeff(G3,1,1);
+  b = gcoeff(G3,1,2);
+  c = negi(d); /* G3[1,3] */
+  d = gcoeff(G3,2,2);
+  if (mpodd(a))
+  {
+    e = addii(b,d);
+    a = addii(a, addii(b,e));
+    e = diviiround(negi(e),c);
+    f = diviiround(negi(a), shifti(c,1));
+    a = addmulii(addii(gel(r,1),gel(r,2)), f,r3);
+  }
+  else
+  {
+    e = diviiround(negi(b),c);
+    f = diviiround(negi(shifti(a,-1)), c);
+    a = addmulii(gel(r,1), f, r3);
+  }
+  b = addmulii(gel(r,2), e, r3);
+  return mkvec3(a,b, r3);
+}
+
+/* QUADRATIC FORM MINIMIZATION */
+/* G symmetric, return ZM_Z_divexact(G,d) */
+static GEN
+ZsymM_Z_divexact(GEN G, GEN d)
+{
+  long i,j,l = lg(G);
+  GEN H = cgetg(l, t_MAT);
+  for(j=1; j<l; j++)
+  {
+    GEN c = cgetg(l, t_COL), b = gel(G,j);
+    for(i=1; i<j; i++) gcoeff(H,j,i) = gel(c,i) = diviiexact(gel(b,i),d);
+    gel(c,j) = diviiexact(gel(b,j),d);
+    gel(H,j) = c;
+  }
+  return H;
+}
+
+/* write symmetric G as [A,B;B~,C], A dxd, C (n-d)x(n-d) */
+static void
+blocks4(GEN G, long d, long n, GEN *A, GEN *B, GEN *C)
+{
+  GEN G2 = vecslice(G,d+1,n);
+  *A = principal_minor(G, d);
+  *B = rowslice(G2, 1, d);
+  *C = rowslice(G2, d+1, n);
+}
+/* Minimization of the quadratic form G, deg G != 0, dim n >= 2
+ * G symmetric integral
+ * Returns [G',U,factd] with U in GLn(Q) such that G'=U~*G*U*constant
+ * is integral and has minimal determinant.
+ * In dimension 3 or 4, may return a prime p if the reduction at p is
+ * impossible because of local non-solvability.
+ * P,E = factor(+/- det(G)), "prime" -1 is ignored. Destroy E. */
+static GEN qfsolvemodp(GEN G, GEN p);
+static GEN
+qfminimize(GEN G, GEN P, GEN E)
+{
+  GEN d, U, Ker, sol, aux, faE, faP;
+  long n = lg(G)-1, lP = lg(P), i, dimKer, m;
+
+  faP = vectrunc_init(lP);
+  faE = vecsmalltrunc_init(lP);
+  U = NULL;
+  for (i = 1; i < lP; i++)
+  {
+    GEN p = gel(P,i);
+    long vp = E[i];
+    if (!vp || !p) continue;
+
+    if (DEBUGLEVEL >= 4) err_printf("    p^v = %Ps^%ld\n", p,vp);
+    /* The case vp = 1 can be minimized only if n is odd. */
+    if (vp == 1 && n%2 == 0) {
+      vectrunc_append(faP, p);
+      vecsmalltrunc_append(faE, 1);
+      continue;
+    }
+    Ker = kermodp(G,p, &dimKer); /* dimKer <= vp */
+    if (DEBUGLEVEL >= 4) err_printf("    dimKer = %ld\n",dimKer);
+    if (dimKer == n)
+    { /* trivial case: dimKer = n */
+      if (DEBUGLEVEL >= 4) err_printf("     case 0: dimKer = n\n");
+      G = ZsymM_Z_divexact(G, p);
+      E[i] -= n;
+      i--; continue; /* same p */
+    }
+    G = qf_apply_ZM(G, Ker);
+    U = U? RgM_mul(U,Ker): Ker;
+
+    /* 1st case: dimKer < vp */
+    /* then the kernel mod p contains a kernel mod p^2 */
+    if (dimKer < vp)
+    {
+      if (DEBUGLEVEL >= 4) err_printf("    case 1: dimker < vp\n");
+      if (dimKer == 1)
+      {
+        long j;
+        gel(G,1) = ZC_Z_divexact(gel(G,1), p);
+        for (j = 1; j<=n; j++) gcoeff(G,1,j) = diviiexact(gcoeff(G,1,j), p);
+        gel(U,1) = RgC_Rg_div(gel(U,1), p);
+        E[i] -= 2;
+      }
+      else
+      {
+        GEN A,B,C, K2 = ZsymM_Z_divexact(principal_minor(G,dimKer),p);
+        long j, dimKer2;
+        K2 = kermodp(K2, p, &dimKer2);
+        for (j = dimKer2+1; j <= dimKer; j++) gel(K2,j) = ZC_Z_mul(gel(K2,j),p);
+        /* Write G = [A,B;B~,C] and apply [K2,0;0,p*Id]/p by blocks */
+        blocks4(G, dimKer,n, &A,&B,&C);
+        A = ZsymM_Z_divexact(qf_apply_ZM(A,K2), sqri(p));
+        B = ZM_Z_divexact(ZM_transmul(B,K2), p);
+        G = shallowmatconcat(mkmat2(mkcol2(A,B),
+                                    mkcol2(shallowtrans(B), C)));
+        /* U *= [K2,0;0,Id] */
+        U = shallowconcat(RgM_Rg_div(RgM_mul(vecslice(U,1,dimKer),K2), p),
+                          vecslice(U,dimKer+1,n));
+        E[i] -= 2*dimKer2;
+      }
+      i--; continue; /* same p */
+    }
+
+   /* vp = dimKer
+    * 2nd case: kernel has dim >= 2 and contains an element of norm 0 mod p^2
+    * search for an element of norm p^2... in the kernel */
+    sol = NULL;
+    if (dimKer > 2) {
+      if (DEBUGLEVEL >= 4) err_printf("    case 2.1\n");
+      dimKer = 3;
+      sol = qfsolvemodp(ZsymM_Z_divexact(principal_minor(G,3),p),  p);
+      sol = FpC_red(sol, p);
+    }
+    else if (dimKer == 2)
+    {
+      GEN a = modii(diviiexact(gcoeff(G,1,1),p), p);
+      GEN b = modii(diviiexact(gcoeff(G,1,2),p), p);
+      GEN c = diviiexact(gcoeff(G,2,2),p);
+      GEN di= modii(subii(sqri(b), mulii(a,c)), p);
+      if (kronecker(di,p) >= 0)
+      {
+        if (DEBUGLEVEL >= 4) err_printf("    case 2.2\n");
+        sol = signe(a)? mkcol2(Fp_sub(Fp_sqrt(di,p), b, p), a): vec_ei(2,1);
+      }
+    }
+    if (sol)
+    {
+      long j;
+      sol = FpC_center(sol, p, shifti(p,-1));
+      sol = Q_primpart(sol);
+      if (DEBUGLEVEL >= 4) err_printf("    sol = %Ps\n", sol);
+      Ker = completebasis(vecextend(sol,n), 1);
+      for(j=1; j<n; j++) gel(Ker,j) = ZC_Z_mul(gel(Ker,j), p);
+      G = ZsymM_Z_divexact(qf_apply_ZM(G, Ker), sqri(p));
+      U = RgM_Rg_div(RgM_mul(U,Ker), p);
+      E[i] -= 2;
+      i--; continue; /* same p */
+    }
+    /* Now 1 <= vp = dimKer <= 2 and kernel contains no vector with norm p^2 */
+    /* exchanging kernel and image makes minimization easier ? */
+    m = (n-3)/2;
+    d = ZM_det(G); if (odd(m)) d = negi(d);
+    if ((vp==1 && kronecker(gmod(gdiv(negi(d), gcoeff(G,1,1)),p), p) >= 0)
+     || (vp==2 && odd(n) && n >= 5)
+     || (vp==2 && !odd(n) && kronecker(modii(diviiexact(d,sqri(p)), p),p) < 0))
+    {
+      long j;
+      if (DEBUGLEVEL >= 4) err_printf("    case 3\n");
+      Ker = matid(n);
+      for (j = dimKer+1; j <= n; j++) gcoeff(Ker,j,j) = p;
+      G = ZsymM_Z_divexact(qf_apply_ZM(G, Ker), p);
+      U = RgM_mul(U,Ker);
+      E[i] -= 2*dimKer-n;
+      i--; continue; /* same p */
+    }
+
+    /* Minimization was not possible so far. */
+    /* If n == 3 or 4, this proves the local non-solubility at p. */
+    if (n == 3 || n == 4)
+    {
+      if (DEBUGLEVEL >= 1) err_printf(" no local solution at %Ps\n",p);
+      return(p);
+    }
+    vectrunc_append(faP, p);
+    vecsmalltrunc_append(faE, vp);
+  }
+  if (!U) U = matid(n);
+  else
+  { /* apply LLL to avoid coefficient explosion */
+    aux = lllint(Q_primpart(U));
+    G = qf_apply_ZM(G,aux);
+    U = RgM_mul(U,aux);
+  }
+  return mkvec4(G, U, faP, faE);
+}
+
+/* CLASS GROUP COMPUTATIONS */
+
+/* Compute the square root of the quadratic form q of discriminant D. Not
+ * fully implemented; it only works for detqfb squarefree except at 2, where
+ * the valuation is 2 or 3.
+ * mkmat2(P,zv_to_ZV(E)) = factor(2*abs(det q)) */
+static GEN
+qfbsqrt(GEN D, GEN q, GEN P, GEN E)
+{
+  GEN a = gel(q,1), b = shifti(gel(q,2),-1), c = gel(q,3), mb = negi(b);
+  GEN m,n, aux,Q1,M, A,B,C;
+  GEN d = subii(mulii(a,c), sqri(b));
+  long i;
+
+  /* 1st step: solve m^2 = a (d), m*n = -b (d), n^2 = c (d) */
+  m = n = mkintmod(gen_0,gen_1);
+  E[1] -= 3;
+  for (i = 1; i < lg(P); i++)
+  {
+    GEN p = gel(P,i), N, M;
+    if (!E[i]) continue;
+    if (dvdii(a,p)) {
+      aux = Fp_sqrt(c, p);
+      N = aux;
+      M = Fp_div(mb, aux, p);
+    } else {
+      aux = Fp_sqrt(a, p);
+      M = aux;
+      N = Fp_div(mb, aux, p);
+    }
+    n = chinese(n, mkintmod(N,p));
+    m = chinese(m, mkintmod(M,p));
+  }
+  m = centerlift(m);
+  n = centerlift(n);
+  if (DEBUGLEVEL >=4) err_printf("    [m,n] = [%Ps, %Ps]\n",m,n);
+
+  /* 2nd step: build Q1, with det=-1 such that Q1(x,y,0) = G(x,y) */
+  A = diviiexact(subii(sqri(n),c), d);
+  B = diviiexact(addii(b, mulii(m,n)), d);
+  C = diviiexact(subii(sqri(m), a), d);
+  Q1 = mkmat3(mkcol3(A,B,n), mkcol3(B,C,m), mkcol3(n,m,d));
+  Q1 = gneg(adj(Q1));
+
+  /* 3rd step: reduce Q1 to [0,0,-1;0,1,0;-1,0,0] */
+  M = qflllgram_indefgoon2(Q1);
+  if (signe(gel(M,1)) < 0) M = ZC_neg(M);
+  a = gel(M,1);
+  b = gel(M,2);
+  c = gel(M,3);
+  if (mpodd(a))
+    return qfb(D, a, shifti(b,1), shifti(c,1));
+  else
+    return qfb(D, c, shifti(negi(b),1), shifti(a,1));
+}
+
+/* \prod gen[i]^e[i] as a Qfb, e in {0,1}^n non-zero */
+static GEN
+qfb_factorback(GEN D, GEN gen, GEN e)
+{
+  GEN q = NULL;
+  long j, l = lg(gen), n = 0;
+  for (j = 1; j < l; j++)
+    if (e[j]) { n++; q = q? qfbcompraw(q, gel(gen,j)): gel(gen,j); }
+  return (n <= 1)? q: qfbreduce(D, q);
+}
+
+/* unit form, assuming 4 | D */
+static GEN
+id(GEN D)
+{ return mkmat2(mkcol2(gen_1,gen_0),mkcol2(gen_0,shifti(negi(D),-2))); }
+
+/* Shanks/Bosma-Stevenhagen algorithm to compute the 2-Sylow of the class
+ * group of discriminant D. Only works for D = fundamental discriminant.
+ * When D = 1(4), work with 4D.
+ * P2D,E2D = factor(abs(2*D))
+ * Pm2D = factor(-abs(2*D))[,1].
+ * Return a form having Witt invariants W at Pm2D */
+static GEN
+quadclass2(GEN D, GEN P2D, GEN E2D, GEN Pm2D, GEN W, int n_is_4)
+{
+  GEN gen, Wgen, U2;
+  long i, n, r, m, vD;
+
+  if (mpodd(D))
+  {
+    D = shifti(D,2);
+    E2D = shallowcopy(E2D);
+    E2D[1] = 3;
+  }
+  if (zv_equal0(W)) return id(D);
+
+  n = lg(Pm2D)-1; /* >= 3 since W != 0 */
+  r = n-3;
+  m = (signe(D)>0)? r+1: r;
+  /* n=4: look among forms of type q or 2*q, since Q can be imprimitive */
+  U2 = n_is_4? mkmat(hilberts(gen_2, D, Pm2D, lg(Pm2D))): NULL;
+  if (U2 && zv_equal(gel(U2,1),W)) return gmul2n(id(D),1);
+
+  gen = cgetg(m+1, t_VEC);
+  for (i = 1; i <= m; i++) /* no need to look at Pm2D[1]=-1, nor Pm2D[2]=2 */
+  {
+    GEN p = gel(Pm2D,i+2), d;
+    long vp = Z_pvalrem(D,p, &d);
+    gel(gen,i) = qfb(D, powiu(p,vp), gen_0, negi(shifti(d,-2)));
+  }
+  vD = Z_lval(D,2);  /* = 2 or 3 */
+  if (vD == 2 && smodis(D,16) != 4)
+  {
+    GEN q2 = qfb(D, gen_2,gen_2, shifti(subsi(4,D),-3));
+    m++; r++; gen = shallowconcat(gen, mkvec(q2));
+  }
+  if (vD == 3)
+  {
+    GEN q2 = qfb(D, gen_2,gen_0, negi(shifti(D,-3)));
+    m++; r++; gen = shallowconcat(gen, mkvec(q2));
+  }
+  if (!r) return id(D);
+  Wgen = qflocalinvariants(gen,Pm2D);
+  for(;;)
+  {
+    GEN Wgen2, gen2, Ker, indexim = gel(Flm_indexrank(Wgen,2), 2);
+    long dKer;
+    if (lg(indexim)-1 >= r)
+    {
+      GEN W2 = Wgen, V;
+      if (lg(indexim) < lg(Wgen)) W2 = vecpermute(Wgen,indexim);
+      if (U2) W2 = shallowconcat(W2,U2);
+      V = Flm_Flc_invimage(W2, W,2);
+      if (V) {
+        GEN Q = qfb_factorback(D, vecpermute(gen,indexim), V);
+        Q = gtomat(Q);
+        if (U2 && V[lg(V)-1]) Q = gmul2n(Q,1);
+        return Q;
+      }
+    }
+    Ker = Flm_ker(Wgen,2); dKer = lg(Ker)-1;
+    gen2 = cgetg(m+1, t_VEC);
+    Wgen2 = cgetg(m+1, t_MAT);
+    for (i = 1; i <= dKer; i++)
+    {
+      GEN q = qfb_factorback(D, gen, gel(Ker,i));
+      q = qfbsqrt(D,q,P2D,E2D);
+      gel(gen2,i) = q;
+      gel(Wgen2,i) = gel(qflocalinvariants(q,Pm2D), 1);
+    }
+    for (; i <=m; i++)
+    {
+      long j = indexim[i-dKer];
+      gel(gen2,i) = gel(gen,j);
+      gel(Wgen2,i) = gel(Wgen,j);
+    }
+    gen = gen2; Wgen = Wgen2;
+  }
+}
+
+/* QUADRATIC EQUATIONS */
+/* is x*y = -1 ? */
+static int
+both_pm1(GEN x, GEN y)
+{ return is_pm1(x) && is_pm1(y) && signe(x) == -signe(y); }
+
+/* Try to solve G = 0 with small coefficients. This is proved to work if
+ * -  det(G) = 1, dim <= 6 and G is LLL reduced
+ * Returns G if no solution is found.
+ * Exit with a norm 0 vector if one such is found.
+ * If base == 1 and norm 0 is obtained, returns [H~*G*H,H] where
+ * the 1st column of H is a norm 0 vector */
+static GEN
+qftriv(GEN G, GEN R, long base)
+{
+  long n = lg(G)-1, i;
+  GEN s, H;
+
+  /* case 1: A basis vector is isotropic */
+  for (i = 1; i <= n; i++)
+    if (!signe(gcoeff(G,i,i)))
+    {
+      if (!base) return col_ei(n,i);
+      H = matid(n); swap(gel(H,1), gel(H,i));
+      return mkvec2(qf_apply_tau(G,1,i),H);
+    }
+  /* case 2: G has a block +- [1,0;0,-1] on the diagonal */
+  for (i = 2; i <= n; i++)
+    if (!signe(gcoeff(G,i-1,i)) && both_pm1(gcoeff(G,i-1,i-1),gcoeff(G,i,i)))
+    {
+      s = col_ei(n,i); gel(s,i-1) = gen_m1;
+      if (!base) return s;
+      H = matid(n); gel(H,i) = gel(H,1); gel(H,1) = s;
+      return mkvec2(qf_apply_ZM(G,H),H);
+    }
+  if (!R) return G; /* fail */
+  /* case 3: a principal minor is 0 */
+  s = keri(principal_minor(G, itos(R)));
+  s = vecextend(Q_primpart(gel(s,1)), n);
+  if (!base) return s;
+  H = completebasis(s, 0);
+  gel(H,n) = ZC_neg(gel(H,1)); gel(H,1) = s;
+  return mkvec2(qf_apply_ZM(G,H),H);
+}
+
+/* p a prime number, G 3x3 symmetric. Finds X!=0 such that X^t G X = 0 mod p.
+ * Allow returning a shorter X: to be completed with 0s. */
+static GEN
+qfsolvemodp(GEN G, GEN p)
+{
+  GEN a,b,c,d,e,f, v1,v2,v3,v4,v5, x1,x2,x3,N1,N2,N3,s,r;
+
+  /* principal_minor(G,3) = [a,b,d; b,c,e; d,e,f] */
+  a = modii(gcoeff(G,1,1), p);
+  if (!signe(a)) return mkcol(gen_1);
+  v1 = a;
+  b = modii(gcoeff(G,1,2), p);
+  c = modii(gcoeff(G,2,2), p);
+  v2 = modii(subii(mulii(a,c), sqri(b)), p);
+  if (!signe(v2)) return mkcol2(Fp_neg(b,p), a);
+  d = modii(gcoeff(G,1,3), p);
+  e = modii(gcoeff(G,2,3), p);
+  f = modii(gcoeff(G,3,3), p);
+  v4 = modii(subii(mulii(c,d), mulii(e,b)), p);
+  v5 = modii(subii(mulii(a,e), mulii(d,b)), p);
+  v3 = subii(mulii(v2,f), addii(mulii(v4,d), mulii(v5,e))); /* det(G) */
+  v3 = modii(v3, p);
+  N1 =  Fp_neg(v2,  p);
+  x3 = mkcol3(v4, v5, N1);
+  if (!signe(v3)) return x3;
+
+  /* now, solve in dimension 3... reduction to the diagonal case: */
+  x1 = mkcol3(gen_1, gen_0, gen_0);
+  x2 = mkcol3(negi(b), a, gen_0);
+  if (kronecker(N1,p) == 1) return ZC_lincomb(Fp_sqrt(N1,p),gen_1,x1,x2);
+  N2 = Fp_div(Fp_neg(v3,p), v1, p);
+  if (kronecker(N2,p) == 1) return ZC_lincomb(Fp_sqrt(N2,p),gen_1,x2,x3);
+  N3 = Fp_mul(v2, N2, p);
+  if (kronecker(N3,p) == 1) return ZC_lincomb(Fp_sqrt(N3,p),gen_1,x1,x3);
+  r = gen_1;
+  for(;;)
+  {
+    s = Fp_sub(gen_1, Fp_mul(N1,Fp_sqr(r,p),p), p);
+    if (kronecker(s, p) <= 0) break;
+    r = randomi(p);
+  }
+  s = Fp_sqrt(Fp_div(s,N3,p), p);
+  return ZC_add(x1, ZC_lincomb(r,s,x2,x3));
+}
+
+/* assume G square integral */
+static void
+check_symmetric(GEN G)
+{
+  long i,j, l = lg(G);
+  for (i = 1; i < l; i++)
+    for(j = 1; j < i; j++)
+      if (!equalii(gcoeff(G,i,j), gcoeff(G,j,i)))
+        pari_err_TYPE("qfsolve [not symmetric]",G);
+}
+
+/* Given a square matrix G of dimension n >= 1, */
+/* solves over Z the quadratic equation X^tGX = 0. */
+/* G is assumed to have integral coprime coefficients. */
+/* The solution might be a vectorv or a matrix. */
+/* If no solution exists, returns an integer, that can */
+/* be a prime p such that there is no local solution at p, */
+/* or -1 if there is no real solution, */
+/* or 0 in some rare cases. */
+static  GEN
+qfsolve_i(GEN G)
+{
+  GEN M, signG, Min, U, G1, M1, G2, M2, solG2, P, E;
+  GEN solG1, sol, Q, d, dQ, detG2, fam2detG;
+  long n, np, codim, dim;
+
+  if (typ(G) != t_MAT) pari_err_TYPE("qfsolve", G);
+  n = lg(G)-1;
+  if (n == 0) pari_err_DOMAIN("qfsolve", "dimension" , "=", gen_0, G);
+  if (n != nbrows(G)) pari_err_DIM("qfsolve");
+  G = Q_primpart(G); RgM_check_ZM(G, "qfsolve");
+  check_symmetric(G);
+
+  /* Trivial case: det = 0 */
+  d = ZM_det(G);
+  if (!signe(d))
+  {
+    if (n == 1) return mkcol(gen_1);
+    sol = keri(G);
+    if (lg(sol) == 2) sol = gel(sol,1);
+    return sol;
+  }
+
+  /* Small dimension: n <= 2 */
+  if (n == 1) return gen_m1;
+  if (n == 2)
+  {
+    GEN t, a =  gcoeff(G,1,1);
+    if (!signe(a)) return mkcol2(gen_1, gen_0);
+    if (signe(d) > 0) return gen_m1; /* no real solution */
+    if (!Z_issquareall(negi(d), &t)) return gen_m2;
+    return mkcol2(subii(t,gcoeff(G,1,2)), a);
+  }
+
+  /* 1st reduction of the coefficients of G */
+  M = qflllgram_indef(G,0);
+  if (typ(M) == t_COL) return M;
+  G = gel(M,1);
+  M = gel(M,2);
+
+  /* real solubility */
+  signG = ZV_to_zv(qfsign(G));
+  {
+    long r =  signG[1], s = signG[2];
+    if (!r || !s) return gen_m1;
+    if (r < s) { G = ZM_neg(G); signG = mkvecsmall2(s,r);  }
+  }
+
+  /* factorization of the determinant */
+  fam2detG = Z_factor( absi(d) );
+  P = gel(fam2detG,1);
+  E = ZV_to_zv(gel(fam2detG,2));
+  /* P,E = factor(|det(G)|) */
+
+  /* Minimization and local solubility */
+  Min = qfminimize(G, P, E);
+  if (typ(Min) == t_INT) return Min;
+
+  M = RgM_mul(M, gel(Min,2));
+  G = gel(Min,1);
+  P = gel(Min,3);
+  E = gel(Min,4);
+  /* P,E = factor(|det(G))| */
+
+  /* Now, we know that local solutions exist (except maybe at 2 if n==4)
+   * if n==3, det(G) = +-1
+   * if n==4, or n is odd, det(G) is squarefree.
+   * if n>=6, det(G) has all its valuations <=2. */
+
+  /* Reduction of G and search for trivial solutions. */
+  /* When |det G|=1, such trivial solutions always exist. */
+  U = qflllgram_indef(G,0);
+  if(typ(U) == t_COL) return Q_primpart(RgM_RgC_mul(M,U));
+  G = gel(U,1);
+  M = RgM_mul(M, gel(U,2));
+  /* P,E = factor(|det(G))| */
+
+  /* If n >= 6 is even, need to increment the dimension by 1 to suppress all
+   * squares from det(G) */
+  np = lg(P)-1;
+  if (n < 6 || odd(n) || !np)
+  {
+    codim = 0;
+    G1 = G;
+    M1 = NULL;
+  }
+  else
+  {
+    GEN aux;
+    long i;
+    codim = 1; n++;
+    /* largest square divisor of d */
+    aux = gen_1;
+    for (i = 1; i <= np; i++)
+      if (E[i] == 2) { aux = mulii(aux, gel(P,i)); E[i] = 3; }
+    /* Choose sign(aux) so as to balance the signature of G1 */
+    if (signG[1] > signG[2])
+    {
+      signG[2]++;
+      aux = negi(aux);
+    }
+    else
+      signG[1]++;
+    G1 = shallowmatconcat(diagonal_shallow(mkvec2(G,aux)));
+    /* P,E = factor(|det G1|) */
+    Min = qfminimize(G1, P, E);
+    G1 = gel(Min,1);
+    M1 = gel(Min,2);
+    P = gel(Min,3);
+    E = gel(Min,4);
+    np = lg(P)-1;
+  }
+
+  /* now, d is squarefree */
+  if (!np)
+  { /* |d| = 1 */
+     G2 = G1;
+     M2 = NULL;
+  }
+  else
+  { /* |d| > 1: increment dimension by 2 */
+    GEN factdP, factdE, W;
+    long i, lfactdP;
+    codim += 2;
+    d = ZV_prod(P); /* d = abs(matdet(G1)); */
+    if (odd(signG[2])) togglesign_safe(&d); /* d = matdet(G1); */
+    /* solubility at 2 (this is the only remaining bad prime). */
+    if (n == 4 && smodis(d,8) == 1 && qflocalinvariant(G,gen_2) == 1)
+      return gen_2;
+
+    P = shallowconcat(mpodd(d)? mkvec2(NULL,gen_2): mkvec(NULL), P);
+    /* build a binary quadratic form with given Witt invariants */
+    W = const_vecsmall(lg(P)-1, 0);
+    /* choose signature of Q (real invariant and sign of the discriminant) */
+    dQ = absi(d);
+    if (signG[1] > signG[2]) togglesign_safe(&dQ); /* signQ = [2,0]; */
+    if (n == 4 && smodis(dQ,4) != 1) dQ = shifti(dQ,2);
+    if (n >= 5) dQ = shifti(dQ,3);
+
+    /* p-adic invariants */
+    if (n == 4)
+    {
+      GEN t = qflocalinvariants(ZM_neg(G1),P);
+      for (i = 3; i < lg(P); i++) W[i] = ucoeff(t,i,1);
+    }
+    else
+    {
+      long s = signe(dQ) == signe(d)? 1: -1;
+      GEN t;
+      if (odd((n-3)/2)) s = -s;
+      t = s > 0? utoipos(8): utoineg(8);
+      for (i = 3; i < lg(P); i++)
+        W[i] = hilbertii(t, gel(P,i), gel(P,i)) > 0;
+    }
+    /* for p = 2, the choice is fixed from the product formula */
+    W[2] = Flv_sum(W, 2);
+
+    /* Construction of the 2-class group of discriminant dQ until some product
+     * of the generators gives the desired invariants. */
+    factdP = vecsplice(P, 1); lfactdP =  lg(factdP);
+    factdE = cgetg(lfactdP, t_VECSMALL);
+    for (i = 1; i < lfactdP; i++) factdE[i] = Z_pval(dQ, gel(factdP,i));
+    factdE[1]++;
+    /* factdP,factdE = factor(2|dQ|), P = factor(-2|dQ|)[,1] */
+    Q = quadclass2(dQ, factdP,factdE, P, W, n == 4);
+    /* Build a form of dim=n+2 potentially unimodular */
+    G2 = shallowmatconcat(diagonal_shallow(mkvec2(G1,ZM_neg(Q))));
+    /* Minimization of G2 */
+    detG2 = mulii(d, ZM_det(Q));
+    for (i = 1; i < lfactdP; i++) factdE[i] = Z_pval(detG2, gel(factdP,i));
+    /* factdP,factdE = factor(|det G2|) */
+    Min = qfminimize(G2, factdP,factdE);
+    M2 = gel(Min,2);
+    G2 = gel(Min,1);
+  }
+  /* |det(G2)| = 1, find a totally isotropic subspace for G2 */
+  solG2 = qflllgram_indefgoon(G2);
+  /* G2 must have a subspace of solutions of dimension > codim */
+  dim = codim+2;
+  while(gequal0(principal_minor(gel(solG2,1), dim))) dim ++;
+  solG2 = vecslice(gel(solG2,2), 1, dim-1);
+
+  if (!M2)
+    solG1 = solG2;
+  else
+  { /* solution of G1 is simultaneously in solG2 and x[n+1] = x[n+2] = 0*/
+    GEN K;
+    solG1 = RgM_mul(M2,solG2);
+    K = ker(rowslice(solG1,n+1,n+2));
+    solG1 = RgM_mul(rowslice(solG1,1,n), K);
+  }
+  if (!M1)
+    sol = solG1;
+  else
+  { /* solution of G1 is simultaneously in solG2 and x[n] = 0 */
+    GEN K;
+    sol = RgM_mul(M1,solG1);
+    K = ker(rowslice(sol,n,n));
+    sol = RgM_mul(rowslice(sol,1,n-1), K);
+  }
+  sol = Q_primpart(RgM_mul(M, sol));
+  if (lg(sol) == 2) sol = gel(sol,1);
+  return sol;
+}
+GEN
+qfsolve(GEN G)
+{
+  pari_sp av = avma;
+  return gerepilecopy(av, qfsolve_i(G));
+}
+
+/* G is a symmetric 3x3 matrix, and sol a solution of sol~*G*sol=0.
+ * Returns a parametrization of the solutions with the good invariants,
+ * as a matrix 3x3, where each line contains
+ * the coefficients of each of the 3 quadratic forms.
+ * If fl!=0, the fl-th form is reduced. */
+GEN
+qfparam(GEN G, GEN sol, long fl)
+{
+  pari_sp av = avma;
+  GEN U, G1, G2, a, b, c, d, e;
+  long n, tx = typ(sol);
+
+  if (typ(G) != t_MAT) pari_err_TYPE("qfsolve", G);
+  if (!is_vec_t(tx)) pari_err_TYPE("qfsolve", G);
+  if (tx == t_VEC) sol = shallowtrans(sol);
+  n = lg(G)-1;
+  if (n == 0) pari_err_DOMAIN("qfsolve", "dimension" , "=", gen_0, G);
+  if (n != nbrows(G) || n != 3 || lg(sol) != 4) pari_err_DIM("qfsolve");
+  G = Q_primpart(G); RgM_check_ZM(G,"qfsolve");
+  check_symmetric(G);
+  sol = Q_primpart(sol); RgV_check_ZV(sol,"qfsolve");
+  /* build U such that U[,3] = sol, and |det(U)| = 1 */
+  U = completebasis(sol,1);
+  G1 = qf_apply_ZM(G,U); /* G1 has a 0 at the bottom right corner */
+  a = shifti(gcoeff(G1,1,2),1);
+  b = shifti(negi(gcoeff(G1,1,3)),1);
+  c = shifti(negi(gcoeff(G1,2,3)),1);
+  d = gcoeff(G1,1,1);
+  e = gcoeff(G1,2,2);
+  G2 = mkmat3(mkcol3(b,gen_0,d), mkcol3(c,b,a), mkcol3(gen_0,c,e));
+  sol = ZM_mul(U,G2);
+  if (fl)
+  {
+    GEN v = row(sol,fl);
+    a = gel(v,1);
+    b = gmul2n(gel(v,2),-1);
+    c = gel(v,3);
+    U = qflllgram_indef(mkmat2(mkcol2(a,b),mkcol2(b,c)), 1);
+    U = gel(U,2);
+    a = gcoeff(U,1,1); b = gcoeff(U,1,2);
+    c = gcoeff(U,2,1); d = gcoeff(U,2,2);
+    U = mkmat3(mkcol3(sqri(a),mulii(a,c),sqri(c)),
+               mkcol3(shifti(mulii(a,b),1), addii(mulii(a,d),mulii(b,c)),
+                      shifti(mulii(c,d),1)),
+               mkcol3(sqri(b),mulii(b,d),sqri(d)));
+    sol = ZM_mul(sol,U);
+  }
+  return gerepileupto(av, sol);
+}
diff --git a/src/basemath/random.c b/src/basemath/random.c
index 969013c..2d16d1d 100644
--- a/src/basemath/random.c
+++ b/src/basemath/random.c
@@ -25,90 +25,125 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 /* Adapted from xorgens.c version 3.04, Richard P. Brent, 20060628 (GPL).
  * 32-bit or 64-bit integer random number generator with period at
  * least 2**4096-1. It is assumed that "ulong" is a 32-bit or 64-bit integer */
-static THREAD ulong xorgen_w;
-static THREAD int xorgen_i;
 
-#ifdef LONG_IS_64BIT /* weyl = odd approximation to 2^BIL*(sqrt(5)-1)/2. */
-  static const ulong weyl = 0x61c8864680b583ebUL;
-  static const int ws = 27, r = 64,  s = 53, a = 33, b = 26, c = 27, d = 29;
-  static THREAD ulong state[64]; /* size r */
+#ifdef LONG_IS_64BIT
+  typedef ulong u64;
+  static THREAD ulong state[64];
+  #define u64state(i)      ((u64)state[(i)])
+  #define u64stateset(i,x) state[(i)] = (ulong) (x);
 #else
-  static const ulong weyl = 0x61c88647UL;
-  static const int ws = 16, r = 128, s = 95, a = 17, b = 12, c = 13, d = 15;
-  static THREAD ulong state[128]; /* size r */
+  typedef unsigned long long u64;
+  static THREAD ulong state[128];
+  #define u64state(i)      _32to64(state[2*(i)],state[2*(i)+1])
+  #define u64stateset(i,x) _64to32(x,state+2*(i),state+2*(i)+1)
+static u64
+_32to64(ulong a, ulong b) { u64 v = a; return (v<<32)|b; }
+static void
+_64to32(u64 v, ulong *a, ulong *b) { *a = v>>32; *b = v&0xFFFFFFFF; }
 #endif
+static THREAD u64 xorgen_w;
+static THREAD int xorgen_i;
+/* weyl = odd approximation to 2^64*(sqrt(5)-1)/2. */
+static const u64 weyl = (((u64)0x61c88646U)<<32)|((u64)0x80b583ebU);
+
+static u64
+block(void)
+{
+  const int r = 64;
+  const int a = 33, b = 26, c = 27, d = 29, s = 53;
+  u64 t, v, w;
+  xorgen_i = (xorgen_i+1)&(r-1);
+  t = u64state(xorgen_i);
+  v = u64state((xorgen_i+(r-s))&(r-1));   /* index is (i-s) mod r */
+  t ^= t<<a; t ^= t>>b;                   /* (I + L^a)(I + R^b) */
+  v ^= v<<c; v ^= v>>d;                   /* (I + L^c)(I + R^d) */
+  w = t^v;
+  u64stateset(xorgen_i, w);               /* update circular array */
+  return w;
+}
 
 static void
 init_xor4096i(ulong seed)
 {
-  ulong t, v = seed;  /* v must be nonzero */
+  const int r = 64;
+  u64 v = seed; /* v must be nonzero */
   int k;
 
-  for (k = BITS_IN_LONG; k > 0; k--) {/* Avoid correlations for close seeds */
-    v ^= v<<10; v ^= v>>15;      /* Recurrence has period 2**BIL -1 */
+  for (k = r; k > 0; k--) {/* avoid correlations for close seeds */
+    v ^= v<<10; v ^= v>>15; /* recurrence has period 2**64-1 */
     v ^= v<<4;  v ^= v>>13;
   }
-  for (xorgen_w = v, k = 0; k < r; k++) { /* Initialise circular array */
+  for (xorgen_w = v, k = 0; k < r; k++) { /* initialise circular array */
     v ^= v<<10; v ^= v>>15;
     v ^= v<<4;  v ^= v>>13;
-    state[k] = v + (xorgen_w+=weyl);
-  }
-  for (xorgen_i = r-1, k = 4*r; k > 0; k--) { /* Discard first 4*r results */
-    t = state[xorgen_i = (xorgen_i+1)&(r-1)]; t ^= t<<a;  t ^= t>>b;
-    v = state[(xorgen_i+(r-s))&(r-1)];        v ^= v<<c;  v ^= v>>d;
-    state[xorgen_i] = t^v;
+    u64stateset(k, v + (xorgen_w+=weyl));
   }
+  /* discard first 4*r results */
+  for (xorgen_i = r-1, k = 4*r; k > 0; k--) (void)block();
 }
 
 void pari_init_rand(void) { init_xor4096i(1); }
 
+static u64
+rand64(void)
+{
+  u64 v = block();
+  xorgen_w += weyl; /* update Weyl generator */
+  return v + (xorgen_w ^ (xorgen_w>>27));
+}
+
 /* One random number uniformly distributed in [0..2**BIL) is returned, where
  * BIL = 8*sizeof(ulong) = 32 or 64. */
 ulong
-pari_rand(void)
-{
-  ulong t, v;
-
-  t = state[xorgen_i = (xorgen_i+1)&(r-1)];
-  v = state[(xorgen_i+(r-s))&(r-1)];   /* Index is (xorgen_i-s) mod r */
-  t ^= t<<a;  t ^= t>>b;               /* (I + L^a)(I + R^b) */
-  v ^= v<<c;  v ^= v>>d;               /* (I + L^c)(I + R^d) */
-  state[xorgen_i] = (v ^= t);          /* Update circular array */
-  xorgen_w += weyl;                    /* Update Weyl generator */
-  return v + (xorgen_w ^ (xorgen_w>>ws));
-}
+pari_rand(void) { return rand64(); }
 
 void
-setrand(GEN seed) {
-  switch (typ(seed))
-  {
-    case t_VECSMALL:
-    {
-      GEN xd = seed+1;
-      long i;
-      if (lg(seed) != r+2 + 1) break;
-      for (i = 0; i < r; i++) state[i] = xd[i];
-      xorgen_i = xd[i++];
-      xorgen_w = xd[i++];
-      return;
-    }
-    case t_INT: if (signe(seed) > 0) { init_xor4096i( itou(seed) ); return; }
-  }
-  pari_err_TYPE("setrand",seed);
+setrand(GEN x)
+{
+  const int r2 = sizeof(state)/sizeof(ulong);
+  ulong useed;
+  long i;
+  GEN xp;
+  if (typ(x)!=t_INT)
+    pari_err_TYPE("setrand",x);
+  if (signe(x) <= 0) return;
+  useed = itou_or_0(x);
+  if (useed > 0) { init_xor4096i(useed); return; }
+  if (lgefint(x)!=2+r2+2+(r2==128))
+    pari_err_TYPE("setrand",x);
+  xp = int_LSW(x);
+  for (i = 0; i < r2; i++) { state[i] = *xp; xp = int_nextW(xp); }
+#ifdef LONG_IS_64BIT
+  xorgen_w = *xp; xp = int_nextW(xp);
+#else
+  xorgen_w = _32to64(*xp, *int_nextW(xp)); xp = int_nextW(int_nextW(xp));
+#endif
+  xorgen_i =  (*xp) & 63;
 }
+
 GEN
-getrand(void) {
-  GEN x, xd;
+getrand(void)
+{
+  const int r2 = sizeof(state)/sizeof(ulong);
+  GEN x;
+  ulong *xp;
   long i;
   if (xorgen_i < 0) init_xor4096i(1);
 
-  x = cgetg(r+2 + 1, t_VECSMALL); xd = x+1;
-  for (i = 0; i < r; i++) xd[i] = state[i];
-  xd[i++] = xorgen_i;
-  xd[i++] = xorgen_w;
-  return x;
+  x = cgetipos(2+r2+2+(r2==128)); xp = (ulong *) int_LSW(x);
+  for (i = 0; i < r2; i++) { *xp = state[i]; xp = int_nextW(xp); }
+#ifdef LONG_IS_64BIT
+  *xp = xorgen_w; xp = int_nextW(xp);
+#else
+  _64to32(xorgen_w, xp, int_nextW(xp)); xp = int_nextW(int_nextW(xp));
+#endif
+  *xp = xorgen_i? xorgen_i: 64; return x;
 }
 
+/* assume 0 <= k <= BITS_IN_LONG. Return uniform random 0 <= x < (1<<k) */
+long
+random_bits(long k) { return rand64() >> (64-k); }
+
 /********************************************************************/
 /*                                                                  */
 /*                         GENERIC ROUTINES                         */
@@ -121,43 +156,91 @@ random_Fl(ulong n)
 {
   ulong d;
   int shift;
+#ifdef LONG_IS_64BIT
+  int SHIFT = 0;
+#else
+  int SHIFT = 32;
+#endif
 
   if (n == 1) return 0;
 
   shift = bfffo(n); /* 2^(BIL-shift) > n >= 2^(BIL-shift-1)*/
   /* if N a power of 2, increment shift. No reject */
-  if ((n << shift) == HIGHBIT) return pari_rand() >> (shift+1);
+  if ((n << shift) == HIGHBIT) return rand64() >> (SHIFT+shift+1);
   for (;;) {
-    d = pari_rand() >> shift; /* d < 2^(BIL-shift) uniformly distributed */
-    /* reject strategy: proba success = n 2^(shift-BIL), in [1/2, 1[ */
+    d = rand64() >> (SHIFT+shift); /* d < 2^(64-shift) uniformly distributed */
+    /* reject strategy: proba success = n 2^(shift-64), in [1/2, 1[ */
     if (d < n) return d;
   }
 }
 
-/* assume N > 0, see random_Fl() for algorithm */
+/* assume N > 0, see random_Fl() for algorithm. Make sure that 32-bit and
+ * 64-bit architectures produce the same integers (consuming random bits
+ * by packets of 64) */
 GEN
 randomi(GEN N)
 {
   long lx = lgefint(N);
-  GEN d, NMSW;
-  pari_sp av;
+  GEN x, d;
   int shift;
 
   if (lx == 3) return utoi( random_Fl(N[2]) );
 
-  NMSW = int_MSW(N); shift = bfffo(*NMSW);
-  if (((ulong)*NMSW << shift) == HIGHBIT)
-  { /* if N a power of 2, increment shift */
-    for (d = int_LSW(N); !*d; d = int_nextW(d)) /* empty */;
-    if (d == NMSW && ++shift == BITS_IN_LONG) { shift = 0; lx--; }
+  shift = bfffo(*int_MSW(N));
+  /* if N a power of 2, increment shift */
+  if (Z_ispow2(N) && ++shift == BITS_IN_LONG) { shift = 0; lx--; }
+  x = cgetipos(lx);
+  for (;;) {
+    GEN y, MSW = int_MSW(x), STOP = MSW;
+#ifdef LONG_IS_64BIT
+    for (d = int_LSW(x); d != STOP; d = int_nextW(d)) *d = rand64();
+    *d = rand64() >> shift;
+#else
+    if (!odd(lx)) STOP = int_precW(STOP);
+    /* STOP points to where MSW would in 64-bit */
+    for (d = int_LSW(x); d != STOP; d = int_nextW(d))
+    {
+      ulong a, b; _64to32(rand64(), &a,&b);
+      *d = b; d = int_nextW(d);
+      *d = a;
+    }
+    {
+      ulong a, b; _64to32(rand64() >> shift, &a,&b);
+      if (d == MSW) /* 32 bits needed */
+        *d = a;
+      else
+      { /* 64 bits needed */
+        *d = b; d = int_nextW(d);
+        *d = a;
+      }
+    }
+#endif
+    y = int_normalize(x, 0);
+    if (absi_cmp(y, N) < 0) return y;
   }
-  for (av = avma;; avma = av) {
-    GEN x = cgetipos(lx), xMSW = int_MSW(x);
-    for (d = int_LSW(x); d != xMSW; d = int_nextW(d)) *d = pari_rand();
-    *d = pari_rand() >> shift;
-    x = int_normalize(x, 0);
-    if (absi_cmp(x, N) < 0) return x;
+}
+
+GEN
+random_F2x(long d, long vs)
+{
+  long i, l = nbits2lg(d+1), n = l-1;
+  GEN y = cgetg(l,t_VECSMALL); y[1] = vs;
+#ifdef LONG_IS_64BIT
+  for (i=2; i<=n; i++) y[i] = rand64();
+#else
+  for (i=2; i<=n; i++)
+  {
+    u64 v = rand64();
+    y[i] = v & 0xFFFFFFFFUL;
+    i++;
+    if (i > n) break;
+    y[i] = v>>32;
+    i++;
+    if (i > n) { v = rand64(); break; }
   }
+#endif
+  y[n] &= (1UL<<remsBIL(d))-1UL;
+  return F2x_renormalize(y,l);
 }
 
 GEN
diff --git a/src/basemath/rootpol.c b/src/basemath/rootpol.c
index 3694d5b..9714adc 100644
--- a/src/basemath/rootpol.c
+++ b/src/basemath/rootpol.c
@@ -1006,7 +1006,7 @@ parameters(GEN p, long *LMAX, double *mu, double *gamma,
 {
   GEN q, pc, Omega, A, RU, prim, g, ONE,TWO;
   long n = degpol(p), bit, NN, K, i, j, Lmax;
-  pari_sp av2, av = avma, lim = stack_lim(av, 1);
+  pari_sp av2, av = avma;
 
   bit = gexpo(p) + (long)param2+8;
   Lmax = 4; while (Lmax <= n) Lmax <<= 1;
@@ -1048,7 +1048,7 @@ parameters(GEN p, long *LMAX, double *mu, double *gamma,
     else
       for (j=0; j<Lmax; j++) g = addrr(g, divrr(ONE, abs_update(gel(A,j),mu)));
     RU = gmul(RU, prim);
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"parameters");
       gerepileall(av2,2, &g,&RU);
@@ -1154,14 +1154,14 @@ static GEN
 refine_H(GEN F, GEN G, GEN HH, long bit, long Sbit)
 {
   GEN H = HH, D, aux;
-  pari_sp ltop = avma, lim = stack_lim(ltop, 1);
+  pari_sp ltop = avma;
   long error, i, bit1, bit2;
 
   D = Rg_RgX_sub(gen_1, RgX_rem(RgX_mul(H,G),F)); error = gexpo(D);
   bit2 = bit + Sbit;
   for (i=0; error>-bit && i<NEWTON_MAX && error<=0; i++)
   {
-    if (low_stack(lim, stack_lim(ltop,1)))
+    if (gc_needed(ltop,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"refine_H");
       gerepileall(ltop,2, &D,&H);
@@ -1185,7 +1185,7 @@ refine_F(GEN p, GEN *F, GEN *G, GEN H, long bit, double gamma)
 {
   GEN f0, FF, GG, r, HH = H;
   long error, i, bit1 = 0, bit2, Sbit, Sbit2,  enh, normF, normG, n = degpol(p);
-  pari_sp av = avma, lim = stack_lim(av, 1);
+  pari_sp av = avma;
 
   FF = *F; GG = RgX_divrem(p, FF, &r);
   error = gexpo(r); if (error <= -bit) error = 1-bit;
@@ -1198,7 +1198,7 @@ refine_F(GEN p, GEN *F, GEN *G, GEN H, long bit, double gamma)
   for (i=0; error>-bit && i<NEWTON_MAX && error<=0; i++)
   {
     if (bit1 == bit2 && i >= 2) { Sbit += n; Sbit2 += n; bit2 += n; }
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"refine_F");
       gerepileall(av,4, &FF,&GG,&r,&HH);
@@ -1308,7 +1308,7 @@ conformal_pol(GEN p, GEN a, long bit)
 {
   GEN z, r, ma = gneg(a), ca = gconj(a);
   long n = degpol(p), i;
-  pari_sp av = avma, lim = stack_lim(av,2);
+  pari_sp av = avma;
 
   z = mkpoln(2, ca, negr(myreal_1(bit)));
   r = scalarpol(gel(p,2+n), 0);
@@ -1318,7 +1318,7 @@ conformal_pol(GEN p, GEN a, long bit)
     r = gadd(r, gmul(z, gel(p,2+i)));
     if (i == 0) return gerepileupto(av, r);
     z = addmulXn(gmul(z,ca), gneg(z), 1); /* z *= conj(a)X - 1 */
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"conformal_pol");
       gerepileall(av,2, &r,&z);
@@ -1788,15 +1788,14 @@ split_complete(GEN p, long bit, GEN roots_pol)
 }
 
 static GEN
-quickabs(GEN x)
+quicktofp(GEN x)
 {
   const long prec = DEFAULTPREC;
-  GEN y;
   switch(typ(x))
   {
-    case t_INT: y = itor(x, prec); setabssign(y); return y;
-    case t_REAL: y = rtor(x, prec); setabssign(y); return y;
-    case t_FRAC: y = fractor(x, prec); setabssign(y); return y;
+    case t_INT: return itor(x, prec);
+    case t_REAL: return rtor(x, prec);
+    case t_FRAC: return fractor(x, prec);
     case t_COMPLEX: {
       GEN a = gel(x,1), b = gel(x,2);
       /* avoid problem with 0, e.g. x = 0 + I*1e-100. We don't want |x| = 0. */
@@ -1805,32 +1804,75 @@ quickabs(GEN x)
       a = cxcompotor(a, prec);
       b = cxcompotor(b, prec); return sqrtr(addrr(sqrr(a), sqrr(b)));
     }
-    default: pari_err_TYPE("quickabs",x);
+    default: pari_err_TYPE("quicktofp",x);
       return NULL;/*not reached*/
   }
 
 }
 
-/* bound ln |largest root of p| */
+/* bound log_2 |largest root of p| (Fujiwara's bound) */
 double
-cauchy_bound(GEN p)
+fujiwara_bound(GEN p)
 {
   pari_sp av = avma;
   long i, n = degpol(p);
-  GEN invlc;
-  double Lmax = -pariINFINITY;
-
-  if (n <= 0) pari_err_CONSTPOL("cauchy_bound");
-  invlc = invr( quickabs(gel(p,n+2)) ); /* 1 / |lc(p)| */
-  for (i = 0; i < n; i++)
+  GEN cc;
+  double loglc, Lmax;
+
+  if (n <= 0) pari_err_CONSTPOL("fujiwara_bound");
+  loglc = mydbllog2r( quicktofp(gel(p,n+2)) ); /* log_2 |lc(p)| */
+  cc = gel(p, 2);
+  if (gequal0(cc))
+    Lmax = -pariINFINITY-1;
+  else
+    Lmax = (mydbllog2r(quicktofp(cc)) - loglc - 1) / n;
+  for (i = 1; i < n; i++)
   {
     GEN y = gel(p,i+2);
     double L;
     if (gequal0(y)) continue;
-    L = mydbllogr(mulrr(quickabs(y), invlc)) / (n-i);
+    L = (mydbllog2r(quicktofp(y)) - loglc) / (n-i);
     if (L > Lmax) Lmax = L;
   }
-  avma = av; return Lmax + LOG2;
+  avma = av; return Lmax + 1;
+}
+
+/* Fujiwara's bound, real roots. Based on the following remark: if
+ *   p = x^n + sum a_i x^i and q = x^n + sum min(a_i,0)x^i
+ * then for all x >= 0, p(x) >= q(x). Thus any bound for the (positive) roots
+ * of q is a bound for the positive roots of p. */
+double
+fujiwara_bound_real(GEN p, long sign)
+{
+  pari_sp av = avma;
+  GEN x;
+  long n = degpol(p), i, signodd, signeven;
+  double fb;
+  if (n <= 0) pari_err_CONSTPOL("fujiwara_bound");
+  x = shallowcopy(p);
+  if (gsigne(gel(x, n+2)) > 0)
+  {
+    signeven = 1;
+    signodd = sign;
+  }
+  else
+  {
+    signeven = -1;
+    signodd = -sign;
+  }
+  for (i = 0; i < n; i++)
+  {
+    if ((n - i) % 2)
+    {
+      if (gsigne(gel(x, i+2)) == signodd ) gel(x, i+2) = gen_0;
+    }
+    else
+    {
+      if (gsigne(gel(x, i+2)) == signeven) gel(x, i+2) = gen_0;
+    }
+  }
+  fb = fujiwara_bound(x);
+  avma = av; return fb;
 }
 
 static GEN
@@ -1914,7 +1956,7 @@ all_roots(GEN p, long bit)
   pari_sp av;
 
   pd = RgX_deflate_max(p, &h); lc = leading_term(pd);
-  e = (long)((2/LOG2) * cauchy_bound(pd)); if (e < 0) e = 0;
+  e = (long)(2 * fujiwara_bound(pd)); if (e < 0) e = 0;
   bit0 = bit + gexpo(pd) - gexpo(lc) + (long)log2(n/h)+1+e;
   bit2 = bit0; e = 0;
   for (av=avma,i=1;; i++,avma=av)
@@ -2163,3 +2205,733 @@ QX_complex_roots(GEN p, long l)
   L = all_roots(Q_primpart(p), bit);
   return gerepileupto(av, clean_roots(L, l, bit, 1));
 }
+
+/********************************************************************/
+/**                                                                **/
+/**                REAL ROOTS OF INTEGER POLYNOMIAL                **/
+/**                                                                **/
+/********************************************************************/
+
+/* Count sign changes in the coefficients of (x+1)^deg(P)*P(1/(x+1))
+ * The inversion is implicit (we take coefficients backwards) */
+static long
+X2XP1(GEN P, long deg, GEN *Premapped)
+{
+  pari_sp av = avma;
+  GEN v = shallowcopy(P);
+  long i, j, vlim, nb, s, s2;
+  char flag;
+
+  vlim = deg+2;
+  nb = 0;
+  i = 0;
+  do
+  {
+    for (j = 2; j < vlim; j++) gel(v, j+1) = addii(gel(v, j), gel(v, j+1));
+    s = -signe(gel(v, vlim));
+    vlim--;
+    i++;
+  }
+  while (!s);
+  if (vlim != deg + 1 && Premapped) setlg(v, vlim + 2);
+
+  for (; i <= deg - 1; i++)
+  {
+    s2 = -signe(gel(v, 2));
+    flag = (s2 == s);
+    for (j = 2; j < vlim; j++)
+    {
+      gel(v, j+1) = addii(gel(v, j), gel(v, j+1));
+      if (flag) flag = (s2 != signe(gel(v, j+1)));
+    }
+    if (s == signe(gel(v, vlim)))
+    {
+      nb++;
+      if (nb >= 2) { avma = av; return 2; }
+      s = -s;
+    }
+    if (gc_needed(av, 3))
+    {
+      if (!Premapped) setlg(v, vlim);
+      v = gerepileupto(av, v);
+      if (DEBUGMEM > 1) pari_warn(warnmem, "X2XP1");
+    }
+    if (flag && !Premapped) goto END;
+    vlim--;
+  }
+  if (s == signe(gel(v, vlim))) nb++;
+END:
+  if (Premapped && nb == 1)
+    *Premapped = gerepileupto(av, v);
+  else
+    avma = av;
+  return nb;
+}
+
+static long
+_intervalcmp(GEN x, GEN y)
+{
+  if (typ(x) == t_VEC) x = gel(x, 1);
+  if (typ(y) == t_VEC) y = gel(y, 1);
+  return gcmp(x, y);
+}
+
+static GEN
+_gen_nored(void *E, GEN x) { (void)E; return x; }
+static GEN
+_mp_add(void *E, GEN x, GEN y) { (void)E; return mpadd(x, y); }
+static GEN
+_mp_mul(void *E, GEN x, GEN y) { (void)E; return mpmul(x, y); }
+static GEN
+_mp_sqr(void *E, GEN x) { (void)E; return mpsqr(x); }
+static GEN
+_gen_one(void *E) { (void)E; return gen_1; }
+static GEN
+_gen_zero(void *E) { (void)E; return gen_0; }
+
+static struct bb_algebra mp_algebra = { _gen_nored,_mp_add,_mp_mul,_mp_sqr,_gen_one,_gen_zero };
+
+static GEN
+_mp_cmul(void *E, GEN P, long a, GEN x) {(void)E; return mpmul(gel(P,a+2), x);}
+
+/* Split the polynom P in two parts, each with unique sign.
+ * Moreover compute the two parts of the derivative of P. */
+static long
+split_polynoms(GEN P, long deg, long s0, GEN *Pp, GEN *Pm, GEN *Pprimep, GEN *Pprimem)
+{
+  long i, degneg, v = evalvarn(varn(P));
+  for(i=1; i <= deg; i++) if (signe(gel(P, i+2)) != s0) break;
+  degneg = i;
+  *Pm = cgetg(degneg + 2, t_POL);
+  (*Pm)[1] = v;
+  *Pprimem = cgetg(degneg + 1, t_POL);
+  (*Pprimem)[1] = v;
+  for(i=0; i < degneg; i++)
+  {
+    GEN elt = gel(P, i+2);
+    gel(*Pm, i+2) = elt;
+    if (i) gel(*Pprimem, i+1) = mului(i, elt);
+  }
+  *Pp = cgetg(deg - degneg + 3, t_POL);
+  (*Pp)[1] = v;
+  *Pprimep = cgetg(deg - degneg + 3, t_POL);
+  (*Pprimep)[1] = v;
+  for(i=degneg; i <= deg; i++)
+  {
+    GEN elt = gel(P, i+2);
+    gel(*Pp, i+2-degneg) = elt;
+    gel(*Pprimep, i+2-degneg) = mului(i, elt);
+  }
+  *Pm = normalizepol_lg(*Pm, degneg+2);
+  *Pprimem = normalizepol_lg(*Pprimem, degneg+1);
+  *Pp = normalizepol_lg(*Pp, deg-degneg+3);
+  *Pprimep = normalizepol_lg(*Pprimep, deg-degneg+3);
+  return degpol(*Pm) + 1;
+}
+
+static GEN
+bkeval_single_power(long d, GEN V)
+{
+  long mp = lg(V) - 2;
+  if (d > mp) return gmul(gpowgs(gel(V, mp+1), d/mp), gel(V, (d%mp)+1));
+  return gel(V, d+1);
+}
+
+static GEN
+splitpoleval(GEN Pp, GEN Pm, GEN pows, long deg, long degneg, long bitprec)
+{
+  GEN vp = gen_bkeval_powers(Pp, deg-degneg, pows, NULL, &mp_algebra, _mp_cmul);
+  GEN vm = gen_bkeval_powers(Pm, degneg-1, pows, NULL, &mp_algebra, _mp_cmul);
+  GEN xa = bkeval_single_power(degneg, pows);
+  GEN r;
+  vp = gmul(vp, xa);
+  r = gadd(vp, vm);
+  if (expo(vp) - (signe(r) ? expo(r) : 0) > prec2nbits(realprec(vp)) - bitprec)
+    return NULL;
+  return r;
+}
+
+/* Newton for polynom P. One solution between 0 and infinity, P' has also at
+ * most one zero. P is almost certainly without zero coefficients. */
+static GEN
+polsolve(GEN P, long bitprec)
+{
+  pari_sp av = avma;
+  GEN Pp, Pm, Pprimep, Pprimem, pows;
+  GEN Pprime, Pprime2;
+  GEN ra, rb, rc, rcold = NULL, Pc, Ppc;
+  long deg = degpol(P), degneg, rt;
+  long s0, cprec = DEFAULTPREC, prec = nbits2prec(bitprec);
+  long bitaddprec, addprec;
+  long expoold = LONG_MAX, iter;
+  if (deg == 1)
+  {
+    ra = negr(divrr(itor(gel(P, 2), bitprec), itor(gel(P, 3), bitprec)));
+    return gerepileuptoleaf(av, ra);
+  }
+  Pprime = ZX_deriv(P); Pprime2 = ZX_deriv(Pprime);
+  bitaddprec = 1 + 2*expu(deg); addprec = nbits2prec(bitaddprec);
+  s0 = signe(gel(P, 2));
+  degneg = split_polynoms(P, deg, s0, &Pp, &Pm, &Pprimep, &Pprimem);
+  rt = maxss(degneg, brent_kung_optpow(maxss(deg-degneg, degneg-1), 2, 1));
+  {
+    /* Optimized Cauchy bound */
+    GEN summin = gen_0, absmaj;
+    long i;
+
+    absmaj = gel(P, 2);
+    for(i=1; i < degneg; i++)
+    {
+      GEN elt = gel(P, i+2);
+      if (absi_cmp(absmaj, elt) < 0) absmaj = elt;
+    }
+    summin = gel(P, i+2);
+    while (++i <= deg) summin = addii(summin, gel(P, i+2));
+    rb = subsr(1, rdivii(absmaj, summin, cprec));
+    do
+    {
+      pows = gen_powers(rb, rt, 1, NULL, _mp_sqr, _mp_mul, _gen_one);
+      Pc = splitpoleval(Pp, Pm, pows, deg, degneg, bitaddprec);
+      if (!Pc) { cprec++; rb = rtor(rb, cprec); continue; }
+      if (signe(Pc) != s0) break;
+      shiftr_inplace(rb,1);
+    }
+    while (1);
+  }
+  ra = NULL;
+  iter = 0;
+  while (1)
+  {
+    GEN wdth;
+    iter++;
+    if (ra)
+      rc = shiftr(addrr(ra, rb), -1);
+    else
+      rc = shiftr(rb, -1);
+    do
+    {
+      pows = gen_powers(rc, rt, 1, NULL, _mp_sqr, _mp_mul, _gen_one);
+      Pc = splitpoleval(Pp, Pm, pows, deg, degneg, bitaddprec+2);
+      if (Pc) break;
+      cprec++; rc = rtor(rc, cprec);
+    } while (1);
+    if (signe(Pc) == s0)
+      ra = rc;
+    else
+      rb = rc;
+    if (!ra) continue;
+    wdth = subrr(rb, ra);
+    if (!(iter % 8))
+    {
+      GEN m1 = poleval(Pprime, ra), M2;
+      if (signe(m1) == s0) continue;
+      M2 = poleval(Pprime2, rb);
+      if (absr_cmp(gmul(M2, wdth), shiftr(m1, 1)) > 0) continue;
+      break;
+    }
+    else if (gexpo(wdth) <= -bitprec)
+      break;
+  }
+  rc = rb;
+  iter = 0;
+  while (1)
+  {
+    long exponew;
+    GEN dist;
+    iter++;
+    rcold = rc;
+    pows = gen_powers(rc, rt, 1, NULL, _mp_sqr, _mp_mul, _gen_one);
+    Ppc = splitpoleval(Pprimep, Pprimem, pows, deg-1, degneg-1, bitaddprec+4);
+    if (Ppc)
+      Pc = splitpoleval(Pp, Pm, pows, deg, degneg, bitaddprec+4);
+    if (!Ppc || !Pc)
+    {
+      if (cprec >= prec+addprec)
+        cprec++;
+      else
+        cprec = minss(2*cprec, prec+addprec);
+      rc = rtor(rc, cprec); /* Backtrack one step */
+      continue;
+    }
+    dist = divrr(Pc, Ppc);
+    rc = subrr(rc, dist);
+    if (cmprr(ra, rc) > 0 || cmprr(rb, rc) < 0)
+    {
+      if (cprec >= prec+addprec) break;
+      cprec = minss(2*cprec, prec+addprec);
+      rc = rtor(rcold, cprec); /* Backtrack one step */
+      continue;
+    }
+    if (expoold == LONG_MAX) { expoold = expo(dist); continue; }
+    exponew = expo(dist);
+    if (exponew < -bitprec - 1)
+    {
+      if (cprec >= prec+addprec) break;
+      cprec = minss(2*cprec, prec+addprec);
+      rc = rtor(rc, cprec);
+      continue;
+    }
+    if (exponew > expoold - 2)
+    {
+      if (cprec >= prec+addprec) break;
+      cprec = minss(2*cprec, prec+addprec);
+      rc = rtor(rc, cprec);
+      expoold = LONG_MAX;
+      continue;
+    }
+    expoold = exponew;
+  }
+  return gerepileuptoleaf(av, rtor(rc, prec));
+}
+
+static GEN
+usp(GEN Q0, long deg, long *nb_donep, long flag, long bitprec)
+{
+  pari_sp av;
+  GEN Q, sol;
+  long nb_todo, nbr = 0, ind, deg0, indf, i, k, nb, j;
+  long listsize = 64, nb_done = 0;
+  GEN c, Lc, Lk;
+
+  av = avma;
+
+  sol = const_col(deg, gen_0);
+  deg0 = deg;
+  Lc = const_vec(listsize, gen_0);
+  Lk = cgetg(listsize+1, t_VECSMALL);
+  c = gen_0;
+  k = Lk[1] = 0;
+  ind = 1; indf = 2;
+  Q = gcopy(Q0);
+
+  nb_todo = 1;
+  while (nb_todo)
+  {
+    GEN nc = gel(Lc, ind), Qremapped;
+    if (Lk[ind] == k + 1)
+    {
+      deg0 = deg;
+      setlg(Q0, deg + 3);
+      Q0 = ZX_rescale2n(Q0, 1);
+      Q = Q_primpart(Q0);
+      c = gen_0;
+    }
+
+    if (!equalii(nc, c)) Q = ZX_translate(Q, subii(nc, c));
+
+    k = Lk[ind];
+    c = nc;
+    ind++;
+    nb_todo--;
+
+    if (equalii(gel(Q, 2), gen_0))
+    {
+      GEN newsol = gmul2n(c, -k);
+      for (j = 1; j <= nbr; j++)
+        if (gequal(gel(sol, j), newsol)) break;
+      if (j > nbr) gel(sol, ++nbr) = newsol;
+
+      deg0--;
+      for (j = 2; j <= deg0 + 2; j++) gel(Q, j) = gel(Q, j+1);
+      setlg(Q, j);
+    }
+
+    nb = X2XP1(Q, deg0, flag == 1 ? &Qremapped : NULL);
+    nb_done++;
+
+    switch (nb)
+    {
+      case 0:
+        break;
+      case 1:
+        switch(flag)
+        {
+        case 0:
+          {
+            GEN low, hi;
+            low = gmul2n(c, -k);
+            hi  = gmul2n(addiu(c,1), -k);
+            gel(sol, ++nbr) = mkvec2(low, hi);
+          }
+          break;
+        case 1:
+          { /* Caveat emptor: Qremapped is the reciprocal polynomial */
+            GEN sr = polsolve(Qremapped, bitprec+1);
+            sr = divrr(sr, addsr(1, sr));
+            sr = gmul2n(addir(c, sr), -k);
+            gel(sol, ++nbr) = rtor(sr, nbits2prec(bitprec));
+          }
+          break;
+        default:
+          gel(sol, ++nbr) = gen_0;
+        }
+      break;
+
+      default:
+        if (indf + 2 > listsize)
+        {
+          if (ind>1)
+          {
+            for (i = ind; i < indf; i++)
+            {
+              gel(Lc, i-ind+1) = gel(Lc, i);
+              Lk[i-ind+1] = Lk[i];
+            }
+          indf -= ind-1; ind = 1;
+          }
+          if (indf + 2 > listsize)
+          {
+            listsize *= 2;
+            Lc = vec_lengthen(Lc, listsize);
+            Lk = vecsmall_lengthen(Lk, listsize);
+          }
+          for (i = indf; i <= listsize; i++) gel(Lc, i) = gen_0;
+        }
+        nc = shifti(c, 1);
+        gel(Lc, indf) = nc;
+        gel(Lc, indf + 1) = addis(nc, 1);
+        Lk[indf] = Lk[indf + 1] = k + 1;
+        indf += 2;
+        nb_todo += 2;
+    }
+
+    if (gc_needed(av, 2))
+    {
+      gerepileall(av, 6, &Q0, &Q, &c, &Lc, &Lk, &sol);
+      if (DEBUGMEM > 1) pari_warn(warnmem, "ZX_uspensky", avma);
+    }
+  }
+
+  setlg(sol, nbr+1);
+  *nb_donep += nb_done;
+  return gerepilecopy(av, sol);
+}
+
+static GEN
+ZX_uspensky_cst_pol(long nbz, long flag, long bitprec)
+{
+  switch(flag)
+  {
+    case 0:  return zerocol(nbz);
+    case 1:  retconst_col(nbz, real_0_bit(bitprec));
+    default: return utoi(nbz);
+  }
+}
+
+GEN
+ZX_uspensky(GEN P, GEN ab, long flag, long bitprec)
+{
+  pari_sp av = avma;
+  GEN a, b, sol = NULL, Pcur;
+  double fb;
+  long nbz, deg, nb_done = 0;
+
+  deg = degpol(P);
+  if (deg == 0) return flag <= 1 ? cgetg(1, t_COL) : gen_0;
+  if (ab)
+  {
+    if (typ(ab) == t_VEC)
+    {
+      if (lg(ab) != 3) pari_err_DIM("ZX_uspensky");
+      a = gel(ab, 1);
+      b = gel(ab, 2);
+    }
+    else
+    {
+      a = ab;
+      b = mkoo();
+    }
+  }
+  else
+  {
+    a = mkmoo();
+    b = mkoo();
+  }
+  switch (gcmp(a, b))
+  {
+    case 1: avma = av; return flag <= 1 ? cgetg(1, t_COL) : gen_0;
+    case 0:
+      if (typ(a) != t_INFINITY && gequal0(poleval(P, a)))
+      { avma = av; return flag <= 1 ? mkcolcopy(a): gen_1; }
+      else
+      { avma = av; return flag <= 1 ? cgetg(1, t_COL) : gen_0; }
+  }
+  nbz = ZX_valrem(P, &Pcur);
+  deg -= nbz;
+  if (!nbz) Pcur = P;
+  if (nbz && (gsigne(a) > 0 || gsigne(b) < 0)) nbz = 0;
+  if (deg == 0) { avma = av; return ZX_uspensky_cst_pol(nbz, flag, bitprec); }
+  if (deg == 1)
+  {
+    sol = gdiv(gneg(gel(Pcur, 2)), pollead(Pcur, -1));
+    if (gcmp(a, sol) > 0 || gcmp(sol, b) > 0)
+    {
+      avma = av;
+      return ZX_uspensky_cst_pol(nbz, flag, bitprec);
+    }
+    if (flag >= 2) { avma = av; return utoi(nbz+1); }
+    sol = concat(zerocol(nbz), mkcol(sol));
+    if (flag == 1) sol = RgC_gtofp(sol, nbits2prec(bitprec));
+    return gerepilecopy(av, sol);
+  }
+  switch(flag)
+  {
+    case 0:
+      sol = zerocol(nbz);
+      break;
+    case 1:
+      sol = const_col(nbz, real_0_bit(bitprec));
+      break;
+    /* case 2: nothing */
+  }
+
+  if (typ(a) == t_INFINITY && typ(b) != t_INFINITY && gsigne(b))
+  {
+    fb = fujiwara_bound_real(Pcur, -1);
+    if (fb > -pariINFINITY)
+      a = negi(int2n((long)ceil(fb)));
+    else
+      a = gen_0;
+  }
+  if (typ(b) == t_INFINITY && typ(a) != t_INFINITY && gsigne(a))
+  {
+    fb = fujiwara_bound_real(Pcur, 1);
+    if (fb > -pariINFINITY)
+      b = int2n((long)ceil(fb));
+    else
+      b = gen_0;
+  }
+
+  if (typ(a) != t_INFINITY && typ(b) != t_INFINITY)
+  {
+    pari_sp av1;
+    GEN den = lcmii(denom(a), denom(b)), diff, unscaledres, co, Pdiv;
+    GEN ascaled;
+    long i;
+    if (!is_pm1(den))
+    {
+      Pcur = ZX_rescale(Pcur, den);
+      ascaled = gmul(a, den);
+    }
+    else
+    {
+      den = NULL;
+      ascaled = a;
+    }
+    diff = subii(den ? gmul(b,den) : b, ascaled);
+    Pcur = ZX_unscale(ZX_translate(Pcur, ascaled), diff);
+    av1 = avma;
+    Pdiv = cgetg(deg+2, t_POL);
+    Pdiv[1] = Pcur[1];
+    co = gel(Pcur, deg+2);
+    for (i = deg; --i >= 0; )
+    {
+      gel(Pdiv, i+2) = co;
+      co = addii(co, gel(Pcur, i+2));
+    }
+    if (!signe(co))
+    {
+      Pcur = Pdiv;
+      deg--;
+      if (flag <= 1)
+        sol = concat(sol, b);
+      else
+        nbz++;
+    }
+    else
+      avma = av1;
+    unscaledres = usp(Pcur, deg, &nb_done, flag, bitprec);
+    if (flag <= 1)
+    {
+      for (i = 1; i < lg(unscaledres); i++)
+      {
+        GEN z = gmul(diff, gel(unscaledres, i));
+        if (typ(z) == t_VEC)
+        {
+          gel(z, 1) = gadd(ascaled, gel(z, 1));
+          gel(z, 2) = gadd(ascaled, gel(z, 2));
+        }
+        else
+          z = gadd(ascaled, z);
+        if (den) z = gdiv(z, den);
+        gel(unscaledres, i) = z;
+      }
+      sol = concat(sol, unscaledres);
+    }
+    else
+      nbz += lg(unscaledres) - 1;
+  }
+  if (typ(b) == t_INFINITY && (fb=fujiwara_bound_real(Pcur, 1)) > -pariINFINITY)
+  {
+    GEN Pcurp, unscaledres;
+    long bp = (long)ceil(fb);
+    if (bp < 0) bp = 0;
+    Pcurp = ZX_unscale2n(Pcur, bp);
+    unscaledres = usp(Pcurp, deg, &nb_done, flag, bitprec);
+    if (flag <= 1)
+      sol = concat(sol, gmul2n(unscaledres, bp));
+    else
+      nbz += lg(unscaledres) - 1;
+  }
+  if (typ(a) == t_INFINITY && (fb=fujiwara_bound_real(Pcur,-1)) > -pariINFINITY)
+  {
+    GEN Pcurm, unscaledres;
+    long i, bm = (long)ceil(fb);
+    if (bm < 0) bm = 0;
+    Pcurm = ZX_unscale(Pcur, gen_m1);
+    Pcurm = ZX_unscale2n(Pcurm, bm);
+    unscaledres = usp(Pcurm,deg,&nb_done,flag,bitprec);
+    if (flag <= 1)
+    {
+      for (i = 1; i < lg(unscaledres); i++)
+      {
+        GEN z = gneg(gmul2n(gel(unscaledres, i), bm));
+        if (typ(z) == t_VEC) swap(gel(z, 1), gel(z, 2));
+        gel(unscaledres, i) = z;
+      }
+      sol = concat(unscaledres, sol);
+    }
+    else
+      nbz += lg(unscaledres) - 1;
+  }
+
+  if (DEBUGLEVEL > 4)
+    err_printf("ZX_uspensky: Number of visited nodes: %d\n", nb_done);
+
+  if (flag >= 2) return utoi(nbz);
+  if (flag)
+    sol = sort(sol);
+  else
+    sol = gen_sort(sol, (void *)_intervalcmp, cmp_nodata);
+  return gerepileupto(av, sol);
+}
+
+/* x a scalar */
+static GEN
+rootsdeg0(GEN x)
+{
+  if (!is_rational_t(typ(x))) pari_err_TYPE("realroots",x);
+  if (gequal0(x)) pari_err_ROOTS0("realroots");
+  return cgetg(1,t_COL); /* constant polynomial */
+}
+static void
+checkbound(GEN a)
+{
+  switch(typ(a))
+  {
+    case t_INT: case t_FRAC: case t_INFINITY: break;
+    default: pari_err_TYPE("polrealroots", a);
+  }
+}
+static GEN
+check_ab(GEN ab)
+{
+  GEN a, b;
+  if (!ab) return NULL;
+  if (typ(ab) != t_VEC || lg(ab) != 3) pari_err_TYPE("polrootsreal",ab);
+  a = gel(ab,1); checkbound(a);
+  b = gel(ab,2); checkbound(b);
+  if (typ(a) == t_INFINITY && inf_get_sign(a) < 0 &&
+      typ(b) == t_INFINITY && inf_get_sign(b) > 0) ab = NULL;
+  return ab;
+}
+GEN
+realroots(GEN P, GEN ab, long prec)
+{
+  pari_sp av = avma;
+  long nrr = 0;
+  GEN sol = NULL, fa, ex;
+  long i, j, k;
+
+  ab = check_ab(ab);
+  if (typ(P) != t_POL) return rootsdeg0(P);
+  switch(degpol(P))
+  {
+    case -1: return rootsdeg0(gen_0);
+    case 0: return rootsdeg0(gel(P,2));
+  }
+  P = Q_primpart(P);
+  if (!RgX_is_ZX(P)) pari_err_TYPE("realroots",P);
+  fa = ZX_squff(P, &ex);
+  for (i = 1; i < lg(fa); i++)
+  {
+    GEN Pi = gel(fa, i), soli, soli2 = NULL;
+    long n, nrri = 0, h, nbz;
+    if (ab)
+      h = 1;
+    else
+      Pi = RgX_deflate_max(Pi, &h);
+    if (!signe(gel(Pi, 2)))
+    {
+      Pi = RgX_shift_shallow(Pi, -1);
+      nbz = 1;
+    }
+    else
+      nbz = 0;
+    soli = ZX_uspensky(Pi, h%2 ? ab: gen_0, 1, prec2nbits(prec));
+    n = lg(soli);
+    if (!(h % 2)) soli2 = cgetg(n, t_COL);
+    for (j = 1; j < n; j++)
+    {
+      GEN elt = gel(soli, j);
+      if (typ(elt) != t_REAL)
+      {
+        nrri++;
+        elt = gtofp(elt, prec);
+        gel(soli, j) = elt;
+      }
+      if (h > 1)
+      { /* note: elt != 0 because we are square free */
+        GEN r;
+        if (h == 2)
+          r = sqrtr(elt);
+        else
+        {
+          if (signe(elt) < 0)
+            r = negr(sqrtnr(negr(elt), h));
+          else
+            r = sqrtnr(elt, h);
+        }
+        gel(soli, j) = r;
+        if (!(h % 2)) gel(soli2, j) = negr(r);
+      }
+    }
+    if (!(h % 2)) soli = shallowconcat(soli, soli2);
+    if (nbz) soli = shallowconcat(soli, real_0(prec));
+    for (k = 1; k <= ex[i]; k++)
+      sol = sol ? shallowconcat(sol, soli) : soli;
+    nrr += ex[i]*nrri;
+  }
+
+  if (DEBUGLEVEL > 4)
+  {
+    err_printf("Number of real roots: %d\n", lg(sol)-1);
+    err_printf(" -- of which 2-integral: %ld\n", nrr);
+  }
+
+  return gerepileupto(av, sort(sol));
+}
+
+/* P non-constant, squarefree ZX */
+long
+ZX_sturm(GEN P)
+{
+  pari_sp av = avma;
+  long h, r;
+  P = RgX_deflate_max(P, &h);
+  if (odd(h))
+    r = itos(ZX_uspensky(P, NULL, 2, 0));
+  else
+    r = 2*itos(ZX_uspensky(P, gen_0, 2, 0));
+  avma = av; return r;
+}
+/* P non-constant, squarefree ZX */
+long
+ZX_sturmpart(GEN P, GEN ab)
+{
+  pari_sp av = avma;
+  long r;
+  if (!check_ab(ab)) return ZX_sturm(P);
+  r = itos(ZX_uspensky(P, ab, 2, 0));
+  avma = av; return r;
+}
diff --git a/src/basemath/subcyclo.c b/src/basemath/subcyclo.c
index c91b24b..30f3cf5 100644
--- a/src/basemath/subcyclo.c
+++ b/src/basemath/subcyclo.c
@@ -110,7 +110,7 @@ znstar_generate(long n, GEN V)
   long i, r = 0;
   for(i=1; i<lg(V); i++)
   {
-    ulong v = (ulong)V[i], g = v;
+    ulong v = uel(V,i), g = v;
     long o = 0;
     while (!F2v_coeff(bits, (long)g)) { g = Fl_mul(g, v, (ulong)n); o++; }
     if (!o) continue;
@@ -265,7 +265,7 @@ znstar_hnf_generators(GEN Z, GEN M)
     {
       ulong u = itou(gel(Mj,h));
       if (!u) continue;
-      gen[j] = Fl_mul((ulong)gen[j], Fl_powu(zgen[h], u, n), n);
+      gen[j] = Fl_mul(uel(gen,j), Fl_powu(uel(zgen,h), u, n), n);
     }
   }
   avma = ltop; return gen;
diff --git a/src/basemath/subgroup.c b/src/basemath/subgroup.c
index cf455a1..1748de0 100644
--- a/src/basemath/subgroup.c
+++ b/src/basemath/subgroup.c
@@ -515,7 +515,10 @@ subgroup_engine(subgp_iter *T)
       err_printf("(lifted) subgp of prime to %Ps part:\n%Ps\n",p, T->subq);
   }
   dopsub(T, p,indexsubq);
-  if (DEBUGLEVEL>4) err_printf("nb subgroup = %ld\n",T->count);
+  if (DEBUGLEVEL>4) {
+    err_printf("nb subgroup = %ld\n",T->count);
+    err_flush();
+  }
   avma = av;
 }
 
diff --git a/src/basemath/trans1.c b/src/basemath/trans1.c
index 76efdec..28db5dd 100644
--- a/src/basemath/trans1.c
+++ b/src/basemath/trans1.c
@@ -335,7 +335,7 @@ mpeuler(long prec) { return rtor(consteuler(prec), prec); }
 static GEN
 catalan(long prec)
 {
-  long i, nmax = bit_accuracy(prec) >> 1;
+  long i, nmax = prec2nbits(prec) >> 1;
   struct abpq_res R;
   struct abpq A;
   GEN u, v;
@@ -483,6 +483,8 @@ _sqr(void *data /* ignored */, GEN x) { (void)data; return gsqr(x); }
 static GEN
 _mul(void *data /* ignored */, GEN x, GEN y) { (void)data; return gmul(x,y); }
 static GEN
+_one(void *x) { return gpowg0((GEN) x); }
+static GEN
 _sqri(void *data /* ignored */, GEN x) { (void)data; return sqri(x); }
 static GEN
 _muli(void *data /* ignored */, GEN x, GEN y) { (void)data; return mulii(x,y); }
@@ -490,6 +492,8 @@ static GEN
 _sqrr(void *data /* ignored */, GEN x) { (void)data; return sqrr(x); }
 static GEN
 _mulr(void *data /* ignored */, GEN x, GEN y) { (void)data; return mulrr(x,y); }
+static GEN
+_oner(void *data /* prec */) { return real_1( *(long*) data); }
 
 /* INTEGER POWERING (a^n for integer a != 0 and integer n > 0)
  *
@@ -670,8 +674,9 @@ upowuu(ulong p, ulong k)
     q *= q ;
     return odd(k)? q*p: q;
   }
-#endif
+#else
   return 0;
+#endif
 }
 
 typedef struct {
@@ -741,6 +746,13 @@ powru(GEN x, ulong n)
   return gerepileuptoleaf(av,y);
 }
 
+GEN
+powersr(GEN x, long n)
+{
+  long prec = realprec(x);
+  return gen_powers(x, n, 1, &prec, &_sqrr, &_mulr, &_oner);
+}
+
 /* x^(s/2), assume x t_REAL */
 GEN
 powrshalf(GEN x, long s)
@@ -1100,7 +1112,7 @@ gpow(GEN x, GEN n, long prec)
     if (!precision(x)) return gcopy(x);
 
     x = ground(gmulsg(gexpo(x),n));
-    if (is_bigint(x) || (ulong)x[2] >= HIGHEXPOBIT)
+    if (is_bigint(x) || uel(x,2) >= HIGHEXPOBIT)
       pari_err_OVERFLOW("gpow");
     avma = av; return real_0_bit(itos(x));
   }
@@ -1135,6 +1147,14 @@ gpow(GEN x, GEN n, long prec)
   return gerepileupto(av, gexp(y,prec));
 }
 
+GEN
+gpowers(GEN x, long n)
+{
+  if (n < 0)
+    pari_err_DOMAIN("powers", "n", "<", gen_0, stoi(n));
+  return gen_powers(x, n, 1, (void*)x, &_sqr, &_mul, &_one);
+}
+
 /********************************************************************/
 /**                                                                **/
 /**                        RACINE CARREE                           **/
@@ -1146,12 +1166,12 @@ sqrt_2adic(GEN x, long pp)
 {
   GEN z = mod16(x)==(signe(x)>=0?1:15)?gen_1: utoipos(3);
   long zp;
-  pari_sp av, lim;
+  pari_sp av;
 
   if (pp == 4) return z;
   zp = 3; /* number of correct bits in z (compared to sqrt(x)) */
 
-  av = avma; lim = stack_lim(av,2);
+  av = avma;
   for(;;)
   {
     GEN mod;
@@ -1164,7 +1184,7 @@ sqrt_2adic(GEN x, long pp)
 
     if (zp < pp) zp--;
 
-    if (low_stack(lim,stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM > 1) pari_warn(warnmem,"Qp_sqrt");
       z = gerepileuptoint(av,z);
@@ -1198,12 +1218,7 @@ Up_sqrt(GEN x, GEN p, long e)
     }
   }
   else
-  {
-    GEN z = Fp_sqrt(x, p);
-    if (!z) return NULL;
-    if (e <= 1) return z;
-    return gerepileuptoint(av, Zp_sqrtlift(x, z, p, e));
-  }
+    return Zp_sqrt(x, p, e);
 }
 
 GEN
@@ -1237,7 +1252,7 @@ Qp_sqrt(GEN x)
 GEN
 Zn_sqrt(GEN d, GEN fn)
 {
-  pari_sp ltop = avma, btop, st_lim;
+  pari_sp ltop = avma, btop;
   GEN b = gen_0, m = gen_1;
   long j, np;
   if (typ(d) != t_INT) pari_err_TYPE("Zn_sqrt",d);
@@ -1246,7 +1261,7 @@ Zn_sqrt(GEN d, GEN fn)
   else if (!is_Z_factorpos(fn))
     pari_err_TYPE("Zn_sqrt",fn);
   np = nbrows(fn);
-  btop = avma; st_lim = stack_lim(btop, 1);
+  btop = avma;
   for (j = 1; j <= np; ++j)
   {
     GEN  bp, mp, pr, r;
@@ -1265,7 +1280,7 @@ Zn_sqrt(GEN d, GEN fn)
     pr = mulii(m, mp);
     b = Z_chinese_coprime(b, bp, m, mp, pr);
     m = pr;
-    if (low_stack(st_lim, stack_lim(btop, 1)))
+    if (gc_needed(btop, 1))
       gerepileall(btop, 2, &b, &m);
   }
   return gerepileupto(ltop, b);
@@ -1304,7 +1319,8 @@ sqrt_ser(GEN b, long prec)
     y = sqr_ser_part(x, lold, l-1) - lold;
     for (j = lold+2; j < l+2; j++) gel(y,j) = gsub(gel(y,j), gel(a,j));
     y += lold; setvalp(y, lold);
-    y = gsub(x, gdiv(y, x2)); /* = gmuloldn(gadd(x, gdiv(a,x)), -1); */
+    y = normalize(y);
+    y = gsub(x, gdiv(y, x2)); /* = gmul2n(gsub(x, gdiv(a,x)), -1); */
     for (j = lold+2; j < l+2; j++) gel(x,j) = gel(y,j);
     lold = l;
   }
@@ -1629,6 +1645,18 @@ sqrtnint(GEN a, long n)
   return gerepileuptoleaf(ltop, x);
 }
 
+GEN
+cbrtr_abs(GEN x)
+{
+  long prec = realprec(x), n = bit_accuracy(prec), e = expo(x), er = e / 3;
+  /* x 2^3(n-er) = b t_INT */
+  GEN b = mantissa2nr(x, (e-3*er+1) + n*2);
+  b = sqrtnint(b, 3);
+  b = itor(b, prec);
+  setexpo(b, expo(b)+er-n);
+  return b;
+}
+
 ulong
 usqrtn(ulong a, ulong n)
 {
@@ -1719,7 +1747,15 @@ gsqrtn(GEN x, GEN n, GEN *zetan, long prec)
         y = real_0_bit(b);
     }
     else
-      y = gerepileupto(av, gexp(gdiv(glog(x,prec), n), prec));
+    {
+      long nn = itos_or_0(n);
+      if (tx == t_INT) { x = itor(x,prec); tx = t_REAL; }
+      if (nn > 0 && tx == t_REAL && signe(x) > 0)
+        y = sqrtnr(x, nn);
+      else
+        y = gexp(gdiv(glog(x,prec), n), prec);
+      y = gerepileupto(av, y);
+    }
     if (zetan) *zetan = rootsof1complex(n,prec);
     return y;
 
@@ -2025,6 +2061,7 @@ serchop0(GEN s)
   long i, l = lg(s);
   GEN y;
   if (l == 2) return s;
+  if (l == 3 && isexactzero(gel(s,2))) return s;
   y = cgetg(l, t_SER); y[1] = s[1];
   gel(y,2) = gen_0; for (i=3; i <l; i++) gel(y,i) = gel(s,i);
   return normalize(y);
@@ -2205,7 +2242,7 @@ zellagmcx(GEN a0, GEN b0, GEN r, GEN t, long prec)
 static GEN
 agm1(GEN x, long prec)
 {
-  GEN p1, a, a1, b1, y;
+  GEN p1, a1, b1, y;
   long l, l2, ep;
   pari_sp av;
 
@@ -2227,9 +2264,10 @@ agm1(GEN x, long prec)
       a1 = x; b1 = gen_1; l = precp(x);
       do
       {
-        a = a1;
+        GEN a = a1;
         a1 = gmul2n(gadd(a,b1),-1);
-        b1 = Qp_sqrt(gmul(a,b1));
+        a = gmul(a,b1);
+        b1 = Qp_sqrt(a); if (!b1) pari_err_SQRTN("Qp_sqrt",a);
         p1 = gsub(b1,a1); ep = valp(p1)-valp(b1);
         if (ep<=0) { b1 = gneg_i(b1); p1 = gsub(b1,a1); ep=valp(p1)-valp(b1); }
       }
@@ -2242,7 +2280,7 @@ agm1(GEN x, long prec)
       l2 = 5-prec2nbits(prec);
       do
       {
-        a = a1;
+        GEN a = a1;
         a1 = gmul2n(gadd(a,b1),-1);
         b1 = gsqrt(gmul(a,b1), prec);
         p1 = gsub(b1,a1); ep = valp(p1)-valp(b1);
@@ -2283,7 +2321,7 @@ atanhQ_split(ulong u, ulong v, long prec)
   struct abpq_res R;
   struct abpq A;
   /* satisfies (2n+1) (v/u)^2n > 2^bitprec */
-  nmax = bit_accuracy(prec) / (2*log2(d));
+  nmax = (long)(prec2nbits(prec) / (2*log2(d)));
   abpq_init(&A, nmax);
   A.a[0] = A.b[0] = gen_1;
   A.p[0] = utoipos(u);
@@ -2370,14 +2408,14 @@ logr_abs(GEN X)
   * 1-1/x and 1-x/2 ( crossover sqrt(2), worse ~ 0.29 ). To avoid an inverse,
   * we choose between x-1 and 1-x/2 ( crossover 4/3, worse ~ 0.33 ) */
   EX = expo(X);
-  u = (ulong)X[2];
+  u = uel(X,2);
   k = 2;
   if (u > (~0UL / 3) * 2) { /* choose 1-x/2 */
     EX++; u = ~u;
-    while (!u && ++k < l) { u = (ulong)X[k]; u = ~u; }
+    while (!u && ++k < l) { u = uel(X,k); u = ~u; }
   } else { /* choose x - 1 */
     u &= ~HIGHBIT; /* u - HIGHBIT, assuming HIGHBIT set */
-    while (!u && ++k < l) u = (ulong)X[k];
+    while (!u && ++k < l) u = uel(X,k);
   }
   if (k == l) return EX? mulsr(EX, mplog2(l)): real_0(l);
   z = cgetr(EX? l: l - (k-2)); ltop = avma;
@@ -2520,7 +2558,7 @@ Zp_teichmuller(GEN x, GEN p, long e, GEN pe)
     /* q <= qold^2 */
     if (lgefint(q) == 3)
     {
-      ulong Z = (ulong)z[2], Q = (ulong)q[2], P1 = (ulong)p1[2];
+      ulong Z = uel(z,2), Q = uel(q,2), P1 = uel(p1,2);
       ulong W = (Q-1) / P1; /* -1/(p-1) + O(qold) */
       ulong T = Fl_mul(W, Fl_powu(Z,P1,Q) - 1, Q);
       Z = Fl_mul(Z, 1 + T, Q);
@@ -2587,6 +2625,14 @@ glog(GEN x, long prec)
     }
     case t_COMPLEX:
       if (ismpzero(gel(x,2))) return glog(gel(x,1), prec);
+      if (ismpzero(gel(x,1)))
+      {
+        GEN a = gel(x,2), b;
+        av = avma; b = Pi2n(-1,prec);
+        if (gsigne(a) < 0) { setsigne(b, -1); a = gabs(a,prec); }
+        a = isint1(a) ? gen_0: glog(a,prec);
+        return gerepilecopy(av, mkcomplex(a, b));
+      }
       l = precision(x); if (l > prec) prec = l;
       if (prec >= LOGAGMCX_LIMIT) return logagmcx(x, prec);
       y = cgetg(3,t_COMPLEX);
@@ -2633,7 +2679,7 @@ mpcosm1(GEN x, long *ptmod8)
       q = floorr( divrr(z,pitemp) ); /* round ( x / (Pi/2) ) */
       p = l+EXTRAPRECWORD; x = rtor(x,p);
     } else {
-      q = stoi((long)floor(rtodbl(x) / (PI/2) + 0.5));
+      q = stoi((long)floor(rtodbl(x) / (M_PI/2) + 0.5));
       p = l;
     }
     if (signe(q))
diff --git a/src/basemath/trans2.c b/src/basemath/trans2.c
index 64b1a46..246dd7d 100644
--- a/src/basemath/trans2.c
+++ b/src/basemath/trans2.c
@@ -82,7 +82,7 @@ mpatan(GEN x)
   if (e < -100)
     alpha = 1.65149612947 - e; /* log_2(Pi) - e */
   else
-    alpha = log2(PI / atan(rtodbl(p1)));
+    alpha = log2(M_PI / atan(rtodbl(p1)));
   beta = (double)(prec2nbits(l)>>1);
   delta = 1 + beta - alpha/2;
   if (delta <= 0) { n = 1; m = 0; }
@@ -277,7 +277,7 @@ gacos(GEN x, long prec)
       if (lg(y) > 2)
       {
         p1 = gsubsg(1,gsqr(y));
-        if (gequal0(p1)) return zeroser(varn(y), valp(p1)>>1);
+        if (gequal0(p1)) { avma = av; return zeroser(varn(y), valp(p1)>>1); }
         p1 = integser(gdiv(gneg(derivser(y)), gsqrt(p1,prec)));
         /*y(t) = 1+O(t)*/
         if (gequal1(gel(y,2)) && !valp(y)) return gerepileupto(av, p1);
@@ -910,7 +910,7 @@ faulhaber(long e, long v)
 GEN
 sumformal(GEN T, long v)
 {
-  pari_sp av = avma, av2, lim;
+  pari_sp av = avma, av2;
   long i, t, d;
   GEN R;
 
@@ -920,7 +920,7 @@ sumformal(GEN T, long v)
     return gerepileupto(av, monomialcopy(T, 1, v < 0? 0: v));
   if (t != t_POL) pari_err_TYPE("sumformal [not a t_POL]", T);
   if (v < 0) v = varn(T);
-  av2 = avma; lim = stack_lim(av2,3);
+  av2 = avma;
   R = gen_0;
   d = poldegree(T,v);
   for (i = d; i >= 0; i--)
@@ -928,7 +928,7 @@ sumformal(GEN T, long v)
     GEN c = polcoeff0(T, i, v);
     if (gequal0(c)) continue;
     R = gadd(R, gmul(c, faulhaber(i, v)));
-    if (low_stack(lim,stack_lim(av2,3)))
+    if (gc_needed(av2,3))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"sumformal, i = %ld/%ld", i,d);
       R = gerepileupto(av2, R);
@@ -971,11 +971,11 @@ double
 darg(double s, double t)
 {
   double x;
-  if (!t) return (s>0)? 0.: PI;
-  if (!s) return (t>0)? PI/2: -PI/2;
+  if (!t) return (s>0)? 0.: M_PI;
+  if (!s) return (t>0)? M_PI/2: -M_PI/2;
   x = atan(t/s);
   return (s>0)? x
-              : ((t>0)? x+PI : x-PI);
+              : ((t>0)? x+M_PI : x-M_PI);
 }
 
 void
@@ -1008,7 +1008,7 @@ cxgamma(GEN s0, int dolog, long prec)
 {
   GEN s, u, a, y, res, tes, sig, tau, invn2, p1, nnx, pi, pi2, sqrtpi2;
   long i, lim, nn, esig, et;
-  pari_sp av, av2, avlim;
+  pari_sp av, av2;
   int funeq = 0;
   pari_timer T;
 
@@ -1037,7 +1037,7 @@ cxgamma(GEN s0, int dolog, long prec)
     iS = imag_i(S);
     if (et > 0 && l > 0)
     {
-      GEN t = gmul(iS, dbltor(PI / l)), logt = glog(t,LOWDEFAULTPREC);
+      GEN t = gmul(iS, dbltor(M_PI / l)), logt = glog(t,LOWDEFAULTPREC);
       la = gmul(t, logt);
       if      (gcmpgs(la, 3) < 0)   { logla = log(3.); la = stoi(3); }
       else if (gcmpgs(la, 150) > 0) { logla = rtodbl(logt); la = t; }
@@ -1050,7 +1050,7 @@ cxgamma(GEN s0, int dolog, long prec)
     lim = (long)ceil(l / (1.+ logla));
     if (lim == 0) lim = 1;
 
-    u = gmul(la, dbltor((lim-0.5)/PI));
+    u = gmul(la, dbltor((lim-0.5)/M_PI));
     l2 = gsub(gsqr(u), gsqr(iS));
     if (signe(l2) > 0)
     {
@@ -1082,7 +1082,7 @@ cxgamma(GEN s0, int dolog, long prec)
     /* Im (s - 1/2) log(s) */
     v = (ssig - 0.5)*ilogs + st * rlogs;
     /* l2 = | (s - 1/2) log(s) - s + log(2Pi)/2 |^2 ~ |lngamma(s))|^2 */
-    u = u - ssig + log(2.*PI)/2;
+    u = u - ssig + log(2.*M_PI)/2;
     v = v - st;
     l2 = u*u + v*v;
     if (l2 < 0.000001) l2 = 0.000001;
@@ -1092,7 +1092,7 @@ cxgamma(GEN s0, int dolog, long prec)
     la = 3.; /* FIXME: heuristic... */
     if (st > 1 && l > 0)
     {
-      double t = st * PI / l;
+      double t = st * M_PI / l;
       la = t * log(t);
       if (la < 3) la = 3.;
       if (la > 150) la = t;
@@ -1100,7 +1100,7 @@ cxgamma(GEN s0, int dolog, long prec)
     lim = (long)ceil(l / (1.+ log(la)));
     if (lim == 0) lim = 1;
 
-    u = (lim-0.5) * la / PI;
+    u = (lim-0.5) * la / M_PI;
     l2 = u*u - st*st;
     if (l2 > 0)
     {
@@ -1113,7 +1113,7 @@ cxgamma(GEN s0, int dolog, long prec)
   }
   incrprec(prec);
 
-  av2 = avma; avlim = stack_lim(av2,3);
+  av2 = avma;
   y = s;
   if (typ(s0) == t_INT)
   {
@@ -1124,7 +1124,7 @@ cxgamma(GEN s0, int dolog, long prec)
       for (i=1; i < nn; i++)
       {
         y = mulri(y, addis(s0, i));
-        if (low_stack(avlim,stack_lim(av2,3)))
+        if (gc_needed(av2,3))
         {
           if(DEBUGMEM>1) pari_warn(warnmem,"gamma");
           y = gerepileuptoleaf(av2, y);
@@ -1135,7 +1135,7 @@ cxgamma(GEN s0, int dolog, long prec)
       for (i=1; i < nn; i++)
       {
         y = mulru(y, ss + i);
-        if (low_stack(avlim,stack_lim(av2,3)))
+        if (gc_needed(av2,3))
         {
           if(DEBUGMEM>1) pari_warn(warnmem,"gamma");
           y = gerepileuptoleaf(av2, y);
@@ -1149,7 +1149,7 @@ cxgamma(GEN s0, int dolog, long prec)
     for (i=1; i < nn; i++)
     {
       y = gmul(y, gaddgs(s,i));
-      if (low_stack(avlim,stack_lim(av2,3)))
+      if (gc_needed(av2,3))
       {
         if(DEBUGMEM>1) pari_warn(warnmem,"gamma");
         y = gerepileupto(av2, y);
@@ -1163,7 +1163,7 @@ cxgamma(GEN s0, int dolog, long prec)
     for (i=1; i < nn; i++)
     {
       y = gadd(y, glog(gaddgs(s,i), prec));
-      if (low_stack(avlim,stack_lim(av2,3)))
+      if (gc_needed(av2,3))
       {
         if(DEBUGMEM>1) pari_warn(warnmem,"gamma");
         y = gerepileupto(av2, y);
@@ -1174,7 +1174,7 @@ cxgamma(GEN s0, int dolog, long prec)
 
   nnx = gaddgs(s, nn);
   a = ginv(nnx); invn2 = gsqr(a);
-  av2 = avma; avlim = stack_lim(av2,3);
+  av2 = avma;
   mpbern(lim,prec);
   tes = divrunu(bernreal(2*lim,prec), 2*lim-1); /* B2l / (2l-1) 2l*/
   if (DEBUGLEVEL>5) timer_printf(&T,"Bernoullis");
@@ -1182,7 +1182,7 @@ cxgamma(GEN s0, int dolog, long prec)
   {
     u = divrunu(bernreal(i,prec), i-1); /* Bi / i(i-1) */
     tes = gadd(u, gmul(invn2,tes));
-    if (low_stack(avlim,stack_lim(av2,3)))
+    if (gc_needed(av2,3))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"gamma");
       tes = gerepileupto(av2, tes);
@@ -1447,8 +1447,16 @@ ggamma(GEN x, long prec)
         {
           pi = mppi(prec);
           Y = gsubsg(1, y);
+          y0= subsi(1, y0);
+        }
+        z = glngamma(Y,prec);
+        if (!valp(z))
+        {
+          z = serchop0(z);
+          z = gmul(ggamma(y0,prec), gexp(z,prec));
         }
-        z = gexp(glngamma(Y,prec),prec);
+        else
+          z = gexp(z,prec);
         if (pi)
           z = gdiv(mpodd(t)? negr(pi): pi,
                    gmul(z, gsin(gmul(pi,serchop0(y)), prec)));
@@ -1548,7 +1556,7 @@ cxpsi(GEN s0, long prec)
     lim = 2 + (long)ceil((prec2nbits_mul(prec, LOG2) - l) / (2*(1+log((double)la))));
     if (lim < 2) lim = 2;
 
-    l = (2*lim-1)*la / (2.*PI);
+    l = (2*lim-1)*la / (2.*M_PI);
     L = gsub(dbltor(l*l), gsqr(iS));
     if (signe(L) < 0) L = gen_0;
 
@@ -1571,7 +1579,7 @@ cxpsi(GEN s0, long prec)
     lim = 2 + (long)ceil((prec2nbits_mul(prec, LOG2) - l) / (2*(1+log((double)la))));
     if (lim < 2) lim = 2;
 
-    l = (2*lim-1)*la / (2.*PI);
+    l = (2*lim-1)*la / (2.*M_PI);
     l = l*l - st*st;
     if (l < 0.) l = 0.;
     nn = (long)ceil( sqrt(l) - ssig );
@@ -1636,7 +1644,7 @@ tr(GEN T, GEN z0, long L)
 static GEN
 serpsiz0(GEN z0, long L, long v, long prec)
 {
-  pari_sp av, lim;
+  pari_sp av;
   GEN A,A1,A2, B,B1,B2, Q;
   long n;
 
@@ -1646,7 +1654,7 @@ serpsiz0(GEN z0, long L, long v, long prec)
   z0 = gtofp(z0, prec + EXTRAPRECWORD);
   /* Start from n = 3; in Luke's notation, A2 := A_{n-2}, A1 := A_{n-1},
    * A := A_n. Same for B */
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
   A2= gdivgs(mkpoln(2, gen_1, utoipos(6)), 2);
   B2 = scalarpol_shallow(utoipos(4), 0);
   A1= gdivgs(mkpoln(3, gen_1, utoipos(82), utoipos(96)), 6);
@@ -1681,10 +1689,10 @@ serpsiz0(GEN z0, long L, long v, long prec)
     a = gdiv(gadd(gadd(gmul(c1,A),gmul(c2,A1)),gmul(c3,A2)), c0);
     b = gdiv(gadd(gadd(gmul(c1,B),gmul(c2,B1)),gmul(c3,B2)), c0);
     Q = gdiv(a,b);
-    if (gexpo(gsub(Q,Q0)) < -bit_accuracy(prec)) break;
+    if (gexpo(gsub(Q,Q0)) < -prec2nbits(prec)) break;
     A2 = A1; A1 = A; A = a;
     B2 = B1; B1 = B; B = b;
-    if (low_stack(lim,stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"serpsiz0, n = %ld", n);
       gerepileall(av, 7, &A,&A1,&A2, &B,&B1,&B2, &Q);
diff --git a/src/basemath/trans3.c b/src/basemath/trans3.c
index 3f23115..54eb5de 100644
--- a/src/basemath/trans3.c
+++ b/src/basemath/trans3.c
@@ -32,7 +32,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 static GEN
 _jbessel(GEN n, GEN z, long flag, long m)
 {
-  pari_sp av, lim;
+  pari_sp av;
   GEN Z,s;
   long k;
 
@@ -47,11 +47,11 @@ _jbessel(GEN n, GEN z, long flag, long m)
     setlg(Z, k+2);
   }
   s = gen_1;
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
   for (k=m; k>=1; k--)
   {
     s = gaddsg(1, gdiv(gmul(Z,s), gmulgs(gaddgs(n,k),k)));
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"besselj");
       s = gerepileupto(av, s);
@@ -289,7 +289,7 @@ kbessel1(GEN nu, GEN gx, long prec)
   y = cgetr(l); l1=lnew+1;
   av = avma; x = gtofp(gx, lnew); nu = gtofp(nu, lnew);
   nu2 = gmul2n(sqrr(nu), 2); togglesign(nu2);
-  n = (long) (prec2nbits_mul(l,LOG2) + PI*fabs(rtodbl(nu))) / 2;
+  n = (long) (prec2nbits_mul(l,LOG2) + M_PI*fabs(rtodbl(nu))) / 2;
   n2 = n<<1; pitemp=mppi(l1);
   r = gmul2n(x,1);
   if (cmprs(x, n) < 0)
@@ -361,7 +361,7 @@ static GEN
 _kbessel1(long n, GEN z, long flag, long m, long prec)
 {
   GEN Z, p1, p2, s, H;
-  pari_sp av, lim;
+  pari_sp av;
   long k;
 
   Z = gmul2n(gsqr(z),-2); if (flag & 1) Z = gneg(Z);
@@ -386,11 +386,11 @@ _kbessel1(long n, GEN z, long flag, long m, long prec)
     for (k=2; k<=m+n; k++) gel(H,k+1) = s = gdivgs(gaddsg(1,gmulsg(k,s)),k);
   }
   s = gadd(gel(H,m+1), gel(H,m+n+1));
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
   for (k=m; k>0; k--)
   {
     s = gadd(gadd(gel(H,k),gel(H,k+n)),gdiv(gmul(Z,s),mulss(k,k+n)));
-    if (low_stack(lim,stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"_kbessel1");
       s = gerepileupto(av, s);
@@ -568,7 +568,7 @@ hyperu(GEN a, GEN b, GEN gx, long prec)
   x = gtofp(gx, l);
   a1 = gaddsg(1, gadd(a,mb)); P = gmul(a1, a);
   p1 = gabs(gtofp(P,LOWDEFAULTPREC), LOWDEFAULTPREC);
-  n = (long)(prec2nbits_mul(l, LOG2) + PI*sqrt(gtodouble(p1)));
+  n = (long)(prec2nbits_mul(l, LOG2) + M_PI*sqrt(gtodouble(p1)));
   S = gadd(a1, a);
   if (cmprs(x,n) < 0)
   {
@@ -659,7 +659,7 @@ incgam_0(GEN x, GEN expx)
   }
   else
   {
-    long prec = l + nbits2extraprec((mx+log(mx))/LOG2);
+    long prec = nbits2prec(prec2nbits(l) + (mx+log(mx))/LOG2 + 10);
     GEN S, t, H, run = real_1(prec);
     n = -prec2nbits(prec);
     x = rtor(x, prec);
@@ -684,7 +684,7 @@ incgam_cf(GEN s, GEN x, double mx, long prec)
 {
   GEN x_s, S, y;
   long n, i;
-  pari_sp av = avma, av2, avlim;
+  pari_sp av = avma, av2;
   double m;
 
   m = (prec2nbits_mul(prec,LOG2) + mx)/4;
@@ -694,12 +694,12 @@ incgam_cf(GEN s, GEN x, double mx, long prec)
   else
     y = gexp(gsub(gmul(gsubgs(s,1), glog(x, prec)), x), prec);
   x_s = gsub(x, s);
-  av2 = avma; avlim = stack_lim(av2,3);
+  av2 = avma;
   S = gdiv(gsubgs(s,n), gaddgs(x_s,n<<1));
   for (i=n-1; i >= 1; i--)
   {
     S = gdiv(gsubgs(s,i), gadd(gaddgs(x_s,i<<1),gmulsg(i,S)));
-    if (low_stack(avlim,stack_lim(av2,3)))
+    if (gc_needed(av2,3))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"incgam_cf");
       S = gerepileupto(av2, S);
@@ -714,7 +714,7 @@ incgamc(GEN s, GEN x, long prec)
 {
   GEN S, t, y;
   long l, n, i, ex;
-  pari_sp av = avma, av2, avlim;
+  pari_sp av = avma, av2;
 
   if (typ(x) != t_REAL) x = gtofp(x, prec);
   if (gequal0(x)) return gcopy(x);
@@ -725,18 +725,18 @@ incgamc(GEN s, GEN x, long prec)
   { /* take cancellation into account */
     long p = LOWDEFAULTPREC;
     double X = rtodbl(gabs(gtofp(x, p), p));
-    p = l + nbits2extraprec(X*log(X));
+    p = l + (long)nbits2extraprec(X*log(X));
     x = gtofp(x, p);
     if (isinexactreal(s)) s = gtofp(s, p);
   }
-  av2 = avma; avlim = stack_lim(av2,3);
+  av2 = avma;
   S = gdiv(x, gaddsg(1,s));
   t = gaddsg(1, S);
   for (i=2; gexpo(S) >= n; i++)
   {
     S = gdiv(gmul(x,S), gaddsg(i,s)); /* x^i / ((s+1)...(s+i)) */
     t = gadd(S,t);
-    if (low_stack(avlim,stack_lim(av2,3)))
+    if (gc_needed(av2,3))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"incgamc");
       gerepileall(av2, 2, &S, &t);
@@ -754,12 +754,12 @@ incgamc(GEN s, GEN x, long prec)
 static GEN
 incgam_asymp(GEN s, GEN x, long prec)
 {
-  pari_sp av = avma, av2, lim;
+  pari_sp av = avma, av2;
   GEN S, q, cox, invx;
   long oldeq = LONG_MAX, eq, esx, j;
   invx = ginv(x);
   esx = -prec2nbits(prec);
-  av2 = avma; lim = stack_lim(av2, 1);
+  av2 = avma;
   q = gmul(gsubgs(s, 1), invx);
   S = gaddgs(q, 1);
   for (j = 2;; j++)
@@ -772,7 +772,7 @@ incgam_asymp(GEN s, GEN x, long prec)
     }
     q = gmul(q, gmul(gsubgs(s, j), invx));
     S = gadd(S, q);
-    if (low_stack(lim, stack_lim(av2, 1))) gerepileall(av2, 2, &S, &q);
+    if (gc_needed(av2, 1)) gerepileall(av2, 2, &S, &q);
   }
   if (typ(s) == t_INT) /* exp(-x) x^(s-1) */
     cox = gmul(gexp(gneg(x), prec), powgi(x, subis(s, 1)));
@@ -928,7 +928,7 @@ incgam(GEN s, GEN x, long prec) { return incgam0(s, x, NULL, prec); }
 GEN
 mpeint1(GEN x, GEN expx)
 {
-  GEN z = cgetr(lg(x));
+  GEN z = cgetr(realprec(x));
   pari_sp av = avma;
   affrr(incgam_0(x, expx), z);
   avma = av; return z;
@@ -979,7 +979,7 @@ eint1(GEN x, long prec)
   /* rewritten from code contributed by Manfred Radimersky */
   res = cgetg(3, t_COMPLEX);
   av = avma;
-  l  = lg(x);
+  l  = realprec(x);
   n  = prec2nbits(l);
   y  = negr(x);
   if (cmprs(y, (3*n)/4) < 0) {
@@ -1038,7 +1038,7 @@ static GEN
 sum_jall(GEN a, long J, long prec)
 {
   GEN s = cgetg(J+1, t_VEC);
-  long j, E = -bit_accuracy(prec) - 5;
+  long j, E = -prec2nbits(prec) - 5;
   gel(s, J) = mp_sum_j(a, J, E, prec);
   for (j = J-1; j; j--)
     gel(s,j) = divru(addrs(mulrr(a, gel(s,j+1)), 1), j);
@@ -1081,7 +1081,7 @@ mpveceint1(GEN C, GEN eC, long N)
   }
   if (Nmin == N) { avma = av0; return w; }
 
-  DL = bit_accuracy_mul(prec, LOG2) + 5;
+  DL = prec2nbits_mul(prec, LOG2) + 5;
   jmin = ceil(DL/log(N)) + 1;
   jmax = ceil(DL/log(Nmin)) + 1;
   v = sum_jall(C, jmax, prec);
@@ -1106,20 +1106,6 @@ mpveceint1(GEN C, GEN eC, long N)
   avma = av0; return w;
 }
 
-/* e t_REAL, vector of e^i, 1 <= i <= n */
-GEN
-powruvec(GEN e, ulong n)
-{
-  GEN G = cgetg(n+1, t_VEC);
-  ulong j;
-  if (n)
-  {
-    gel(G, 1) = e;
-    for (j = 2; j <= n; j++) gel(G,j) = mulrr(gel(G,j-1), e);
-  }
-  return G;
-}
-
 /* erfc via numerical integration : assume real(x)>=1 */
 static GEN
 cxerfc_r1(GEN x, long prec)
@@ -1127,10 +1113,10 @@ cxerfc_r1(GEN x, long prec)
   GEN h, h2, eh2, denom, res, lambda;
   long u, v;
   const double D = prec2nbits_mul(prec, LOG2);
-  const long npoints = (long)ceil(D/PI)+1;
+  const long npoints = (long)ceil(D/M_PI)+1;
   pari_sp av = avma;
   {
-    double t = exp(-2*PI*PI/D); /* ~exp(-2*h^2) */
+    double t = exp(-2*M_PI*M_PI/D); /* ~exp(-2*h^2) */
     v = 30; /* bits that fit in both long and double mantissa */
     u = (long)floor(t*(1L<<v));
     /* define exp(-2*h^2) to be u*2^(-v) */
@@ -1217,7 +1203,7 @@ get_xinf(double beta)
   double x0, y0, x1;
 
   if (beta < maxbeta) return beta + pow(3*beta, 1.0/3.0);
-  x0 = beta + PI/2.0;
+  x0 = beta + M_PI/2.0;
   for(;;)
   {
     y0 = x0*x0;
@@ -1251,7 +1237,7 @@ optim_zeta(GEN S, long prec, long *pp, long *pn)
     if (beta > 0)
     {
       p = (long)ceil(beta / 2.0);
-      n = fabs(s + 2*p-1)/(2*PI);
+      n = fabs(s + 2*p-1)/(2*M_PI);
     }
     else
     {
@@ -1268,7 +1254,7 @@ optim_zeta(GEN S, long prec, long *pp, long *pn)
     l2 = dabs(s, t)/2;
     if (l < l2) l = l2;
     p = (long) ceil(l); if (p < 2) p = 2;
-    n = 1 + dabs(p+s/2.-.25, t/2) * la / PI;
+    n = 1 + dabs(p+s/2.-.25, t/2) * la / M_PI;
   }
   else
   {
@@ -1283,7 +1269,7 @@ optim_zeta(GEN S, long prec, long *pp, long *pn)
     }
     else
       if (s < 1.0) p = 1;
-    n = p? dabs(s + 2*p-1, t) / (2*PI) : exp((B-LOG2+L) / s);
+    n = p? dabs(s + 2*p-1, t) / (2*M_PI) : exp((B-LOG2+L) / s);
   }
   *pp = p;
   *pn = (long)ceil(n);
@@ -1297,7 +1283,7 @@ GEN
 inv_szeta_euler(long n, double lba, long prec)
 {
   GEN z, res;
-  pari_sp av, av2, avlim;
+  pari_sp av, av2;
   double A, D;
   ulong p, lim;
   forprime_t S;
@@ -1309,21 +1295,21 @@ inv_szeta_euler(long n, double lba, long prec)
   lim = 1 + (ulong)ceil(D);
   if (lim < 3) return subir(gen_1,real2n(-n,prec));
   res = cgetr(prec); incrprec(prec);
-  av = avma; avlim = stack_lim(av, 1);
+  av = avma;
   z = subir(gen_1, real2n(-n, prec));
 
   (void)u_forprime_init(&S, 3, lim);
   av2 = avma; A = n / LOG2;
   while ((p = u_forprime_next(&S)))
   {
-    long l = prec - nbits2extraprec((long)floor(A * log(p)) - BITS_IN_LONG);
+    long l = prec2nbits(prec) - (long)floor(A * log(p)) - BITS_IN_LONG;
     GEN h;
 
-    if (l < 3)         l = 3;
-    else if (l > prec) l = prec;
+    if (l < BITS_IN_LONG) l = BITS_IN_LONG;
+    l = minss(prec, nbits2prec(l));
     h = divrr(z, rpowuu(p, (ulong)n, l));
     z = subrr(z, h);
-    if (low_stack(avlim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"inv_szeta_euler, p = %lu/%lu", p,lim);
       z = gerepileuptoleaf(av2, z);
@@ -1369,95 +1355,6 @@ bernfrac_using_zeta(long n)
   return gerepilecopy(av, mkfrac(a, d));
 }
 
-/* n >= k >= 2, y = binomial(n,k-2), as a t_REAL. Return binomial(n,k) */
-static GEN
-next_bin(GEN y, long n, long k)
-{
-  if (n & HIGHMASK)
-  {
-    y = divru(mulru(y, n-k+2), k-1);
-    return divru(mulru(y, n-k+1), k);
-  }
-  return divru(mulru(y, (n-k+2)*(n-k+1)), (k-1)*k);
-}
-
-/* assume k > 1 odd */
-static GEN
-szeta_odd(long k, long prec)
-{
-  long kk, n, li = -(1+prec2nbits(prec));
-  pari_sp av = avma, av2, limit;
-  GEN y, p1, qn, z, q, pi2 = Pi2n(1, prec), binom= real_1(prec+EXTRAPRECWORD);
-
-  q = mpexp(pi2); kk = k+1; /* >= 4 */
-  qn = sqrr(q);
-  y = NULL; /* gcc -Wall */
-  mpbern(kk>>1,prec);
-  if ((k&3)==3)
-  {
-    for (n=0; n <= kk>>1; n+=2)
-    {
-      p1 = mulrr(bernreal(kk-n,prec),bernreal(n,prec));
-      if (n) binom = next_bin(binom,kk,n);
-      p1 = mulrr(binom,p1);
-      if (n == kk>>1) shiftr_inplace(p1, -1);
-      if ((n>>1)&1) togglesign(p1);
-      y = n? addrr(y,p1): p1;
-    }
-    y = mulrr(divrr(powru(pi2,k),mpfactr(kk,prec)),y);
-
-    av2 = avma; limit = stack_lim(av2,1);
-    z = invr( addrs(q,-1) );
-    for (n=2;; n++)
-    {
-      p1 = invr( mulir(powuu(n,k),addrs(qn,-1)) );
-      z = addrr(z,p1); if (expo(p1) < li) break;
-      qn = mulrr(qn,q);
-      if (low_stack(limit,stack_lim(av2,1)))
-      {
-        if (DEBUGMEM>1) pari_warn(warnmem,"szeta, delta = %ld", expo(p1)-li);
-        gerepileall(av2,2, &z,&qn);
-      }
-    }
-    shiftr_inplace(z, 1);
-    y = addrr(y,z); togglesign(y);
-  }
-  else
-  {
-    GEN p2 = divru(pi2, k-1);
-    for (n=0; n <= k>>1; n+=2)
-    {
-      p1 = mulrr(bernreal(kk-n,prec),bernreal(n,prec));
-      if (n) binom = next_bin(binom,kk,n);
-      p1 = mulrr(binom,p1);
-      p1 = mulur(kk-(n<<1),p1);
-      if ((n>>1)&1) togglesign(p1);
-      y = n? addrr(y,p1): p1;
-    }
-    y = mulrr(divrr(powru(pi2,k),mpfactr(kk,prec)),y);
-    y = divru(y,k-1);
-
-    av2 = avma; limit = stack_lim(av2,1);
-    p1 = sqrr(addrs(q,-1));
-    z = divrr(addrs(mulrr(q,addsr(1,mulur(2,p2))),-1),p1);
-    for (n=2;; n++)
-    {
-      p1 = mulir(powuu(n,k),sqrr(addrs(qn,-1)));
-      p1 = divrr(addrs(mulrr(qn,addsr(1,mulur(n<<1,p2))),-1),p1);
-      z = addrr(z,p1); if (expo(p1) < li) break;
-      qn = mulrr(qn,q);
-      if (low_stack(limit,stack_lim(av2,1)))
-      {
-        if (DEBUGMEM>1) pari_warn(warnmem,"szeta, delta = %ld", expo(p1)-li);
-        gerepileall(av2,2, &z,&qn);
-      }
-    }
-    shiftr_inplace(z, 1);
-    y = subrr(y,z);
-  }
-  return gerepileuptoleaf(av, y);
-}
-
 static int
 bernreal_use_zeta(long k, long prec)
 {
@@ -1506,12 +1403,76 @@ bernreal(long n, long prec)
   return B;
 }
 
+/* zeta(s+h*j), j=0..N-1, s>1, using sumalt. Johansonn's thesis, Algo 4.7.1 */
+GEN
+zetaBorweinRecycled(long s, long h, long N, long prec)
+{
+  pari_sp av = avma, lim = stack_lim(av,3);
+  const long n = ceil(2 + prec2nbits_mul(prec, LOG2/1.7627));
+  long j, k;
+  GEN c, d, z = cgetg(N+1, t_VEC);
+  c = d = int2n(2*n-1);
+  for (j = 0; j < N; j++) gel(z,j+1) = gen_0;
+  for (k = n; k; k--)
+  {
+    GEN u, t = divii(d, powuu(k,s));
+    if (!odd(k)) t = negi(t);
+    gel(z,1) = addii(gel(z,1), t);
+    u = powuu(k,h);
+    for (j = 1; j < N; j++)
+    {
+      t = divii(t,u); if (!signe(t)) break;
+      gel(z,j+1) = addii(gel(z,j+1), t);
+    }
+    c = muluui(k,2*k-1,c);
+    c = diviuuexact(c, 2*(n-k+1),n+k-1);
+    d = addii(d,c);
+    if (low_stack(lim,stack_lim(av,3)))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"zetaBorweinRecycled");
+      gerepileall(av, 3, &c,&d,&z);
+    }
+  }
+  for (j = 0; j < N; j++)
+  {
+    long a = s+h*j-1;
+    gel(z,j+1) = rdivii(shifti(gel(z,j+1), a), subii(shifti(d,a), d), prec);
+  }
+  return gerepilecopy(av, z);
+}
+/* zeta(s) using sumalt, case h=0,N=1. Assume s > 1 */
+static GEN
+zetaBorwein(long s, long prec)
+{
+  pari_sp av = avma, lim = stack_lim(av,3);
+  const long n = ceil(2 + prec2nbits_mul(prec, LOG2/1.7627));
+  long k;
+  GEN c, d, z = gen_0;
+  c = d = int2n(2*n-1);
+  for (k = n; k; k--)
+  {
+    GEN t = divii(d, powuu(k,s));
+    z = odd(k)? addii(z,t): subii(z,t);
+    c = muluui(k,2*k-1,c);
+    c = diviuuexact(c, 2*(n-k+1),n+k-1);
+    d = addii(d,c);
+    if (low_stack(lim,stack_lim(av,3)))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"zetaBorwein");
+      gerepileall(av, 3, &c,&d,&z);
+    }
+  }
+  z = rdivii(shifti(z, s-1), subii(shifti(d,s-1), d), prec);
+  return gerepileuptoleaf(av, z);
+}
+
 /* assume k != 1 */
 GEN
 szeta(long k, long prec)
 {
   pari_sp av = avma;
   GEN y;
+  double p;
 
   /* treat trivial cases */
   if (!k) { y = real2n(-1, prec); setsigne(y,-1); return y; }
@@ -1540,9 +1501,10 @@ szeta(long k, long prec)
     return gerepileuptoleaf(av, y);
   }
   /* k > 1 odd */
-  if (k * log(k) > prec2nbits_mul(prec, LOG2)) /* heuristic */
+  p = prec2nbits_mul(prec,0.393); /* 0.393 ~ 1/log_2(3+sqrt(8)) */
+  if (log2(p * log(p))*k > prec2nbits(prec))
     return gerepileuptoleaf(av, invr( inv_szeta_euler(k, 0, prec) ));
-  return szeta_odd(k, prec);
+  return zetaBorwein(k, prec);
 }
 
 /* return n^-s, n > 1 odd. tab[q] := q^-s, q prime power */
@@ -1567,7 +1529,7 @@ czeta(GEN s0, long prec)
   GEN sim, *tab, tabn, funeq_factor = NULL;
   ulong p, sqn;
   long i, nn, lim, lim2, ct;
-  pari_sp av0 = avma, av, av2, avlim;
+  pari_sp av0 = avma, av, av2;
   pari_timer T;
   forprime_t S;
 
@@ -1652,7 +1614,7 @@ czeta(GEN s0, long prec)
     s1 = gsub(gmul2n(s,1), unr);
     s2 = gmul(s, gsub(s,unr));
     s3 = gmul2n(invn2,3);
-    av2 = avma; avlim = stack_lim(av2,3);
+    av2 = avma;
     s4 = gmul(invn2, gmul2n(gaddsg(4*lim-2,s1),1));
     s5 = gmul(invn2, gadd(s2, gmulsg(lim2, gaddgs(s1, lim2))));
     for (i = lim2-2; i>=2; i -= 2)
@@ -1660,7 +1622,7 @@ czeta(GEN s0, long prec)
       s5 = gsub(s5, s4);
       s4 = gsub(s4, s3);
       tes = gadd(bernreal(i,prec), divgunu(gmul(s5,tes), i+1));
-      if (low_stack(avlim,stack_lim(av2,3)))
+      if (gc_needed(av2,3))
       {
         if(DEBUGMEM>1) pari_warn(warnmem,"czeta");
         gerepileall(av2,3, &tes,&s5,&s4);
@@ -1694,8 +1656,8 @@ GEN
 twistpartialzeta(GEN q, long f, long c, GEN va, GEN cff)
 {
   long j, k, lva = lg(va)-1, N = lg(cff)-1;
-  pari_sp av, av2, lim;
-  GEN Ax, Cx, Bx, Dx, x = pol_x(0), y = pol_x(fetch_user_var("y"));
+  pari_sp av, av2;
+  GEN Ax, Cx, Bx, Dx, x = pol_x(0), y = pol_x(1);
   GEN cyc, psm, rep, eta, etaf;
 
   cyc = gdiv(gsubgs(gpowgs(y, c), 1), gsubgs(y, 1));
@@ -1708,7 +1670,7 @@ twistpartialzeta(GEN q, long f, long c, GEN va, GEN cff)
   Ax  = gerepileupto(av, RgX_to_FqX(Ax, cyc, q));
   Cx  = Ax;
   Bx  = gen_1;
-  av  = avma; lim = stack_lim(av, 1);
+  av  = avma;
   for (j = 2; j <= N; j++)
   {
     Bx = gadd(Bx, Cx);
@@ -1716,7 +1678,7 @@ twistpartialzeta(GEN q, long f, long c, GEN va, GEN cff)
     Cx = FpXQX_mul(Cx, Ax, cyc, q);
     Cx = pol_mod_xn(Cx, N);
     if (gequal0(Cx)) break;
-    if (low_stack(lim, stack_lim(av, 1)))
+    if (gc_needed(av, 1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem, "twistpartialzeta (1), j = %ld/%ld", j, N);
       gerepileall(av, 2, &Cx, &Bx);
@@ -1726,7 +1688,7 @@ twistpartialzeta(GEN q, long f, long c, GEN va, GEN cff)
   Bx  = gerepileupto(av, RgX_to_FqX(Bx, cyc, q));
   Cx = lift(gmul(eta, gaddsg(1, x)));
   Dx = pol_1(varn(x));
-  av2 = avma; lim = stack_lim(av2, 1);
+  av2 = avma;
   for (j = lva; j > 1; j--)
   {
     GEN Ex;
@@ -1739,7 +1701,7 @@ twistpartialzeta(GEN q, long f, long c, GEN va, GEN cff)
          them or to compute them in a smart way) */
       Ex = gpowgs(Cx, e);
     Dx = gaddsg(1, FpXQX_mul(Dx, Ex, cyc, q));
-    if (low_stack(lim, stack_lim(av2, 1)))
+    if (gc_needed(av2, 1))
     {
       if(DEBUGMEM>1)
         pari_warn(warnmem, "twistpartialzeta (2), j = %ld/%ld", lva-j, lva);
@@ -1749,13 +1711,13 @@ twistpartialzeta(GEN q, long f, long c, GEN va, GEN cff)
   Dx = FpXQX_mul(Dx, Cx, cyc, q); /* va[1] = 1 */
   Bx = gerepileupto(av, FpXQX_mul(Dx, Bx, cyc, q));
   rep = gen_0;
-  av2 = avma; lim = stack_lim(av2, 1);
+  av2 = avma;
   for (k = 1; k <= N; k++)
   {
     GEN p2, ak = polcoeff_i(Bx, k, 0);
     p2  = quicktrace(ak, psm);
     rep = modii(addii(rep, mulii(gel(cff, k), p2)), q);
-    if (low_stack(lim, stack_lim(av2, 1)))
+    if (gc_needed(av2, 1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem, "twistpartialzeta (3), j = %ld/%ld", k, N);
       rep = gerepileupto(av2, rep);
@@ -1815,14 +1777,14 @@ GEN
 coeff_of_phi_ms(ulong p, GEN q, long m, GEN s, long N, GEN vz)
 {
   GEN qs2 = shifti(q, -1), cff = zerovec(N);
-  pari_sp av, lim;
+  pari_sp av;
   long k, j;
 
-  av = avma; lim = stack_lim(av, 2);
+  av = avma;
   for (k = 1; k <= N; k++)
   {
     gel(cff, k) = phi_ms(p, q, m, s, k, vz);
-    if (low_stack(lim, stack_lim(av, 2)))
+    if (gc_needed(av, 2))
     {
       if(DEBUGMEM>1)
         pari_warn(warnmem, "coeff_of_phi_ms (1), k = %ld/%ld", N-k, N);
@@ -1833,7 +1795,7 @@ coeff_of_phi_ms(ulong p, GEN q, long m, GEN s, long N, GEN vz)
   {
     GEN b = subii(gel(cff, j), gel(cff, j-1));
     gel(cff, j) = centermodii(b, q, qs2);
-    if (low_stack(lim, stack_lim(av, 2)))
+    if (gc_needed(av, 2))
     {
       if(DEBUGMEM>1)
         pari_warn(warnmem, "coeff_of_phi_ms (2), j = %ld/%ld", N-j, N);
@@ -1845,7 +1807,7 @@ coeff_of_phi_ms(ulong p, GEN q, long m, GEN s, long N, GEN vz)
     {
       GEN b = subii(gel(cff, j), gel(cff, j-1));
       gel(cff, j) = centermodii(b, q, qs2);
-      if (low_stack(lim, stack_lim(av, 2)))
+      if (gc_needed(av, 2))
       {
         if(DEBUGMEM>1)
           pari_warn(warnmem, "coeff_of_phi_ms (3), (k,j) = (%ld,%ld)/%ld",
@@ -2091,7 +2053,7 @@ static GEN
 polylog(long m, GEN x, long prec)
 {
   long l, e, i, G, sx;
-  pari_sp av, av1, limpile;
+  pari_sp av, av1;
   GEN X, Xn, z, p1, p2, y, res;
 
   if (m < 0) pari_err_DOMAIN("polylog", "index", "<", gen_0, stoi(m));
@@ -2113,7 +2075,7 @@ polylog(long m, GEN x, long prec)
   }
   X = (e > 0)? ginv(x): x;
   G = -prec2nbits(l);
-  av1 = avma; limpile = stack_lim(av1,1);
+  av1 = avma;
   y = Xn = X;
   for (i=2; ; i++)
   {
@@ -2121,7 +2083,7 @@ polylog(long m, GEN x, long prec)
     y = gadd(y,p2);
     if (gexpo(p2) <= G) break;
 
-    if (low_stack(limpile, stack_lim(av1,1)))
+    if (gc_needed(av1,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"polylog");
       gerepileall(av1,2, &y, &Xn);
@@ -2464,7 +2426,7 @@ ser_addmulXn(GEN y, GEN x, long d)
 static GEN
 inteta_pol(GEN q, long v, long l)
 {
-  pari_sp av = avma, lim = stack_lim(av, 1);
+  pari_sp av = avma;
   GEN qn, ps, y;
   ulong vps, vqn, n;
 
@@ -2482,9 +2444,9 @@ inteta_pol(GEN q, long v, long l)
     k2 = k1 - vqn; /* = l-2 + v - vps + 1 */
     if (k1 <= 0) break;
     t = RgX_mul(q, RgX_sqr(qn));
-    t = RgX_modXn_shallow(t, k1);
+    t = RgXn_red_shallow(t, k1);
     t = RgX_mul(ps,t);
-    t = RgX_modXn_shallow(t, k1);
+    t = RgXn_red_shallow(t, k1);
     t = RgX_neg(t); /* t = (-1)^(n+1) q^(n(3n+1)/2 + 2n+1) */
     t = gerepileupto(av2, t);
     y = addmulXn(t, y, vt);
@@ -2492,10 +2454,10 @@ inteta_pol(GEN q, long v, long l)
 
     qn = RgX_mul(qn,q);
     ps = RgX_mul(t,qn);
-    ps = RgX_modXn_shallow(ps, k2);
+    ps = RgXn_red_shallow(ps, k2);
     y = addmulXn(ps, y, vps);
 
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"eta, n = %ld", n);
       gerepileall(av, 3, &y, &qn, &ps);
@@ -2527,7 +2489,7 @@ inteta(GEN q)
   {
     ulong vps, vqn;
     long l = lg(q), v, n;
-    pari_sp av, lim;
+    pari_sp av;
 
     v = valp(q); /* handle valuation separately to avoid overflow */
     if (v <= 0) pari_err_DOMAIN("eta", "v_p(q)", "<=",gen_0,q);
@@ -2535,7 +2497,7 @@ inteta(GEN q)
     n = degpol(y);
     if (n == 1 || n < (l>>2)) return inteta_pol(y, v, l);
 
-    q = leafcopy(q); av = avma; lim = stack_lim(av, 3);
+    q = leafcopy(q); av = avma;
     setvalp(q, 0);
     y = scalarser(gen_1, varn(q), l+v);
     vps = vqn = 0;
@@ -2555,7 +2517,7 @@ inteta(GEN q)
       setlg(q, k);
       setlg(qn, k);
       setlg(ps, k);
-      if (low_stack(lim, stack_lim(av,3)))
+      if (gc_needed(av,3))
       {
         if(DEBUGMEM>1) pari_warn(warnmem,"eta");
         gerepileall(av, 3, &y, &qn, &ps);
@@ -2564,7 +2526,7 @@ inteta(GEN q)
   }
   {
     long l; /* gcc -Wall */
-    pari_sp av = avma, lim = stack_lim(av, 3);
+    pari_sp av = avma;
 
     l = -prec2nbits(precision(q));
     for(;;)
@@ -2576,7 +2538,7 @@ inteta(GEN q)
       y = gadd(y,t); qn = gmul(qn,q); ps = gmul(t,qn);
       y = gadd(y,ps);
       if (gexpo(ps)-gexpo(y) < l) return y;
-      if (low_stack(lim, stack_lim(av,3)))
+      if (gc_needed(av,3))
       {
         if(DEBUGMEM>1) pari_warn(warnmem,"eta");
         gerepileall(av, 3, &y, &qn, &ps);
@@ -2602,7 +2564,7 @@ sumdedekind_coprime(GEN h, GEN k)
   pari_sp av = avma;
   GEN s2, s1, p, pp;
   long s;
-  if (lgefint(k) == 3 && (ulong)k[2] <= (2*(ulong)LONG_MAX) / 3)
+  if (lgefint(k) == 3 && uel(k,2) <= (2*(ulong)LONG_MAX) / 3)
   {
     ulong kk = k[2], hh = umodiu(h, kk);
     long s1, s2;
@@ -2817,7 +2779,7 @@ jell(GEN x, long prec)
      * but inteta(q) costly and useless if expo(q) << 1  => inteta(q) = 1.
      * log_2 ( exp(-2Pi Im tau) ) < -prec2nbits(prec)
      * <=> Im tau > prec2nbits(prec) * log(2) / 2Pi */
-    long C = (long)prec2nbits_mul(prec, LOG2/(2*PI));
+    long C = (long)prec2nbits_mul(prec, LOG2/(2*M_PI));
     q = exp_IPiC(gmul2n(x,1), prec); /* e(x) */
     if (gcmpgs(gel(x,2), C) > 0) /* eta(q(x)) = 1 : no need to compute q(2x) */
       h = q;
@@ -3028,7 +2990,7 @@ weberf1(GEN x, long prec)
   z = apply_eta_correction(z, st_a, st_b, gen_0, NULL, prec);
   return gerepileupto(av, z);
 }
-/* e(-1/24) * eta((x+1)/2) / eta(x) */
+/* exp(-I*Pi/24) * eta((x+1)/2) / eta(x) */
 GEN
 weberf(GEN x, long prec)
 {
@@ -3045,7 +3007,7 @@ weberf(GEN x, long prec)
   st_b = eta_correction(b, Ub, 1);
   t0 = mkfrac(gen_m1, utoipos(24));
   z = apply_eta_correction(z, st_a, st_b, t0, NULL, prec);
-  if (typ(z) == t_COMPLEX && isexactzero(real_i(a)))
+  if (typ(z) == t_COMPLEX && isexactzero(real_i(x)))
     z = gerepilecopy(av, gel(z,1));
   else
     z = gerepileupto(av, z);
@@ -3079,7 +3041,7 @@ GEN
 theta(GEN q, GEN z, long prec)
 {
   long l, n;
-  pari_sp av = avma, av2, lim;
+  pari_sp av = avma, av2;
   GEN s, c, snz, cnz, s2z, c2z, ps, qn, y, zy, ps2, k, zold;
 
   l = precision(q);
@@ -3103,7 +3065,7 @@ theta(GEN q, GEN z, long prec)
   c2z = gsubgs(gmul2n(gsqr(c),1), 1); /* cos 2z */
   snz = s;
   cnz = c; y = s;
-  av2 = avma; lim = stack_lim(av2,2);
+  av2 = avma;
   for (n = 3;; n += 2)
   {
     long e;
@@ -3117,7 +3079,7 @@ theta(GEN q, GEN z, long prec)
     c = gsub(gmul(cnz, c2z), gmul(snz,s2z));
     snz = s; /* sin nz */
     cnz = c; /* cos nz */
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"theta (n = %ld)", n);
       gerepileall(av2, 5, &snz, &cnz, &ps, &qn, &y);
@@ -3168,7 +3130,7 @@ static GEN
 vecthetanullk_loop(GEN q2, long k, long prec)
 {
   GEN ps, qn = gen_1, y = const_vec(k, gen_1);
-  pari_sp av = avma, lim = stack_lim(av,2);
+  pari_sp av = avma;
   const long bit = prec2nbits(prec);
   long i, n;
 
@@ -3184,7 +3146,7 @@ vecthetanullk_loop(GEN q2, long k, long prec)
       P = mulii(P, N2);
     }
     if (gexpo(t) < -bit) return y;
-    if (low_stack(lim, stack_lim(av,2)))
+    if (gc_needed(av,2))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"vecthetanullk_loop, n = %ld",n);
       gerepileall(av, 3, &qn, &ps, &y);
@@ -3256,7 +3218,7 @@ mplambertW0(GEN y)
     x = mulrr(x, divrr(subsr(1, mplog(divrr(x,y))), addrs(x,1)));
   } while (expo(tmp) - expo(subrr(x,tmp)) < bitprec);
   return x;
-};
+}
 
 /* Lambert W function using Newton, increasing prec */
 GEN
@@ -3265,7 +3227,7 @@ mplambertW(GEN y)
   pari_sp av = avma;
   GEN x;
   long p = 1, s = signe(y);
-  ulong mask = quadratic_prec_mask(lg(y)-1);
+  ulong mask = quadratic_prec_mask(realprec(y)-1);
 
   if (s<0) pari_err_DOMAIN("Lw", "y", "<", gen_0, y);
   if(s==0) return rcopy(y);
@@ -3280,13 +3242,80 @@ mplambertW(GEN y)
   return gerepileuptoleaf(av,x);
 }
 
+/* exp(t (1 + O(t^n))), n >= 1 */
+static GEN
+serexp0(long v, long n)
+{
+  long i, l = n+3;
+  GEN y = cgetg(l, t_SER), t;
+  y[1] = evalsigne(1) | evalvarn(v) | evalvalp(0);
+  gel(y,2) = gen_1; t = gen_1;
+  for (i = 3; i < l; i++)
+  {
+    t = muliu(t, i-2);
+    gel(y,i) = mkfrac(gen_1, t);
+  }
+  return y;
+}
+
+static GEN
+reverse(GEN y)
+{
+  GEN z = ser2rfrac_i(y);
+  long l = lg(z);
+  return RgX_to_ser(RgXn_reverse(z, l-2), l);
+}
+static GEN
+serlambertW(GEN y, long prec)
+{
+  GEN x, t, y0;
+  long n, l, vy, val, v;
+
+  if (!signe(y)) return gcopy(y);
+  v = valp(y);
+  vy = varn(y);
+  n = lg(y)-3;
+  y0 = gel(y,2);
+  for (val = 1; val < n; val++)
+    if (!gcmp0(polcoeff0(y, val, vy))) break;
+  if (v < 0) pari_err_DOMAIN("lambertw","valuation", "<", gen_0, y);
+  if (val >= n)
+  {
+    if (v) return zeroser(vy, n);
+    x = glambertW(y0,prec);
+    return scalarser(x, vy, n+1);
+  }
+  l = 3 + n/val;
+  if (v)
+  {
+    t = serexp0(vy, l-3);
+    setvalp(t, 1); /* t exp(t) */
+    t = reverse(t);
+  }
+  else
+  {
+    y = serchop0(y);
+    x = glambertW(y0, prec);
+    /* (x + t) exp(x + t) = (y0 + t y0/x) * exp(t) */
+    t = gmul(deg1pol_shallow(gdiv(y0,x), y0, vy), serexp0(vy, l-3));
+    t = gadd(x, reverse(serchop0(t)));
+  }
+  t = gsubst(t, vy, y);
+  return normalize(t);
+}
+
 GEN
 glambertW(GEN y, long prec)
 {
+  pari_sp av;
+  GEN z;
   switch(typ(y))
   {
     case t_REAL: return mplambertW(y);
     case t_COMPLEX: pari_err_IMPL("lambert(t_COMPLEX)");
+    default:
+      av = avma; if (!(z = toser_i(y))) break;
+      return gerepileupto(av, serlambertW(z, prec));
   }
   return trans_eval("lambert",glambertW,y,prec);
 }
diff --git a/src/basemath/volcano.c b/src/basemath/volcano.c
new file mode 100644
index 0000000..a812b6f
--- /dev/null
+++ b/src/basemath/volcano.c
@@ -0,0 +1,422 @@
+/* Copyright (C) 2014  The PARI group.
+
+This file is part of the PARI/GP package.
+
+PARI/GP 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. It is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY WHATSOEVER.
+
+Check the License for details. You should have received a copy of it, along
+with the package; see the file 'COPYING'. If not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+#include "pari.h"
+#include "paripriv.h"
+
+/* Is j = 0 or 1728 (mod p)? */
+INLINE int
+is_j_exceptional(ulong j, ulong p)
+{
+  return j == 0 || j == 1728 % p;
+}
+
+
+INLINE long
+node_degree(GEN phi, long L, ulong j, ulong p, ulong pi)
+{
+  pari_sp av = avma;
+  long n = Flx_nbroots(Flm_Fl_polmodular_evalx(phi, L, j, p, pi), p);
+  avma = av;
+  return n;
+}
+
+
+/*
+ * Given an array path = [j0, j1] of length 2, return the polynomial
+ *
+ *   \Phi_L(X, j1) / (X - j0)
+ *
+ * where \Phi_L(X, Y) is the modular polynomial of level L.  An error
+ * is raised if X - j0 does not divide \Phi_L(X, j1).
+ */
+INLINE GEN
+nhbr_polynomial(ulong path[], GEN phi, ulong p, ulong pi, long L)
+{
+  pari_sp ltop = avma;
+  GEN modpol = Flm_Fl_polmodular_evalx(phi, L, path[0], p, pi);
+
+  /* Note that, if the discriminant of End(path[0]) is less than L^2,
+   * then it's possible for path[0] to appear among the roots of
+   * nhbr_pol.  This case should have been obviated by earlier
+   * choices. */
+  ulong rem = 0;
+  GEN nhbr_pol = Flx_div_by_X_x(modpol, path[-1], p, &rem);
+  if (rem)
+    pari_err_BUG("nhbr_polynomial: invalid preceding j");
+  return gerepileupto(ltop, nhbr_pol);
+}
+
+/* This function assumes the volcano is a 2-volcano of depth 1, with
+ * path[0] and path[1] already on the surface. */
+static long
+walk_surface_of_2_volcano(
+  ulong path[], GEN phi, GEN first_nhbr_pol, ulong p, ulong pi, long max_len)
+{
+  enum { L = 2 };
+  pari_sp av = avma;
+  long d = 1;
+  GEN nhbr_pol = first_nhbr_pol;
+  for ( ; d < max_len && path[0] != path[d]; ++d) {
+    GEN rts = Flx_roots(nhbr_pol, p);
+    if (lg(rts) != 3) {
+      char *err = stack_sprintf("walk_surface_of_2_volcano: got %ld "
+                                "roots but expected 2", lg(rts) - 1);
+      pari_err_BUG(err);
+    }
+    path[d + 1] = rts[1];
+    nhbr_pol = nhbr_polynomial(path + d + 1, phi, p, pi, L);
+    if (Flx_nbroots(nhbr_pol, p) == 0) {
+      path[d + 1] = rts[2];
+      if (d + 1 < max_len)
+        nhbr_pol = nhbr_polynomial(path + d + 1, phi, p, pi, L);
+    }
+    nhbr_pol = gerepileupto(av, nhbr_pol);
+  }
+  avma = av;
+  return d;
+}
+
+
+/*
+ * Assumes path is an array with space for at least max_len + 1
+ * elements, whose first and second elements are the beginning of the
+ * path.  I.e., the path starts
+ *
+ *   (path[0], path[1])
+ *
+ * If the result is less than max_len, then the last element of path
+ * is definitely on the floor.  If the result equals max_len, then in
+ * general it is unknown whether the last element of path is on the
+ * floor or not.
+ */
+static long
+extend_path(
+  ulong path[], GEN phi, ulong p, ulong pi, long L, long max_len)
+{
+  pari_sp av = avma;
+  long d = 1;
+  for ( ; d < max_len; ++d) {
+    ulong nhbr;
+    GEN nhbr_pol;
+
+    nhbr_pol = nhbr_polynomial(path + d, phi, p, pi, L);
+    nhbr = Flx_oneroot(nhbr_pol, p);
+    avma = av;
+    /* Flx_oneroot didn't find a root; so we must be on the floor. */
+    if (nhbr == p)
+      break;
+    path[d + 1] = nhbr;
+  }
+  return d;
+}
+
+
+/*
+ * This is Sutherland 2009 Algorithm Ascend (p12).
+ */
+ulong
+ascend_volcano(
+  GEN phi, ulong j, ulong p, ulong pi, long level, long L,
+  long depth, long steps)
+{
+  pari_sp ltop = avma, av;
+  /* path will never hold more than max_len elements, and max_len <
+   * depth always. */
+  GEN path_g = cgetg(depth + 2, t_VECSMALL);
+  ulong *path = (ulong *)&path_g[1];
+  long max_len = depth - level;
+  int first_iter = 1;
+
+  if (steps <= 0 || max_len < 0)
+    pari_err_BUG("ascend_volcano: bad params");
+
+  av = avma;
+  while (steps--) {
+    GEN nhbr_pol = first_iter
+      ? Flm_Fl_polmodular_evalx(phi, L, j, p, pi)
+      : nhbr_polynomial(path + 1, phi, p, pi, L);
+    GEN nhbrs = Flx_roots(nhbr_pol, p);
+    long nhbrs_len = lg(nhbrs) - 1, i;
+    pari_sp btop = avma;
+    path[0] = j;
+    first_iter = 0;
+
+    j = nhbrs[nhbrs_len];
+    for (i = 1; i < nhbrs_len; ++i) {
+      ulong next_j = nhbrs[i], last_j;
+      long len;
+      if (is_j_exceptional(next_j, p)) {
+        /* According to Fouquet & Morain, Section 4.3, if j = 0 or
+         * 1728, then it is necessarily on the surface.  So we just
+         * return it. */
+        if (steps) {
+          pari_err_BUG("ascend_volcano: "
+                       "Got to the top with more steps to go!");
+        }
+        j = next_j;
+        break;
+      }
+      path[1] = next_j;
+      len = extend_path(path, phi, p, pi, L, max_len);
+      last_j = path[len];
+      if (len == max_len
+          /* Ended up on the surface */
+          && (is_j_exceptional(last_j, p)
+              || node_degree(phi, L, last_j, p, pi) > 1)) {
+        j = next_j;
+        break;
+      }
+      avma = btop;
+    }
+    path[1] = j; /* For nhbr_polynomial() at the top. */
+
+    ++max_len;
+    avma = av;
+  }
+  avma = ltop;
+  return j;
+}
+
+
+static void
+random_distinct_neighbours_of(
+  ulong *nhbr1, ulong *nhbr2,
+  GEN phi, ulong j, ulong p, ulong pi, long L,
+  long must_have_two_neighbours)
+{
+  pari_sp ltop = avma;
+  GEN modpol = Flm_Fl_polmodular_evalx(phi, L, j, p, pi);
+  ulong rem;
+  *nhbr1 = Flx_oneroot(modpol, p);
+  if (*nhbr1 == p) {
+    /* Didn't even find one root! */
+    char *err = stack_sprintf("random_distinct_neighbours_of: "
+                              "No neighbours for j = %lu (mod %lu) "
+                              "in %lu-volcano.", j, p, L);
+    pari_err_BUG(err);
+  }
+  modpol = Flx_div_by_X_x(modpol, *nhbr1, p, &rem);
+  *nhbr2 = Flx_oneroot(modpol, p);
+  if (must_have_two_neighbours && *nhbr2 == p) {
+    /* Didn't find distinct root! */
+    char *err = stack_sprintf("random_distinct_neighbours_of: "
+                              "Only one neighbour for j = %lu (mod %lu) "
+                              "in %lu-volcano.", j, p, L);
+    pari_err_BUG(err);
+  }
+  avma = ltop;
+}
+
+
+/*
+ * This is Sutherland 2009 Algorithm Descend (p12).
+ */
+ulong
+descend_volcano(
+  GEN phi, ulong j, ulong p, ulong pi,
+  long level, long L, long depth, long steps)
+{
+  pari_sp ltop = avma;
+  GEN path_g;
+  ulong *path, res;
+  long max_len;
+
+  if (steps <= 0 || level + steps > depth)
+    pari_err_BUG("descend_volcano: bad params");
+
+  max_len = depth - level;
+  path_g = cgetg(max_len + 1 + 1, t_VECSMALL);
+  path = (ulong *)&path_g[1];
+  path[0] = j;
+  /* level = 0 means we're on the volcano surface... */
+  if ( ! level) {
+    /* Look for any path to the floor.  One of j's first three
+     * neighbours must lead to the floor, since at most two neighbours
+     * are on the surface. */
+    GEN nhbrs = Flx_roots(Flm_Fl_polmodular_evalx(phi, L, j, p, pi), p);
+    long i;
+    for (i = 1; i <= 3; ++i) {
+      long len;
+      path[1] = nhbrs[i];
+      len = extend_path(path, phi, p, pi, L, max_len);
+      /* If nhbrs[i] took us to the floor: */
+      if (len < max_len || node_degree(phi, L, path[len], p, pi) == 1)
+        break;
+    }
+
+    if (i > 3) {
+      pari_err_BUG("descend_volcano: "
+                   "None of three neighbours lead to the floor");
+    }
+  } else {
+    ulong nhbr1, nhbr2;
+    long len;
+    random_distinct_neighbours_of(&nhbr1, &nhbr2, phi, j, p, pi, L, 1);
+    path[1] = nhbr1;
+    len = extend_path(path, phi, p, pi, L, max_len);
+    /* If last j isn't on the floor */
+    if (len == max_len   /* Ended up on the surface. */
+        && (is_j_exceptional(path[len], p)
+            || node_degree(phi, L, path[len], p, pi) != 1)) {
+      /* The other neighbour leads to the floor */
+      path[1] = nhbr2;
+      (void) extend_path(path, phi, p, pi, L, steps);
+    }
+  }
+  res = path[steps];
+  avma = ltop;
+  return res;
+}
+
+
+long
+j_level_in_volcano(
+  GEN phi, ulong j, ulong p, ulong pi, long L, long depth)
+{
+  pari_sp av = avma;
+  GEN chunk;
+  ulong *path1, *path2;
+  long lvl;
+
+  if (depth == 0 || is_j_exceptional(j, p)) {
+    /* According to Fouquet & Morain, Section 4.3, if j = 0 or 1728,
+     * then it is necessarily on the surface.  Also, if the volcano
+     * depth is zero then j necessarily has level 0. */
+    return 0;
+  }
+
+  chunk = new_chunk(2 * (depth + 1));
+  path1 = (ulong *) &chunk[0];
+  path2 = (ulong *) &chunk[depth + 1];
+
+  path1[0] = path2[0] = j;
+
+  random_distinct_neighbours_of(&path1[1], &path2[1],
+                                phi, j, p, pi, L, 0);
+  if (path2[1] == p) {
+    /* Only found one neighbour, hence j is on the floor, hence
+     * level == depth. */
+    lvl = depth;
+  } else {
+    long path1_len = extend_path(path1, phi, p, pi, L, depth);
+    long path2_len = extend_path(path2, phi, p, pi, L, path1_len);
+    lvl = depth - path2_len;
+  }
+  avma = av;
+  return lvl;
+}
+
+
+/*
+ * path should have space for at least (d + max_len + 1) ulongs.  Its
+ * first element should be the j-invariant at the start of the path.
+ * Returns length of the path obtained (which may be less than
+ * max_len; note that the path length is *one less* than the number of
+ * elements in path).
+ */
+long
+walk_surface_path(
+  ulong path[], GEN phi, ulong p, ulong pi,
+  long L, long depth, long max_len)
+{
+  pari_sp ltop = avma;
+  GEN nhbrs, modpol;
+  ulong *path_curr, *path_end;
+  long nhbr_idx;
+  if (max_len <= 0)
+    pari_err_BUG("walk_surface_path: bad max_len");
+
+  modpol = Flm_Fl_polmodular_evalx(phi, L, path[0], p, pi);
+  nhbrs = Flx_roots(modpol, p);
+  if (lg(nhbrs) == 1) {
+    char *err = stack_sprintf("walk_surface_path: "
+                              "No neighbours in %lu-volcano of j = %lu "
+                              "(mod %lu)", L, path[0], p);
+    pari_err_BUG(err);
+  }
+
+  path[1] = nhbrs[1];
+  if (lg(nhbrs) == 2) {
+    avma = ltop;
+    return 1;
+  }
+
+  /* Handle frequently occurring special case.  Note that, if L = 2
+   * (and (D|L) = 1 as usual), then necessarily depth > 0, since the
+   * degree of \Phi_2(X, j1)/(X - j0) is 2 and both roots are either
+   * rational or both not. */
+  if (L == 2 && depth == 1) {
+    long len;
+    /* If we didn't pick the correct neighbour above, select the next
+     * one. */
+    modpol = nhbr_polynomial(path + 1, phi, p, pi, L);
+    if (Flx_nbroots(modpol, p) == 0) {
+      path[1] = nhbrs[2];
+      modpol = nhbr_polynomial(path + 1, phi, p, pi, L);
+      /* If the first two choices were incorrect, select the last one.
+       * Note that the only way for the first two choices to have failed
+       * is if there are 3 neighbours. */
+      if (Flx_nbroots(modpol, p) == 0) {
+        /* N.B. This should only occur when h(D) = 2, since then the
+         * volcano looks like this: >-< It happens when D = -20 for
+         * example. */
+        path[1] = nhbrs[3];
+        modpol = nhbr_polynomial(path + 1, phi, p, pi, L);
+      }
+    }
+    len = walk_surface_of_2_volcano(path, phi, modpol, p, pi, max_len);
+    avma = ltop;
+    return len;
+  }
+
+  /* Invariant: *path_curr is the most recently found surface-dwelling
+   * element. */
+  path_curr = path;
+  path_end = path + max_len;
+  nhbr_idx = 1;
+  while (1) {
+    /* Find a path that doesn't lead directly to the floor. */
+    do {
+      if (nhbr_idx == lg(nhbrs)) {
+        char *err = stack_sprintf(
+          "walk_surface_path: Can't find neighbour of %lu (mod "
+          "%lu) that doesn't lead directly to the floor of its "
+          "%lu-volcano", *path_curr, p, L);
+        pari_err_BUG(err);
+      }
+      /* Select a new neighbour of path_curr. */
+      path_curr[1] = nhbrs[nhbr_idx++];
+      (void) extend_path(path_curr, phi, p, pi, L, depth);
+    } while (node_degree(phi, L, path_curr[depth], p, pi) == 1);
+
+    /* Finished if we get to max_len (i.e. path_end) or if we've come
+     * back to the beginning. */
+    if (path_curr + 1 == path_end || path_curr[1] == path[0])
+      break;
+
+    /* This extends path_curr+d by one element; i.e. it adds a
+     * random neighbour.  We do this so that the access to
+     * path_curr[depth] at the beginning of the next iteration is
+     * valid. */
+    if (depth && extend_path(path_curr + depth - 1, phi, p, pi, L, 2) != 2)
+      pari_err_BUG("walk_surface_path: Failed to add a random element");
+
+    ++path_curr;
+    avma = ltop;
+    nhbrs = Flx_roots(nhbr_polynomial(path_curr, phi, p, pi, L), p);
+    nhbr_idx = 1;
+  }
+  avma = ltop;
+  return path_curr - path + 1;
+}
diff --git a/src/desc/deftune b/src/desc/deftune
new file mode 100644
index 0000000..edbcbad
--- /dev/null
+++ b/src/desc/deftune
@@ -0,0 +1,45 @@
+#LIMIT                          none32   gmp32  none64   gmp64
+AGM_ATAN_LIMIT                     159      89      56      60
+DIVRR_GMP_LIMIT                     -1       4      -1       4
+EXPNEWTON_LIMIT                     66     197      66      66
+Flx_BARRETT_HALFMULII_LIMIT        244      23      29      21
+Flx_BARRETT_KARATSUBA_LIMIT        905     905    2561    1172
+Flx_BARRETT_MULII2_LIMIT          1004     647      30      16
+Flx_BARRETT_MULII_LIMIT           2715     433    1681     448
+Flx_DIVREM_BARRETT_LIMIT          3942    1289    2804     768
+Flx_EXTGCD_LIMIT                   850     632     284     241
+Flx_GCD_LIMIT                     7165    2514    1890    1017
+Flx_HALFGCD_LIMIT                  232     321      80      81
+Flx_INVBARRETT_HALFMULII_LIMIT     898     240     424     231
+Flx_INVBARRETT_KARATSUBA_LIMIT    3471    3600    5120    5067
+Flx_INVBARRETT_MULII2_LIMIT       3672    1815      36      26
+Flx_INVBARRETT_MULII_LIMIT        4196    1293    3840    1154
+Flx_MUL_HALFMULII_LIMIT              8       7       5       5
+Flx_MUL_KARATSUBA_LIMIT             85      90     147     142
+Flx_MUL_MULII2_LIMIT              3755     152       5       5
+Flx_MUL_MULII_LIMIT                698       8    1639       7
+Flx_REM_BARRETT_LIMIT             3942     689    3577    1266
+Flx_SQR_HALFSQRI_LIMIT               6       4       3       3
+Flx_SQR_KARATSUBA_LIMIT            159     159     330     316
+Flx_SQR_SQRI2_LIMIT               4139     470       8       7
+Flx_SQR_SQRI_LIMIT                1276       5       5       5
+FpX_BARRETT_LIMIT                  144      44      85      38
+FpX_DIVREM_BARRETT_LIMIT           306     116     292     113
+FpX_EXTGCD_LIMIT                   238      81     117      87
+FpX_GCD_LIMIT                     1292     414     731     406
+FpX_HALFGCD_LIMIT                  145      55      75      58
+FpX_INVBARRETT_LIMIT               337     121     254     111
+FpX_REM_BARRETT_LIMIT              306     127     306     111
+Fp_POW_BARRETT_LIMIT                97      11     101     127
+Fp_POW_REDC_LIMIT                   99       3      99      17
+INVMOD_GMP_LIMIT                    -1       3      -1       3
+INVNEWTON_LIMIT                    380      66     656     520
+LOGAGMCX_LIMIT                      58      32      13      22
+LOGAGM_LIMIT                        55      45      16       6
+MULII_FFT_LIMIT                   1386      -1    1441      -1
+MULII_KARATSUBA_LIMIT               18      -1      23      -1
+MULRR_MULII_LIMIT                  102       8     276      74
+RgX_MUL_LIMIT                        5       7       9       9
+RgX_SQR_LIMIT                       26      34      35      38
+SQRI_FFT_LIMIT                    1469      -1    1651      -1
+SQRI_KARATSUBA_LIMIT                27      -1      36      -1
diff --git a/src/desc/doc_make b/src/desc/doc_make
index 91b894e..bb41bc9 100755
--- a/src/desc/doc_make
+++ b/src/desc/doc_make
@@ -40,6 +40,7 @@ while (<FILE>)
         $v =~ s/\^([a-z])/\\hbox{\\kbd{\\pow}}$1/g;
         $v =~ s/\\var{flag}/\\fl/g;
         $v =~ s/\\var{(\d+)}/{$1}/g;
+        $v =~ s/_/\\_/g; # don't merge with first subst: \var{} rule kills it
 
         $v = "\$($v)\$";
       }
diff --git a/src/desc/gen_proto b/src/desc/gen_proto
index ee55449..bd6618c 100755
--- a/src/desc/gen_proto
+++ b/src/desc/gen_proto
@@ -3,25 +3,31 @@ use PARI::822;
 
 $class=$ARGV[0];
 
+$i = 1;
+# update MAX_SECTION in gplib.c and gp_rl.c when changing this
 %secnumber=(
-  'operators'             =>  1,
-  'conversions'           =>  2,
-  'transcendental'        =>  3,
-  'number_theoretical'    =>  4,
-  'elliptic_curves'       =>  5,
-  'number_fields'         =>  6,
-  'polynomials'           =>  7,
-  'linear_algebra'        =>  8,
-  'sums'                  =>  9,
-  'graphic'               => 10,
-  'programming/control'   => 11,
-  'programming/specific'  => 11,
-  'programming/parallel'  => 11,
-  'symbolic_operators'    => 13,
-  'member_functions'      => 14,
-  'programming/internals' => 15,
-  'default'               => 16,
+  'operators'             => $i++,
+  'conversions'           => $i++,
+  'transcendental'        => $i++,
+  'number_theoretical'    => $i++,
+  'elliptic_curves'       => $i++,
+  'modular_forms'         => $i++,
+  'number_fields'         => $i++,
+  'algebras'              => $i++,
+  'polynomials'           => $i++,
+  'linear_algebra'        => $i++,
+  'sums'                  => $i++,
+  'graphic'               => $i++,
 );
+# join
+$secnumber{'programming/control'} = $i;
+$secnumber{'programming/specific'} = $i;
+$secnumber{'programming/parallel'} = $i;
+$i += 2;# skip next
+$secnumber{'symbolic_operators'} = $i++;
+$secnumber{'member_functions'} = $i++;
+$secnumber{'programming/internals'} = $i++;
+$secnumber{'default'} = $i++;
 
 print <<EOF;
 /* This file is autogenerated from the database. */
diff --git a/src/desc/gen_tune b/src/desc/gen_tune
new file mode 100755
index 0000000..3e20ac8
--- /dev/null
+++ b/src/desc/gen_tune
@@ -0,0 +1,114 @@
+#! /usr/bin/perl -w
+
+use strict;
+
+sub gendefine
+{
+  my($hash)=@_;
+  for (sort keys %{$hash})
+  {
+    printf TUNE "#define __%-30s %s\n",$_,$hash->{$_};
+  }
+}
+
+sub gendefinefile
+{
+  my($file,$hash32,$hash64)=@_;
+  open TUNE, ">$file";
+  print TUNE "#ifdef LONG_IS_64BIT\n";
+  gendefine $hash64;
+  print TUNE "#else\n";
+  gendefine $hash32;
+  print TUNE "#endif\n";
+  close TUNE;
+}
+
+sub gentune
+{
+  my (%none32, %none64, %gmp32, %gmp64, @list);
+  while(<>)
+  {
+    /^#/ and next;
+    my($tunable,$none32,$gmp32,$none64,$gmp64) = split(' ');
+    push @list,$tunable;
+    $none32{$tunable}=$none32;
+    $gmp32{$tunable}=$gmp32;
+    $none64{$tunable}=$none64;
+    $gmp64{$tunable}=$gmp64;
+  }
+  open TUNE, ">src/headers/paritune.h";
+  print TUNE <<EOF;
+#define PARI_TUNE
+
+#ifdef PARI_TUNE
+EOF
+  for (@list)
+  {
+    print TUNE "extern long $_;\n";
+  }
+  print TUNE "#else\n";
+  for (@list)
+  {
+    printf TUNE "#  define %-30s __%s\n",$_,$_;
+  }
+  print TUNE "#endif\n";
+  close TUNE;
+  
+  open TUNE, ">src/kernel/none/tune-gen.h";
+  print TUNE "#ifdef PARI_TUNE\n";
+  for (@list)
+  {
+    printf TUNE "long %-30s = __%s;\n",$_,$_;
+  }
+  print TUNE "#endif\n";
+  close TUNE;
+  gendefinefile "src/kernel/none/tune.h",\%none32,\%none64;
+  gendefinefile "src/kernel/gmp/tune.h",\%gmp32,\%gmp64;
+}
+sub gendesc
+{
+  my ($file,$hash32,$hash64)=@_;
+  open DESC, "<$file";
+  my $hash = $hash64;
+  while(<DESC>)
+  {
+    /^#else/ and $hash=$hash32;
+    /#define[ \t]+__([^ ]+)[ \t]+([0-9]+)/ and $hash->{$1}=$2;
+  }
+  close DESC;
+}
+sub cc
+{
+  my $v = $_[0];
+  return $v if (defined $v);
+  return -1;
+}
+sub gendescfile
+{
+  my (%none32, %none64, %gmp32, %gmp64);
+  gendesc "src/kernel/none/tune.h",\%none32,\%none64;
+  gendesc "src/kernel/gmp/tune.h",\%gmp32,\%gmp64;
+  my %hlist=map {$_=>1} (keys %none32, keys %none64, keys %gmp32, keys %gmp64);
+  my @list = sort keys %hlist;
+  printf "%-30s %7s %7s %7s %7s\n","#LIMIT","none32","gmp32","none64","gmp64";
+  
+  for $_ (@list)
+  {
+    printf "%-30s %7s %7s %7s %7s\n",$_,cc($none32{$_}),cc($gmp32{$_}),
+                                        cc($none64{$_}),cc($gmp64{$_});
+  }
+}
+
+my $arg = shift;
+
+if ($arg eq "--gendesc")
+{
+  &gendescfile;
+}
+elsif ($arg eq "--gentune")
+{
+  &gentune;
+} else
+{
+  die("Error: gentune --gendesc|--gentune\n");
+}
diff --git a/src/desc/whatnow b/src/desc/whatnow
deleted file mode 100755
index 7c4186c..0000000
--- a/src/desc/whatnow
+++ /dev/null
@@ -1,81 +0,0 @@
-#!/usr/bin/perl -w
-##################################################
-#
-# Outputs the whatnow_list to be included in gp.c
-#
-##################################################
-$src = "..";
-$special = "\@";
-
-%funold = read_oldfun("$src/language/compat.c");
-%gpold  = read_oldfun("$src/gp/gp_init.c");
-for ( read_dico() )
-{ my ($oldname,$name,$arg,$oldarg) = split(/$special/);
-  if ($funold{$oldname}) { push(@funres, get_new($name,$oldarg,$arg)); next; }
-  if ($gpold{$oldname})  { push(@gpres,  get_new($name,$oldarg,$arg)); next; }
-  bug("5: $oldname\n");
-}
-print "/* generated by the perl script 'whatnow' */\n"
-      . "static const whatnow_t whatnowlist[]={\n"
-      . join(",\n", at funres) . ",\n\n" . join(",\n", at gpres) . "\n};\n";
-
-sub get_new { my($name, $oldarg,$arg) = @_;
-  return "_SAME" if ($name eq "=");
-  return "_REMOV" if ($name eq "");
-  return "{\"$name\",\"$oldarg\",\"$arg\"}";
-}
-
-sub bug { die "BUG$_[0]\n"; }
-sub o_r { my($f) = $_[0]; open(IN,"<$f") || die "can't open $f\n"; }
-
-sub read_oldfun {
-  o_r($_[0]);
-  my(%fun);
-  while(<IN>) {
-    if (/^entree.*old/../^$/) {
-      next if (/^entree/ || /^$/);
-      my(@line) = split(/\"/);
-      my($first) = $line[1]; bug("1: $_") if (!$first);
-      $fun{$first} = 1;
-    }
-  }
-  close(IN); return %fun;
-}
-
-sub read_dico {
-  o_r("$src/whatnow");
-  my(@diclist);
-  while(<IN>)
-  {
-    chop; if (/_/ || !/=/) { push(@diclist,"$_$special="); next; }
-    print bug("2: $_") if (! /; *$/);
-
-    chop;
-    my(@tab) = split(//);
-    my($paren) = 0;
-    my($pre, $post) = ("","");
-    my($c) = 0;
-    for (@tab)
-    {
-      if ($_ eq '(') { $paren++; }
-      elsif ($_ eq ')') { $paren--; }
-      elsif ($_ eq '=')
-      {
-        if (!$paren)
-        {
-          $pre = join("", at tab[0..$c-1]);
-          $post = join("", at tab[$c+1..$#tab]);
-          last;
-        }
-      }
-      $c++;
-    }
-    $old = $pre;
-    bug("3: $_") if ($post !~ /([^(]*)(.*)/);
-    $name = $1; $arg = $2;
-    bug("4: $_") if ($old !~ /([^(]*)(.*)/);
-    $oldname = $1; $oldarg = $2;
-    push(@diclist, "$oldname$special$name$special$arg$special$oldarg");
-  }
-  close(IN); return @diclist;
-}
diff --git a/src/funclist b/src/funclist
index e53f083..1a3ff97 100644
--- a/src/funclist
+++ b/src/funclist
@@ -1,3 +1,59 @@
+3159856057 398 ../functions/algebras/algabsdim
+2505876462 352 ../functions/algebras/algadd
+2059206215 615 ../functions/algebras/algalgtobasis
+145171335 461 ../functions/algebras/algaut
+3438450824 433 ../functions/algebras/algb
+1534068303 507 ../functions/algebras/algbasis
+4100607966 637 ../functions/algebras/algbasistoalg
+3927883884 943 ../functions/algebras/algcenter
+3921512702 1037 ../functions/algebras/algcentralproj
+3080470202 370 ../functions/algebras/algchar
+2358029032 842 ../functions/algebras/algcharpoly
+2407295337 393 ../functions/algebras/algdecomposition
+419788237 329 ../functions/algebras/algdegree
+1396571055 463 ../functions/algebras/algdim
+3959112302 730 ../functions/algebras/algdisc
+1098863400 495 ../functions/algebras/algdivl
+1215189391 230 ../functions/algebras/algdivr
+314136651 610 ../functions/algebras/alghasse
+2526874808 659 ../functions/algebras/alghassef
+4127842702 542 ../functions/algebras/alghassei
+2721560937 929 ../functions/algebras/algindex
+2627466423 6552 ../functions/algebras/alginit
+4130883813 385 ../functions/algebras/alginv
+1945081219 498 ../functions/algebras/alginvbasis
+465212633 851 ../functions/algebras/algisassociative
+129389649 583 ../functions/algebras/algiscommutative
+1669826909 933 ../functions/algebras/algisdivision
+2401762233 622 ../functions/algebras/algisdivl
+1754423584 513 ../functions/algebras/algisinv
+4229236741 1004 ../functions/algebras/algisramified
+2127934605 704 ../functions/algebras/algissemisimple
+3958203294 1014 ../functions/algebras/algissimple
+1832370070 960 ../functions/algebras/algissplit
+2778562661 373 ../functions/algebras/algmul
+3938818232 1429 ../functions/algebras/algmultable
+1313574628 347 ../functions/algebras/algneg
+1836622012 666 ../functions/algebras/algnorm
+2145716957 230 ../functions/algebras/algpoleval
+3010523485 376 ../functions/algebras/algpow
+1985608982 685 ../functions/algebras/algprimesubalg
+780611881 721 ../functions/algebras/algquotient
+1055827042 822 ../functions/algebras/algradical
+372718674 637 ../functions/algebras/algramifiedplaces
+4111370658 267 ../functions/algebras/algrandom
+466896792 831 ../functions/algebras/algrelmultable
+996623183 760 ../functions/algebras/algsimpledec
+103612713 1389 ../functions/algebras/algsplittingdata
+1194989589 767 ../functions/algebras/algsplittingfield
+1996647248 686 ../functions/algebras/algsplittingmatrix
+960240613 353 ../functions/algebras/algsqr
+642679398 376 ../functions/algebras/algsub
+3788547921 500 ../functions/algebras/algsubalg
+2209271687 1739 ../functions/algebras/algtableinit
+2670339631 584 ../functions/algebras/algtensor
+2229708950 596 ../functions/algebras/algtrace
+1995908831 1174 ../functions/algebras/algtype
 1557685643 1558 ../functions/conversions/Col
 3234299882 400 ../functions/conversions/Colrev
 4195552700 684 ../functions/conversions/List
@@ -6,7 +62,7 @@
 3703587249 1772 ../functions/conversions/Pol
 812817715 914 ../functions/conversions/Polrev
 2844602529 620 ../functions/conversions/Qfb
-2571513257 1826 ../functions/conversions/Ser
+1413791718 1825 ../functions/conversions/Ser
 1244914425 745 ../functions/conversions/Set
 2425486384 993 ../functions/conversions/Str
 1983631051 398 ../functions/conversions/Strchr
@@ -30,9 +86,10 @@
 2027282389 401 ../functions/conversions/conj
 4003200502 838 ../functions/conversions/conjvec
 2494482002 1105 ../functions/conversions/denominator
-863736833 259 ../functions/conversions/digits
+3890428380 308 ../functions/conversions/digits
 2072628265 514 ../functions/conversions/floor
 689569802 220 ../functions/conversions/frac
+3733465262 421 ../functions/conversions/fromdigits
 958959570 550 ../functions/conversions/hammingweight
 293423956 246 ../functions/conversions/imag
 1061890972 1035 ../functions/conversions/length
@@ -43,95 +100,117 @@
 4165166886 433 ../functions/conversions/norm
 765810884 922 ../functions/conversions/numerator
 1895271770 411 ../functions/conversions/numtoperm
+3045216896 393 ../functions/conversions/oo
 622159595 369 ../functions/conversions/padicprec
 137224884 360 ../functions/conversions/permtonum
-3807185038 2929 ../functions/conversions/precision
-3713049196 3331 ../functions/conversions/random
+1797839927 2971 ../functions/conversions/precision
+1247489541 3326 ../functions/conversions/random
 1868514297 244 ../functions/conversions/real
 1814815920 1559 ../functions/conversions/round
 1581212202 1010 ../functions/conversions/simplify
 2803792228 343 ../functions/conversions/sizebyte
-2662166564 350 ../functions/conversions/sizedigit
+1970193605 706 ../functions/conversions/sizedigit
 1113868494 1709 ../functions/conversions/truncate
-3403630479 953 ../functions/conversions/valuation
-3384175128 1425 ../functions/conversions/variable
+2570928087 1031 ../functions/conversions/valuation
+3395959447 2556 ../functions/conversions/varhigher
+2892598405 1869 ../functions/conversions/variable
+3735723900 1066 ../functions/conversions/variables
+2504491136 3296 ../functions/conversions/varlower
 2091712008 516 ../functions/default/TeXstyle
-1101063589 291 ../functions/default/breakloop
+1744298337 288 ../functions/default/breakloop
 2501181600 2179 ../functions/default/colors
-45066311 2219 ../functions/default/compatible
+3015856994 141 ../functions/default/compatible
 1698176216 380 ../functions/default/datadir
 845501215 264 ../functions/default/debug
 1705281810 307 ../functions/default/debugfiles
 2013652512 591 ../functions/default/debugmem
-3848717427 468 ../functions/default/echo
+2315543353 465 ../functions/default/echo
 3483503147 774 ../functions/default/factor_add_primes
 3740185017 672 ../functions/default/factor_proven
 3860891309 1410 ../functions/default/format
-2809565288 1006 ../functions/default/graphcolormap
-3446126174 403 ../functions/default/graphcolors
-398680676 391 ../functions/default/help
-1229391942 562 ../functions/default/histfile
+1870636521 1003 ../functions/default/graphcolormap
+555087692 400 ../functions/default/graphcolors
+1161054041 388 ../functions/default/help
+1058569251 559 ../functions/default/histfile
 3654358528 443 ../functions/default/histsize
-220523559 556 ../functions/default/lines
-1161338771 240 ../functions/default/linewrap
+804309020 553 ../functions/default/lines
+1037801881 237 ../functions/default/linewrap
 2950182014 774 ../functions/default/log
 4131263332 249 ../functions/default/logfile
 281989783 482 ../functions/default/nbthreads
 3548328759 468 ../functions/default/new_galois_format
 852419531 1403 ../functions/default/output
-140801756 712 ../functions/default/parisize
+232928573 875 ../functions/default/parisize
+421302230 827 ../functions/default/parisizemax
 2366699578 712 ../functions/default/path
 1991406625 395 ../functions/default/prettyprinter
 4106670828 1738 ../functions/default/primelimit
-4187737678 1452 ../functions/default/prompt
-673656302 350 ../functions/default/prompt_cont
-3343395058 317 ../functions/default/psfile
-3790396319 438 ../functions/default/readline
+3806881294 1449 ../functions/default/prompt
+576684223 347 ../functions/default/prompt_cont
+3784229291 314 ../functions/default/psfile
+1224291797 435 ../functions/default/readline
 712378547 1306 ../functions/default/realprecision
-312510814 312 ../functions/default/recover
+1281891849 309 ../functions/default/recover
 1228873450 456 ../functions/default/secure
 699347451 257 ../functions/default/seriesprecision
 4068861417 868 ../functions/default/simplify
 3166076333 826 ../functions/default/sopath
 3837614417 832 ../functions/default/strictargs
-2150187344 472 ../functions/default/strictmatch
+2124246976 142 ../functions/default/strictmatch
 563829741 477 ../functions/default/threadsize
-4240558956 932 ../functions/default/timer
-4197571579 1431 ../functions/elliptic_curves/ellL1
+776813016 566 ../functions/default/threadsizemax
+2044127399 929 ../functions/default/timer
+2727567316 1265 ../functions/elliptic_curves/ellL1
 1093349276 227 ../functions/elliptic_curves/elladd
 288388107 1283 ../functions/elliptic_curves/ellak
 994306239 581 ../functions/elliptic_curves/ellan
 1664571559 1126 ../functions/elliptic_curves/ellanalyticrank
-1413240744 2280 ../functions/elliptic_curves/ellap
-74509841 536 ../functions/elliptic_curves/ellbil
-515089431 958 ../functions/elliptic_curves/ellcard
+1149014931 2296 ../functions/elliptic_curves/ellap
+3802676380 186 ../functions/elliptic_curves/ellbil
+1044928453 961 ../functions/elliptic_curves/ellcard
 400654891 599 ../functions/elliptic_curves/ellchangecurve
 286283106 745 ../functions/elliptic_curves/ellchangepoint
 3036975212 727 ../functions/elliptic_curves/ellchangepointinv
 1622337703 620 ../functions/elliptic_curves/ellconvertname
 959851128 885 ../functions/elliptic_curves/elldivpol
-2935267458 1270 ../functions/elliptic_curves/elleisnum
+423067503 1270 ../functions/elliptic_curves/elleisnum
 1336341633 601 ../functions/elliptic_curves/elleta
+4273328684 941 ../functions/elliptic_curves/ellformaldifferential
+2780651412 719 ../functions/elliptic_curves/ellformalexp
+2038371915 674 ../functions/elliptic_curves/ellformallog
+1595209028 977 ../functions/elliptic_curves/ellformalpoint
+2758880974 748 ../functions/elliptic_curves/ellformalw
 2802844850 287 ../functions/elliptic_curves/ellfromj
 1592776600 870 ../functions/elliptic_curves/ellgenerators
 2881662361 1249 ../functions/elliptic_curves/ellglobalred
 1057201550 2793 ../functions/elliptic_curves/ellgroup
 2445648106 1082 ../functions/elliptic_curves/ellheegner
-3354629609 1166 ../functions/elliptic_curves/ellheight
-170338517 805 ../functions/elliptic_curves/ellheightmatrix
+1607376713 721 ../functions/elliptic_curves/ellheight
+1066647709 813 ../functions/elliptic_curves/ellheightmatrix
 1035396547 705 ../functions/elliptic_curves/ellidentify
-1730986466 4261 ../functions/elliptic_curves/ellinit
+1108384190 4514 ../functions/elliptic_curves/ellinit
+2762050491 1048 ../functions/elliptic_curves/ellisdivisible
+2048468232 1044 ../functions/elliptic_curves/ellisogeny
+1779925024 967 ../functions/elliptic_curves/ellisogenyapply
 240812548 602 ../functions/elliptic_curves/ellisoncurve
+1874277860 826 ../functions/elliptic_curves/ellissupersingular
 3064568940 281 ../functions/elliptic_curves/ellj
-1723653689 1242 ../functions/elliptic_curves/elllocalred
+2172225455 1472 ../functions/elliptic_curves/elllocalred
 2579301528 1166 ../functions/elliptic_curves/elllog
 1621101605 661 ../functions/elliptic_curves/elllseries
 904157268 782 ../functions/elliptic_curves/ellminimalmodel
 1775278007 2358 ../functions/elliptic_curves/ellmodulareqn
 2371457085 1054 ../functions/elliptic_curves/ellmul
 2235217918 190 ../functions/elliptic_curves/ellneg
-3036504182 1786 ../functions/elliptic_curves/ellorder
+906417652 664 ../functions/elliptic_curves/ellnonsingularmultiple
+1314089142 1876 ../functions/elliptic_curves/ellorder
 712202039 307 ../functions/elliptic_curves/ellordinate
+1080622774 2524 ../functions/elliptic_curves/ellpadicL
+1034758728 905 ../functions/elliptic_curves/ellpadicfrobenius
+2311743566 2684 ../functions/elliptic_curves/ellpadicheight
+1688216667 687 ../functions/elliptic_curves/ellpadicheightmatrix
+1606024858 578 ../functions/elliptic_curves/ellpadiclog
+1378825097 1267 ../functions/elliptic_curves/ellpadics2
 722101610 1172 ../functions/elliptic_curves/ellperiods
 1794297368 2153 ../functions/elliptic_curves/ellpointtoz
 731455575 162 ../functions/elliptic_curves/ellpow
@@ -141,30 +220,34 @@
 3595576828 241 ../functions/elliptic_curves/ellsub
 3847829045 1085 ../functions/elliptic_curves/elltaniyama
 463127701 362 ../functions/elliptic_curves/elltatepairing
-4013058914 1362 ../functions/elliptic_curves/elltors
+3567448886 807 ../functions/elliptic_curves/elltors
 2219345950 318 ../functions/elliptic_curves/ellweilpairing
 2456249932 1334 ../functions/elliptic_curves/ellwp
+471737010 547 ../functions/elliptic_curves/ellxn
 36981238 1480 ../functions/elliptic_curves/ellzeta
 1222568733 758 ../functions/elliptic_curves/ellztopoint
-1815276599 5553 ../functions/elliptic_curves/genus2red
+727315604 5711 ../functions/elliptic_curves/genus2red
+2832333632 729 ../functions/elliptic_curves/hyperellcharpoly
+3063493560 994 ../functions/elliptic_curves/hyperellpadicfrobenius
 1668730040 123 ../functions/gp2c/DEBUGLEVEL
-977116536 393 ../functions/gp2c/clone
+673657102 528 ../functions/gp2c/clone
 4282475994 385 ../functions/gp2c/copy
 3783251634 108 ../functions/gp2c/unclone
 1891743718 82 ../functions/gp2c_internal/_avma
 2668997632 759 ../functions/gp2c_internal/_badtype
-118976974 2945 ../functions/gp2c_internal/_cast
+1214941351 3151 ../functions/gp2c_internal/_cast
 2617906549 160 ../functions/gp2c_internal/_cgetg
 1229532743 478 ../functions/gp2c_internal/_const
 1013746615 244 ../functions/gp2c_internal/_formatcode
+1852686017 103 ../functions/gp2c_internal/_gc_needed
 2727635652 193 ../functions/gp2c_internal/_gerepileall
 1155278703 344 ../functions/gp2c_internal/_gerepileupto
 2948757155 90 ../functions/gp2c_internal/_maxprime
 1600216421 227 ../functions/gp2c_internal/_stack_lim
 667601403 171 ../functions/gp2c_internal/_strtoclosure
-445566870 730 ../functions/gp2c_internal/_tovec
-918090833 2108 ../functions/gp2c_internal/_typedef
-2426792003 312 ../functions/gp2c_internal/_wrap
+4035878089 888 ../functions/gp2c_internal/_tovec
+722974942 2193 ../functions/gp2c_internal/_typedef
+3508241653 415 ../functions/gp2c_internal/_wrap
 1104882680 596 ../functions/graphic/plot
 165946816 531 ../functions/graphic/plotbox
 2126934426 451 ../functions/graphic/plotclip
@@ -227,11 +310,11 @@
 1920196350 820 ../functions/linear_algebra/matinverseimage
 543305113 230 ../functions/linear_algebra/matisdiagonal
 3529997100 775 ../functions/linear_algebra/matker
-3907458254 868 ../functions/linear_algebra/matkerint
+125900953 561 ../functions/linear_algebra/matkerint
 1800646688 424 ../functions/linear_algebra/matmuldiagonal
 2929869545 432 ../functions/linear_algebra/matmultodiagonal
 3703545803 453 ../functions/linear_algebra/matpascal
-3982066657 941 ../functions/linear_algebra/matqr
+1550537839 952 ../functions/linear_algebra/matqr
 4135328056 138 ../functions/linear_algebra/matrank
 2190495821 621 ../functions/linear_algebra/matrix
 4051332933 1509 ../functions/linear_algebra/matrixqz
@@ -255,9 +338,11 @@
 2571047474 1825 ../functions/linear_algebra/qflllgram
 1151173386 5570 ../functions/linear_algebra/qfminim
 1309940214 1092 ../functions/linear_algebra/qfnorm
+1692086055 905 ../functions/linear_algebra/qfparam
 884649199 631 ../functions/linear_algebra/qfperfection
 3388145892 1110 ../functions/linear_algebra/qfrep
 182597421 360 ../functions/linear_algebra/qfsign
+2176120364 1032 ../functions/linear_algebra/qfsolve
 3023808062 820 ../functions/linear_algebra/seralgdep
 3338722377 634 ../functions/linear_algebra/setbinop
 2553744756 320 ../functions/linear_algebra/setintersect
@@ -267,9 +352,9 @@
 1510185044 290 ../functions/linear_algebra/setunion
 2343012690 397 ../functions/linear_algebra/trace
 1009255636 2824 ../functions/linear_algebra/vecextract
-4066532264 1527 ../functions/linear_algebra/vecsearch
+3204283581 1552 ../functions/linear_algebra/vecsearch
 2127481713 4246 ../functions/linear_algebra/vecsort
-975438261 189 ../functions/linear_algebra/vecsum
+1210136160 289 ../functions/linear_algebra/vecsum
 3969360427 869 ../functions/linear_algebra/vector
 2820295330 518 ../functions/linear_algebra/vectorsmall
 864292486 288 ../functions/linear_algebra/vectorv
@@ -320,6 +405,20 @@
 2066290395 90 ../functions/member_functions/tufu
 1665968088 171 ../functions/member_functions/zk
 2924685257 142 ../functions/member_functions/zkst
+626242422 853 ../functions/modular_forms/msatkinlehner
+3791420813 894 ../functions/modular_forms/mscuspidal
+2763530206 783 ../functions/modular_forms/mseisenstein
+58290885 1746 ../functions/modular_forms/mseval
+3113737247 1556 ../functions/modular_forms/msfromell
+671010731 989 ../functions/modular_forms/mshecke
+4228701829 1382 ../functions/modular_forms/msinit
+132317707 742 ../functions/modular_forms/msissymbol
+2465050845 620 ../functions/modular_forms/msnew
+2508813533 1968 ../functions/modular_forms/mspathgens
+925573144 1092 ../functions/modular_forms/mspathlog
+257636660 1085 ../functions/modular_forms/msqexpansion
+1713575565 1199 ../functions/modular_forms/mssplit
+3206775694 569 ../functions/modular_forms/msstar
 817575908 1451 ../functions/number_fields/bnfcertify
 654416520 1799 ../functions/number_fields/bnfcompress
 1086935842 498 ../functions/number_fields/bnfdecodemodule
@@ -339,8 +438,11 @@
 2388880686 434 ../functions/number_fields/bnrconductorofchar
 4134011564 1456 ../functions/number_fields/bnrdisc
 3292276537 2779 ../functions/number_fields/bnrdisclist
-299142429 2215 ../functions/number_fields/bnrinit
+3847585707 452 ../functions/number_fields/bnrgaloisapply
+2171187845 1024 ../functions/number_fields/bnrgaloismatrix
+2631157809 2218 ../functions/number_fields/bnrinit
 1297085953 549 ../functions/number_fields/bnrisconductor
+3589985364 1386 ../functions/number_fields/bnrisgalois
 4098267331 1306 ../functions/number_fields/bnrisprincipal
 1309169618 1461 ../functions/number_fields/bnrrootnumber
 1162900897 2256 ../functions/number_fields/bnrstark
@@ -356,7 +458,7 @@
 999481307 869 ../functions/number_fields/galoispermtopol
 415883189 2573 ../functions/number_fields/galoissubcyclo
 1739582821 432 ../functions/number_fields/galoissubfields
-1103908484 810 ../functions/number_fields/galoissubgroups
+4087525432 813 ../functions/number_fields/galoissubgroups
 4041888397 1330 ../functions/number_fields/idealadd
 2595771256 868 ../functions/number_fields/idealaddtoone
 988771264 1290 ../functions/number_fields/idealappr
@@ -377,23 +479,24 @@
 2213617432 214 ../functions/number_fields/idealnorm
 3621386739 392 ../functions/number_fields/idealnumden
 590254486 900 ../functions/number_fields/idealpow
-4185462448 1955 ../functions/number_fields/idealprimedec
+331735799 2224 ../functions/number_fields/idealprimedec
 1421736270 775 ../functions/number_fields/idealprincipalunits
 1446079677 1715 ../functions/number_fields/idealramgroups
 477008975 2910 ../functions/number_fields/idealred
 2275219186 2198 ../functions/number_fields/idealstar
 2606691333 1306 ../functions/number_fields/idealtwoelt
-1614130949 338 ../functions/number_fields/idealval
+3391906004 542 ../functions/number_fields/idealval
 2450987406 330 ../functions/number_fields/matalgtobasis
 4263225345 330 ../functions/number_fields/matbasistoalg
 370962582 1543 ../functions/number_fields/modreverse
 923642746 645 ../functions/number_fields/newtonpoly
 74387094 580 ../functions/number_fields/nfalgtobasis
-1254909946 5186 ../functions/number_fields/nfbasis
+660206524 5182 ../functions/number_fields/nfbasis
 794927693 569 ../functions/number_fields/nfbasistoalg
 1941191205 887 ../functions/number_fields/nfcertify
+4206073549 3226 ../functions/number_fields/nfcompositum
 1793444342 342 ../functions/number_fields/nfdetint
-3831355376 1546 ../functions/number_fields/nfdisc
+2662403780 1539 ../functions/number_fields/nfdisc
 2893425002 219 ../functions/number_fields/nfeltadd
 3704437998 223 ../functions/number_fields/nfeltdiv
 64595969 403 ../functions/number_fields/nfeltdiveuc
@@ -408,16 +511,17 @@
 3760170244 359 ../functions/number_fields/nfeltreduce
 3125536475 519 ../functions/number_fields/nfeltreducemodpr
 2932345806 150 ../functions/number_fields/nfelttrace
-3293746003 460 ../functions/number_fields/nfeltval
+69697065 1744 ../functions/number_fields/nfeltval
 1589700260 1566 ../functions/number_fields/nffactor
 973653093 818 ../functions/number_fields/nffactorback
 488334419 1043 ../functions/number_fields/nffactormod
 973104481 2219 ../functions/number_fields/nfgaloisapply
 3907195035 2623 ../functions/number_fields/nfgaloisconj
+774726221 1918 ../functions/number_fields/nfgrunwaldwang
 624126709 736 ../functions/number_fields/nfhilbert
-2072610218 507 ../functions/number_fields/nfhnf
+1057485554 774 ../functions/number_fields/nfhnf
 868333029 539 ../functions/number_fields/nfhnfmod
-1082558102 7702 ../functions/number_fields/nfinit
+2680138903 7876 ../functions/number_fields/nfinit
 1575169407 243 ../functions/number_fields/nfisideal
 196768795 980 ../functions/number_fields/nfisincl
 1085970401 276 ../functions/number_fields/nfisisom
@@ -426,10 +530,11 @@
 987402003 612 ../functions/number_fields/nfnewprec
 770708172 1418 ../functions/number_fields/nfroots
 967762132 1587 ../functions/number_fields/nfrootsof1
-503060488 1181 ../functions/number_fields/nfsnf
+118612559 1423 ../functions/number_fields/nfsnf
 1005488227 839 ../functions/number_fields/nfsolvemodpr
+2330291555 899 ../functions/number_fields/nfsplitting
 2732061843 972 ../functions/number_fields/nfsubfields
-1252868226 3254 ../functions/number_fields/polcompositum
+2177394093 4011 ../functions/number_fields/polcompositum
 1565615061 4266 ../functions/number_fields/polgalois
 754868682 1743 ../functions/number_fields/polred
 1630097175 4003 ../functions/number_fields/polredabs
@@ -452,7 +557,7 @@
 205183268 667 ../functions/number_fields/rnfeltup
 4138499114 2180 ../functions/number_fields/rnfequation
 3457630168 562 ../functions/number_fields/rnfhnfbasis
-3710921157 1501 ../functions/number_fields/rnfidealabstorel
+3668542085 1497 ../functions/number_fields/rnfidealabstorel
 3524519381 482 ../functions/number_fields/rnfidealdown
 2124882618 471 ../functions/number_fields/rnfidealhnf
 2972910198 410 ../functions/number_fields/rnfidealmul
@@ -461,14 +566,14 @@
 295860721 993 ../functions/number_fields/rnfidealreltoabs
 3572608050 463 ../functions/number_fields/rnfidealtwoelt
 460503870 915 ../functions/number_fields/rnfidealup
-890141568 3847 ../functions/number_fields/rnfinit
+1085006596 4388 ../functions/number_fields/rnfinit
 3000009520 440 ../functions/number_fields/rnfisabelian
 301910451 511 ../functions/number_fields/rnfisfree
 788695769 2247 ../functions/number_fields/rnfisnorm
 2615116728 1060 ../functions/number_fields/rnfisnorminit
 1544630009 1346 ../functions/number_fields/rnfkummer
 1089289418 648 ../functions/number_fields/rnflllgram
-2727680788 1102 ../functions/number_fields/rnfnormgroup
+2677163276 1247 ../functions/number_fields/rnfnormgroup
 1425929762 773 ../functions/number_fields/rnfpolred
 2338701732 1880 ../functions/number_fields/rnfpolredabs
 2550913263 1973 ../functions/number_fields/rnfpolredbest
@@ -484,7 +589,7 @@
 3857964875 371 ../functions/number_theoretical/bigomega
 590656338 526 ../functions/number_theoretical/binomial
 3062219339 1967 ../functions/number_theoretical/chinese
-686535871 1031 ../functions/number_theoretical/content
+3029095152 1156 ../functions/number_theoretical/content
 1721333311 2932 ../functions/number_theoretical/contfrac
 2762680277 1347 ../functions/number_theoretical/contfracpnqn
 1215033860 661 ../functions/number_theoretical/core
@@ -501,7 +606,7 @@
 4089779703 347 ../functions/number_theoretical/factorial
 3706897439 2084 ../functions/number_theoretical/factorint
 4224377394 813 ../functions/number_theoretical/factormod
-2120464340 1834 ../functions/number_theoretical/ffgen
+2035832219 1984 ../functions/number_theoretical/ffgen
 4176254427 703 ../functions/number_theoretical/ffinit
 3488041316 1370 ../functions/number_theoretical/fflog
 3597614832 652 ../functions/number_theoretical/ffnbirred
@@ -513,16 +618,17 @@
 514753190 536 ../functions/number_theoretical/hilbert
 1861985508 377 ../functions/number_theoretical/isfundamental
 4121111175 479 ../functions/number_theoretical/ispolygonal
-3013969901 1221 ../functions/number_theoretical/ispower
-2938323692 460 ../functions/number_theoretical/ispowerful
+179939414 1208 ../functions/number_theoretical/ispower
+2327997766 484 ../functions/number_theoretical/ispowerful
 3017578398 2646 ../functions/number_theoretical/isprime
 1951470040 472 ../functions/number_theoretical/isprimepower
-2569893220 1562 ../functions/number_theoretical/ispseudoprime
+2311445093 1562 ../functions/number_theoretical/ispseudoprime
+137991166 889 ../functions/number_theoretical/ispseudoprimepower
 3271459303 1518 ../functions/number_theoretical/issquare
 389293029 301 ../functions/number_theoretical/issquarefree
 3038253040 442 ../functions/number_theoretical/istotient
 756622456 758 ../functions/number_theoretical/kronecker
-3492197658 1446 ../functions/number_theoretical/lcm
+1278866935 1522 ../functions/number_theoretical/lcm
 2023281030 968 ../functions/number_theoretical/logint
 2160606288 190 ../functions/number_theoretical/moebius
 4254054828 481 ../functions/number_theoretical/nextprime
@@ -535,7 +641,7 @@
 3693765799 270 ../functions/number_theoretical/prime
 429279699 442 ../functions/number_theoretical/primepi
 530053972 619 ../functions/number_theoretical/primes
-2798669539 2553 ../functions/number_theoretical/qfbclassno
+3694653558 2705 ../functions/number_theoretical/qfbclassno
 3695050800 431 ../functions/number_theoretical/qfbcompraw
 1940983238 339 ../functions/number_theoretical/qfbhclassno
 973965715 902 ../functions/number_theoretical/qfbnucomp
@@ -543,9 +649,10 @@
 3393949890 338 ../functions/number_theoretical/qfbpowraw
 3859788640 639 ../functions/number_theoretical/qfbprimeform
 760904670 1434 ../functions/number_theoretical/qfbred
+3921590456 657 ../functions/number_theoretical/qfbredsl2
 2106514910 916 ../functions/number_theoretical/qfbsolve
 3231541093 2938 ../functions/number_theoretical/quadclassunit
-411309927 217 ../functions/number_theoretical/quaddisc
+3694460288 541 ../functions/number_theoretical/quaddisc
 4137872200 445 ../functions/number_theoretical/quadgen
 1926712746 577 ../functions/number_theoretical/quadhilbert
 1522706503 423 ../functions/number_theoretical/quadpoly
@@ -557,10 +664,10 @@
 405726717 467 ../functions/number_theoretical/sigma
 2721939469 441 ../functions/number_theoretical/sqrtint
 504793252 509 ../functions/number_theoretical/sqrtnint
-3464175627 1336 ../functions/number_theoretical/stirling
+2352169098 1346 ../functions/number_theoretical/stirling
 1102505332 332 ../functions/number_theoretical/sumdedekind
-1060747982 357 ../functions/number_theoretical/sumdigits
-3270801584 2239 ../functions/number_theoretical/zncoppersmith
+1567067073 613 ../functions/number_theoretical/sumdigits
+1410684096 2263 ../functions/number_theoretical/zncoppersmith
 581186171 2248 ../functions/number_theoretical/znlog
 2737149070 769 ../functions/number_theoretical/znorder
 247007143 690 ../functions/number_theoretical/znprimroot
@@ -570,25 +677,27 @@
 1311333090 875 ../functions/operators/lex
 3424443404 548 ../functions/operators/max
 1305994321 548 ../functions/operators/min
+2383733157 207 ../functions/operators/powers
 2356147055 550 ../functions/operators/shift
 1941910361 424 ../functions/operators/shiftmul
 2474408050 291 ../functions/operators/sign
 2122378256 865 ../functions/operators/vecmax
 3459801581 867 ../functions/operators/vecmin
 3728482663 863 ../functions/polynomials/O
-3840401116 192 ../functions/polynomials/bezoutres
+1819362815 193 ../functions/polynomials/bezoutres
 542241653 848 ../functions/polynomials/deriv
 3783180479 1942 ../functions/polynomials/diffop
-2644110396 1484 ../functions/polynomials/eval
-997399994 1498 ../functions/polynomials/factorpadic
+739426567 1572 ../functions/polynomials/eval
+663040141 1492 ../functions/polynomials/factorpadic
 1249194359 1397 ../functions/polynomials/intformal
 986511628 730 ../functions/polynomials/padicappr
 2143739774 1841 ../functions/polynomials/padicfields
 2394852716 1226 ../functions/polynomials/polchebyshev
-791830338 1027 ../functions/polynomials/polcoeff
+2712494786 415 ../functions/polynomials/polclass
+56811805 1157 ../functions/polynomials/polcoeff
 3865942159 896 ../functions/polynomials/polcyclo
 3980671021 912 ../functions/polynomials/polcyclofactors
-2540383469 797 ../functions/polynomials/poldegree
+931656876 742 ../functions/polynomials/poldegree
 1629390302 482 ../functions/polynomials/poldisc
 1885087402 528 ../functions/polynomials/poldiscreduced
 838056086 250 ../functions/polynomials/polgraeffe
@@ -600,33 +709,35 @@
 2559408188 460 ../functions/polynomials/polisirreducible
 4266292747 609 ../functions/polynomials/pollead
 693228044 460 ../functions/polynomials/pollegendre
+2327968050 1311 ../functions/polynomials/polmodular
 803988097 240 ../functions/polynomials/polrecip
 1033208739 1192 ../functions/polynomials/polresultant
 3717931312 827 ../functions/polynomials/polresultantext
 2456631457 760 ../functions/polynomials/polroots
 3629305914 706 ../functions/polynomials/polrootsmod
 943111125 1016 ../functions/polynomials/polrootspadic
-3644766318 523 ../functions/polynomials/polsturm
+1194699357 1682 ../functions/polynomials/polrootsreal
+3506598208 1229 ../functions/polynomials/polsturm
 2495767096 741 ../functions/polynomials/polsubcyclo
 1076716398 656 ../functions/polynomials/polsylvestermatrix
 368684839 285 ../functions/polynomials/polsym
 1218299547 184 ../functions/polynomials/poltchebi
-2974829760 714 ../functions/polynomials/polzagier
+3918042108 1020 ../functions/polynomials/polzagier
 3084901600 333 ../functions/polynomials/serconvol
-678736819 330 ../functions/polynomials/serlaplace
+131956016 347 ../functions/polynomials/serlaplace
 1323530505 398 ../functions/polynomials/serreverse
 1472934463 1070 ../functions/polynomials/subst
 1374933613 1103 ../functions/polynomials/substpol
 2817986031 662 ../functions/polynomials/substvec
 2581224437 1040 ../functions/polynomials/sumformal
 226826326 702 ../functions/polynomials/taylor
-1270801577 2607 ../functions/polynomials/thue
-3735388021 992 ../functions/polynomials/thueinit
+3673679320 2602 ../functions/polynomials/thue
+1266732821 2968 ../functions/polynomials/thueinit
 3300553752 136 ../functions/programming/_eval_mnemonic
 3140964717 1110 ../functions/programming/addhelp
-983874885 1936 ../functions/programming/alarm
+455356863 1926 ../functions/programming/alarm
 164541180 1843 ../functions/programming/alias
-2897255199 2301 ../functions/programming/allocatemem
+2788866922 4567 ../functions/programming/allocatemem
 3731392400 1596 ../functions/programming/apply
 1649867724 490 ../functions/programming/break
 3619971697 685 ../functions/programming/breakpoint
@@ -637,8 +748,9 @@
 673969152 1794 ../functions/programming/default
 3384828003 243 ../functions/programming/errname
 2772696481 674 ../functions/programming/error
-1852833943 400 ../functions/programming/extern
-2658094063 458 ../functions/programming/externstr
+3990237234 391 ../functions/programming/extern
+81173858 448 ../functions/programming/externstr
+996397508 680 ../functions/programming/fold
 1154955545 285 ../functions/programming/for
 1548115268 1490 ../functions/programming/forcomposite
 1930174191 1067 ../functions/programming/fordiv
@@ -648,26 +760,28 @@
 4097689279 583 ../functions/programming/forstep
 3286177718 2061 ../functions/programming/forsubgroup
 1526035725 1339 ../functions/programming/forvec
-1575287630 347 ../functions/programming/getabstime
+1907835141 413 ../functions/programming/getabstime
 748638207 252 ../functions/programming/getenv
-4278770330 361 ../functions/programming/getheap
+1277212506 377 ../functions/programming/getheap
 3575456435 442 ../functions/programming/getrand
 4109487323 285 ../functions/programming/getstack
-3623950775 385 ../functions/programming/gettime
+3150979343 449 ../functions/programming/gettime
+503409212 331 ../functions/programming/getwalltime
 551521830 165 ../functions/programming/global
 1141761031 2392 ../functions/programming/if
-3720775545 10465 ../functions/programming/iferr
+1726980669 10246 ../functions/programming/iferr
 2051796286 494 ../functions/programming/inline
-1949270646 754 ../functions/programming/input
+132054800 746 ../functions/programming/input
 490792963 3434 ../functions/programming/install
 2467288771 1469 ../functions/programming/kill
 3065531026 125 ../functions/programming/local
+1095397871 2220 ../functions/programming/localprec
 2557836032 115 ../functions/programming/my
 1218387207 521 ../functions/programming/next
 315903861 794 ../functions/programming/parapply
 407023495 541 ../functions/programming/pareval
-168871054 1080 ../functions/programming/parfor
-2197030888 896 ../functions/programming/parforprime
+476875235 1149 ../functions/programming/parfor
+3077276986 970 ../functions/programming/parforprime
 325469141 592 ../functions/programming/parselect
 2300142208 700 ../functions/programming/parsum
 3003736710 744 ../functions/programming/parvector
@@ -678,13 +792,14 @@
 2686332207 415 ../functions/programming/printsep1
 1208643084 604 ../functions/programming/printtex
 203110110 447 ../functions/programming/quit
-1497408310 835 ../functions/programming/read
-2733156182 394 ../functions/programming/readstr
+825700248 832 ../functions/programming/read
+1942540668 384 ../functions/programming/readstr
 2278186691 967 ../functions/programming/readvec
 1182439920 287 ../functions/programming/return
 1550019273 2768 ../functions/programming/select
+3703969658 374 ../functions/programming/self
 3452942428 504 ../functions/programming/setrand
-3720197410 447 ../functions/programming/system
+1512723254 400 ../functions/programming/system
 3717803513 2317 ../functions/programming/trap
 722695522 608 ../functions/programming/type
 419976951 184 ../functions/programming/uninline
@@ -705,9 +820,9 @@
 3096883269 1556 ../functions/sums/intfuncinit
 3456264235 2300 ../functions/sums/intlaplaceinv
 2519244525 2071 ../functions/sums/intmellininv
-1440289081 2077 ../functions/sums/intmellininvshort
-528809183 12017 ../functions/sums/intnum
-1762228811 1941 ../functions/sums/intnuminit
+3633417749 2041 ../functions/sums/intmellininvshort
+223149020 11817 ../functions/sums/intnum
+1298834224 1939 ../functions/sums/intnuminit
 3061973932 975 ../functions/sums/intnuminitgen
 2361868629 2774 ../functions/sums/intnumromb
 400964355 342 ../functions/sums/intnumstep
@@ -716,14 +831,14 @@
 4010920763 901 ../functions/sums/prodinf
 3627520822 712 ../functions/sums/solve
 1209900028 648 ../functions/sums/sum
-2063081340 2085 ../functions/sums/sumalt
+3687431531 3330 ../functions/sums/sumalt
 2396474070 511 ../functions/sums/sumdiv
 3260846671 413 ../functions/sums/sumdivmult
 4053719439 1152 ../functions/sums/suminf
 2896834138 4953 ../functions/sums/sumnum
 1929035087 2463 ../functions/sums/sumnumalt
 763341576 559 ../functions/sums/sumnuminit
-233495912 1413 ../functions/sums/sumpos
+2459440955 2147 ../functions/sums/sumpos
 3764491866 847 ../functions/symbolic_operators/add
 3353925834 892 ../functions/symbolic_operators/adde
 2224582694 150 ../functions/symbolic_operators/and
diff --git a/src/functions/algebras/algabsdim b/src/functions/algebras/algabsdim
new file mode 100644
index 0000000..30b0a9e
--- /dev/null
+++ b/src/functions/algebras/algabsdim
@@ -0,0 +1,14 @@
+Function: algabsdim
+Section: algebras
+C-Name: algabsdim
+Prototype: lG
+Help: algabsdim(al): dimension of the algebra al over its prime subfield.
+Doc: Given an algebra \var{al} output by \tet{alginit} or by
+ \tet{algtableinit}, returns the dimension of \var{al} over its prime subfield
+ ($\Q$ or $\F_p$).
+ \bprog
+ ? nf = nfinit(y^3-y+1);
+ ? A = alginit(nf, [-1,-1]);
+ ? algabsdim(A)
+ %3 = 12
+ @eprog
diff --git a/src/functions/algebras/algadd b/src/functions/algebras/algadd
new file mode 100644
index 0000000..f91b01f
--- /dev/null
+++ b/src/functions/algebras/algadd
@@ -0,0 +1,14 @@
+Function: algadd
+Section: algebras
+C-Name: algadd
+Prototype: GGG
+Help: algadd(al,x,y): element x+y in al.
+Doc: Given two elements $x$ and $y$ in \var{al}, computes their sum $x+y$ in
+ the algebra~\var{al}.
+ \bprog
+ ? A = alginit(nfinit(y),[-1,1]);
+ ? algadd(A,[1,0]~,[1,2]~)
+ %2 = [2, 2]~
+ @eprog
+
+ Also accepts matrices with coefficients in \var{al}.
diff --git a/src/functions/algebras/algalgtobasis b/src/functions/algebras/algalgtobasis
new file mode 100644
index 0000000..4ea83e6
--- /dev/null
+++ b/src/functions/algebras/algalgtobasis
@@ -0,0 +1,16 @@
+Function: algalgtobasis
+Section: algebras
+C-Name: algalgtobasis
+Prototype: GG
+Help: algalgtobasis(al,x): transforms the element x of the algebra al into a
+ column vector on the integral basis of al.
+Doc: Given an element \var{x} in the central simple algebra \var{al} output
+ by \tet{alginit}, transforms it to a column vector on the integral basis of
+ \var{al}. This is the inverse function of \tet{algbasistoalg}.
+ \bprog
+ ? A = alginit(nfinit(y^2-5),[2,y]);
+ ? algalgtobasis(A,[y,1]~)
+ %2 = [0, 2, 0, -1, 2, 0, 0, 0]~
+ ? algbasistoalg(A,algalgtobasis(A,[y,1]~))
+ %3 = [Mod(Mod(y, y^2 - 5), x^2 - 2), 1]~
+ @eprog
diff --git a/src/functions/algebras/algaut b/src/functions/algebras/algaut
new file mode 100644
index 0000000..d641687
--- /dev/null
+++ b/src/functions/algebras/algaut
@@ -0,0 +1,16 @@
+Function: algaut
+Section: algebras
+C-Name: algaut
+Prototype: G
+Help: algaut(al): the stored automorphism of the splitting field of the
+ cyclic algebra al.
+Doc: Given a cyclic algebra $\var{al} = (L/K,\sigma,b)$ output by
+ \tet{alginit}, returns the automorphism $\sigma$.
+ \bprog
+ ? nf = nfinit(y);
+ ? p = idealprimedec(nf,7)[1];
+ ? p2 = idealprimedec(nf,11)[1];
+ ? A = alginit(nf,[3,[[p,p2],[1/3,2/3]],[0]]);
+ ? algaut(A)
+ %5 = -1/3*x^2 + 1/3*x + 26/3
+ @eprog
diff --git a/src/functions/algebras/algb b/src/functions/algebras/algb
new file mode 100644
index 0000000..2cfc46e
--- /dev/null
+++ b/src/functions/algebras/algb
@@ -0,0 +1,16 @@
+Function: algb
+Section: algebras
+C-Name: algb
+Prototype: G
+Help: algb(al): the element b of the center of the cyclic algebra al used
+ to define it.
+Doc: Given a cyclic algebra $\var{al} = (L/K,\sigma,b)$ output by
+ \tet{alginit}, returns the element $b\in K$.
+ \bprog
+ nf = nfinit(y);
+ ? p = idealprimedec(nf,7)[1];
+ ? p2 = idealprimedec(nf,11)[1];
+ ? A = alginit(nf,[3,[[p,p2],[1/3,2/3]],[0]]);
+ ? algb(A)
+ %5 = Mod(-77, y)
+ @eprog
diff --git a/src/functions/algebras/algbasis b/src/functions/algebras/algbasis
new file mode 100644
index 0000000..85db910
--- /dev/null
+++ b/src/functions/algebras/algbasis
@@ -0,0 +1,20 @@
+Function: algbasis
+Section: algebras
+C-Name: algbasis
+Prototype: G
+Help: algbasis(al): basis of the stored order of the central simple algebra al.
+Doc: Given an central simple algebra \var{al} output by \tet{alginit}, returns
+ a $\Z$-basis of the order~${\cal O}_0$ stored in \var{al} with respect to the
+ natural order in \var{al}. It is a maximal order if one has been computed.
+ \bprog
+ A = alginit(nfinit(y), [-1,-1]);
+ ? algbasis(A)
+ %2 =
+ [1 0 0 1/2]
+
+ [0 1 0 1/2]
+
+ [0 0 1 1/2]
+
+ [0 0 0 1/2]
+ @eprog
diff --git a/src/functions/algebras/algbasistoalg b/src/functions/algebras/algbasistoalg
new file mode 100644
index 0000000..222e326
--- /dev/null
+++ b/src/functions/algebras/algbasistoalg
@@ -0,0 +1,18 @@
+Function: algbasistoalg
+Section: algebras
+C-Name: algbasistoalg
+Prototype: GG
+Help: algbasistoalg(al,x): transforms the column vector x on the integral
+ basis of al into an element of al in algebraic form.
+
+Doc: Given an element \var{x} in the central simple algebra \var{al} output
+ by \tet{alginit}, transforms it to its algebraic representation in \var{al}.
+ This is the inverse function of \tet{algalgtobasis}.
+ \bprog
+ ? A = alginit(nfinit(y^2-5),[2,y]);
+ ? z = algbasistoalg(A,[0,1,0,0,2,-3,0,0]~);
+ ? liftall(z)
+ %3 = [(-1/2*y - 2)*x + (-1/4*y + 5/4), -3/4*y + 7/4]~
+ ? algalgtobasis(A,z)
+ %4 = [0, 1, 0, 0, 2, -3, 0, 0]~
+ @eprog
diff --git a/src/functions/algebras/algcenter b/src/functions/algebras/algcenter
new file mode 100644
index 0000000..32c11a8
--- /dev/null
+++ b/src/functions/algebras/algcenter
@@ -0,0 +1,34 @@
+Function: algcenter
+Section: algebras
+C-Name: gp_algcenter
+Prototype: G
+Help: algcenter(al): center of the algebra al.
+Doc: If \var{al} is a table algebra output by \tet{algtableinit}, returns a
+ basis of the center of the algebra~\var{al} over its prime field ($\Q$ or
+ $\F_p$). If \var{al} is a central simple algebra output by \tet{alginit},
+ returns the center of~\var{al}, which is stored in \var{al}.
+
+ A simple example: the $2\times 2$ upper triangular matrices over $\Q$,
+ generated by $I_2$, $a = \kbd{[0,1;0,0]}$ and $b = \kbd{[0,0;0,1]}$,
+ such that $a^2 = 0$, $ab = a$, $ba = 0$, $b^2 = b$: the diagonal matrices
+ for the center.
+ \bprog
+ ? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
+ ? A = algtableinit(mt);
+ ? algcenter(A) \\ = (I_2)
+ %3 =
+ [1]
+
+ [0]
+
+ [0]
+ @eprog
+
+ An example in the central simple case:
+
+ \bprog
+ ? nf = nfinit(y^3-y+1);
+ ? A = alginit(nf, [-1,-1]);
+ ? algcenter(A).pol
+ %3 = y^3 - y + 1
+ @eprog
diff --git a/src/functions/algebras/algcentralproj b/src/functions/algebras/algcentralproj
new file mode 100644
index 0000000..d3283b5
--- /dev/null
+++ b/src/functions/algebras/algcentralproj
@@ -0,0 +1,27 @@
+Function: algcentralproj
+Section: algebras
+C-Name: alg_centralproj
+Prototype: GGD0,L,
+Help: algcentralproj(al,z,{maps=0}): projections of the algebra al on the
+ orthogonal central idempotents z[i].
+Doc: Given a table algebra \var{al} output by \tet{algtableinit} and a
+ \typ{VEC} $\var{z}=[z_1,\dots,z_n]$ of orthogonal central idempotents,
+ returns a \typ{VEC} $[al_1,\dots,al_n]$ of algebras such that
+ $al_i = z_i\, al$. If $\var{maps}=1$, each $al_i$ is a \typ{VEC}
+ $[quo,proj,lift]$ where \var{quo} is the quotient algebra, \var{proj} is a
+ \typ{MAT} representing the projection onto this quotient and \var{lift} is a
+ \typ{MAT} representing a lift.
+
+ A simple example: $\F_2\oplus \F_4$, generated by~$1=(1,1)$, $e=(1,0)$
+ and~$x$ such that~$x^2+x+1=0$. We have~$e^2=e$, $x^2=x+1$ and~$ex=0$.
+ \bprog
+ ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+ ? A = algtableinit(mt,2);
+ ? e = [0,1,0]~;
+ ? e2 = algsub(A,[1,0,0]~,e);
+ ? [a,a2] = algcentralproj(A,[e,e2]);
+ ? algdim(a)
+ %6 = 1
+ ? algdim(a2)
+ %7 = 2
+ @eprog
diff --git a/src/functions/algebras/algchar b/src/functions/algebras/algchar
new file mode 100644
index 0000000..c25e750
--- /dev/null
+++ b/src/functions/algebras/algchar
@@ -0,0 +1,13 @@
+Function: algchar
+Section: algebras
+C-Name: algchar
+Prototype: G
+Help: algchar(al): characteristic of the algebra al.
+Doc: Given an algebra \var{al} output by \tet{alginit} or \tet{algtableinit},
+ returns the characteristic of \var{al}.
+ \bprog
+ ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+ ? A = algtableinit(mt,13);
+ ? algchar(A)
+ %3 = 13
+ @eprog
diff --git a/src/functions/algebras/algcharpoly b/src/functions/algebras/algcharpoly
new file mode 100644
index 0000000..800d79b
--- /dev/null
+++ b/src/functions/algebras/algcharpoly
@@ -0,0 +1,21 @@
+Function: algcharpoly
+Section: algebras
+C-Name: algcharpoly
+Prototype: GGDn
+Help: algcharpoly(al,b,{v='x}): (reduced) characteristic polynomial of b in
+ \var{al}, with respect to the variable $v$.
+
+Doc: Given an element $b$ in \var{al}, returns its characteristic polynomial
+ as a polynomial in the variable $v$. If \var{al} is a table algebra output
+ by \tet{algtableinit}, returns the absolute characteristic polynomial of
+ \var{b}, which is an element of $\F_p[v]$ or~$\Q[v]$; if \var{al} is a
+ central simple algebra output by \tet{alginit}, returns the reduced
+ characteristic polynomial of \var{b}, which is an element of $K[v]$ where~$K$
+ is the center of \var{al}.
+ \bprog
+ ? al = alginit(nfinit(y), [-1,-1]); \\ (-1,-1)_Q
+ ? algcharpoly(al, [0,1]~)
+ %2 = x^2 + 1
+ @eprog
+
+ Also accepts a square matrix with coefficients in \var{al}.
diff --git a/src/functions/algebras/algdecomposition b/src/functions/algebras/algdecomposition
new file mode 100644
index 0000000..117ffb7
--- /dev/null
+++ b/src/functions/algebras/algdecomposition
@@ -0,0 +1,9 @@
+Function: algdecomposition
+Section: algebras
+C-Name: alg_decomposition
+Prototype: G
+Help: algdecomposition(al): semisimple decomposition of the algebra al.
+Doc: \var{al} being a table algebra output by \tet{algtableinit}, returns
+ $[J,[al_1,\dots,al_n]]$ where $J$ is a basis of the Jacobson radical of
+ \var{al} and $al_1,\dots,al_n$ are the simple factors of the semisimple
+ algebra $al/J$.
diff --git a/src/functions/algebras/algdegree b/src/functions/algebras/algdegree
new file mode 100644
index 0000000..5ca7d45
--- /dev/null
+++ b/src/functions/algebras/algdegree
@@ -0,0 +1,13 @@
+Function: algdegree
+Section: algebras
+C-Name: algdegree
+Prototype: lG
+Help: algdegree(al): degree of the central simple algebra al.
+Doc: Given a central simple algebra \var{al} output by \tet{alginit}, returns
+ the degree of \var{al}.
+ \bprog
+ ? nf = nfinit(y^3-y+1);
+ ? A = alginit(nf, [-1,-1]);
+ ? algdegree(A)
+ %3 = 2
+ @eprog
diff --git a/src/functions/algebras/algdim b/src/functions/algebras/algdim
new file mode 100644
index 0000000..cb5f8db
--- /dev/null
+++ b/src/functions/algebras/algdim
@@ -0,0 +1,15 @@
+Function: algdim
+Section: algebras
+C-Name: algdim
+Prototype: lG
+Help: algdim(al): dimension of the algebra al.
+Doc: Given a central simple algebra \var{al} output by \tet{alginit}, returns
+ the dimension of \var{al} over its center. Given a table algebra \var{al}
+ output by \tet{algtableinit}, returns the dimension of \var{al} over its prime
+ subfield ($\Q$ or $\F_p$).
+ \bprog
+ ? nf = nfinit(y^3-y+1);
+ ? A = alginit(nf, [-1,-1]);
+ ? algdim(A)
+ %3 = 4
+ @eprog
diff --git a/src/functions/algebras/algdisc b/src/functions/algebras/algdisc
new file mode 100644
index 0000000..c97b5c6
--- /dev/null
+++ b/src/functions/algebras/algdisc
@@ -0,0 +1,21 @@
+Function: algdisc
+Section: algebras
+C-Name: algdisc
+Prototype: G
+Help: algdisc(al): discriminant of the stored order of the algebra al.
+Doc: Given a central simple algebra \var{al} output by \tet{alginit}, computes
+ the discriminant of the order ${\cal O}_0$ stored in \var{al}, that is the
+ determinant of the trace form $\rm{Tr} : {\cal O}_0\times {\cal O}_0 \to \Z$.
+ \bprog
+ ? nf = nfinit(y^2-5);
+ ? A = alginit(nf, [-3,1-y]);
+ ? [PR,h] = alghassef(A);
+ %3 = [[[2, [2, 0]~, 1, 2, 1], [3, [3, 0]~, 1, 2, 1]], Vecsmall([0, 1])]
+ ? n = algdegree(A);
+ ? D = algabsdim(A);
+ ? h = vector(#h, i, n - gcd(n,h[i]));
+ ? n^D * nf.disc^(n^2) * idealnorm(nf, idealfactorback(nf,PR,h))^n
+ %4 = 12960000
+ ? algdisc(A)
+ %5 = 12960000
+ @eprog
diff --git a/src/functions/algebras/algdivl b/src/functions/algebras/algdivl
new file mode 100644
index 0000000..2df96a5
--- /dev/null
+++ b/src/functions/algebras/algdivl
@@ -0,0 +1,10 @@
+Function: algdivl
+Section: algebras
+C-Name: algdivl
+Prototype: GGG
+Help: algdivl(al,x,y): element x\y in al.
+Doc: Given two elements $x$ and $y$ in \var{al}, computes their left quotient
+ $x\backslash y$ in the algebra \var{al}: an element $z$ such that $xz=y$ (such
+ an element is not unique when $x$ is a zerodivisor). If~$x$ is invertible, this
+ is the same as $x^{-1}y$. Assumes that $y$ is left divisible by $x$ (i.e. that
+ $z$ exists). Also accepts matrices with coefficients in~\var{al}.
diff --git a/src/functions/algebras/algdivr b/src/functions/algebras/algdivr
new file mode 100644
index 0000000..f0ed278
--- /dev/null
+++ b/src/functions/algebras/algdivr
@@ -0,0 +1,7 @@
+Function: algdivr
+Section: algebras
+C-Name: algdivr
+Prototype: GGG
+Help: algdivr(al,x,y): element x/y in al.
+Doc: Given two elements $x$ and $y$ in \var{al}, return $xy^{-1}$. Also accepts
+ matrices with coefficients in \var{al}.
diff --git a/src/functions/algebras/alghasse b/src/functions/algebras/alghasse
new file mode 100644
index 0000000..350b604
--- /dev/null
+++ b/src/functions/algebras/alghasse
@@ -0,0 +1,21 @@
+Function: alghasse
+Section: algebras
+C-Name: alghasse
+Prototype: GG
+Help: alghasse(al,pl): the hasse invariant of the central simple algebra al at
+ the place pl.
+Doc: Given a central simple algebra \var{al} output by \tet{alginit} and a prime
+ ideal or an integer between $1$ and $r_1+r_2$, returns a \typ{FRAC} $h$ : the
+ local Hasse invariant of \var{al} at the place specified by \var{pl}.
+ \bprog
+ ? nf = nfinit(y^2-5);
+ ? A = alginit(nf, [-1,y]);
+ ? alghasse(A, 1)
+ %3 = 1/2
+ ? alghasse(A, 2)
+ %4 = 0
+ ? alghasse(A, idealprimedec(nf,2)[1])
+ %5 = 1/2
+ ? alghasse(A, idealprimedec(nf,5)[1])
+ %6 = 0
+ @eprog
diff --git a/src/functions/algebras/alghassef b/src/functions/algebras/alghassef
new file mode 100644
index 0000000..2faac25
--- /dev/null
+++ b/src/functions/algebras/alghassef
@@ -0,0 +1,18 @@
+Function: alghassef
+Section: algebras
+C-Name: alghassef
+Prototype: G
+Help: alghassef(al): the hasse invariant of the central simple algebra al at finite places.
+Doc: Given a central simple algebra \var{al} output by \tet{alginit}, returns
+ a \typ{VEC} $[\kbd{PR}, h_f]$ describing the local Hasse invariants at the
+ finite places of the center: \kbd{PR} is a \typ{VEC} of primes and $h_f$ is a
+ \typ{VECSMALL} of integers modulo the degree $d$ of \var{al}.
+ \bprog
+ ? nf = nfinit(y^2-5);
+ ? A = alginit(nf, [-1,2*y-1]);
+ ? [PR,hf] = alghassef(A);
+ ? PR
+ %4 = [[19, [10, 2]~, 1, 1, [-8, 2; 2, -10]], [2, [2, 0]~, 1, 2, 1]]
+ ? hf
+ %5 = Vecsmall([1, 0])
+ @eprog
diff --git a/src/functions/algebras/alghassei b/src/functions/algebras/alghassei
new file mode 100644
index 0000000..9b59c5e
--- /dev/null
+++ b/src/functions/algebras/alghassei
@@ -0,0 +1,16 @@
+Function: alghassei
+Section: algebras
+C-Name: alghassei
+Prototype: G
+Help: alghassei(al): the hasse invariant of the central simple algebra al
+ at infinite places.
+Doc: Given a central simple algebra \var{al} output by \tet{alginit}, returns
+ a \typ{VECSMALL} $h_i$ of $r_1$ integers modulo the degree $d$ of \var{al},
+ where $r_1$ is the number of real places of the center: the local Hasse
+ invariants of \var{al} at infinite places.
+ \bprog
+ ? nf = nfinit(y^2-5);
+ ? A = alginit(nf, [-1,y]);
+ ? alghassei(A)
+ %3 = Vecsmall([1, 0])
+ @eprog
diff --git a/src/functions/algebras/algindex b/src/functions/algebras/algindex
new file mode 100644
index 0000000..98bbc50
--- /dev/null
+++ b/src/functions/algebras/algindex
@@ -0,0 +1,28 @@
+Function: algindex
+Section: algebras
+C-Name: algindex
+Prototype: lGDG
+Help: algindex(al,{pl}): the index of the central simple algebra al. If pl is
+ set, it should be a prime ideal of the center or an integer between 1 and
+ r1+r2, and in that case return the local index at the place pl instead.
+Doc: Return the index of the central simple algebra~$A$ over~$K$ (as output by
+ alginit), that is the degree~$e$ of the unique central division algebra~$D$
+ over $K$ such that~$A$ is isomorphic to some matrix algebra~$M_d(D)$. If
+ \var{pl} is set, it should be a prime ideal of~$K$ or an integer between~$1$
+ and~$r_1+r_2$, and in that case return the local index at the place \var{pl}
+ instead.
+
+ \bprog
+ ? nf = nfinit(y^2-5);
+ ? A = alginit(nf, [-1,y]);
+ ? algindex(A, 1)
+ %3 = 2
+ ? algindex(A, 2)
+ %4 = 1
+ ? algindex(A, idealprimedec(nf,2)[1])
+ %5 = 2
+ ? algindex(A, idealprimedec(nf,5)[1])
+ %6 = 1
+ ? algindex(A)
+ %7 = 2
+ @eprog
diff --git a/src/functions/algebras/alginit b/src/functions/algebras/alginit
new file mode 100644
index 0000000..609fc93
--- /dev/null
+++ b/src/functions/algebras/alginit
@@ -0,0 +1,146 @@
+Function: alginit
+Section: algebras
+C-Name: alginit
+Prototype: GGDnD1,L,
+Help: alginit(B, C, {v}, {flag = 1}): initialize the central simple algebra
+ defined by data B, C. If flag = 1, compute a maximal order.
+Doc: initialize the central simple algebra defined by data $B$, $C$ and
+ variable $v$, as follows.
+
+ \item (multiplication table) $B$ is the base number field $K$ in \tet{nfinit}
+ form, $C$ is a ``multiplication table'' over $K$.
+ As a $K$-vector space, the algebra is generated by a basis
+ $(e_1 = 1,\dots, e_n)$; the table is given as a \typ{VEC} of $n$ matrices in
+ $M_n(K)$, giving the left multiplication by the basis elements $e_i$, in the
+ given basis.
+ Assumes that $e_1= 1$, that the multiplication table is integral, and that
+ $K[e_1,\dots,e_n]$ describes a central simple algebra over $K$; $v$ and $\fl$
+ are ignored.
+ \bprog
+ { m_i = [0,-1,0, 0;
+          1, 0,0, 0;
+          0, 0,0,-1;
+          0, 0,1, 0];
+   m_j = [0, 0,-1,0;
+          0, 0, 0,1;
+          1, 0, 0,0;
+          0,-1, 0,0];
+   m_k = [0, 0, 0, 0;
+          0, 0,-1, 0;
+          0, 1, 0, 0;
+          1, 0, 0,-1];
+   A = alginit(nfinit(y), [matid(4), m_i,m_j,m_k],  0); }
+ @eprog represents (in a complicated way) the quaternion algebra $(-1,-1)_\Q$.
+ See below for a simpler solution.
+
+ \item (cyclic algebra) $B$ is an \var{rnf} structure associated with a cyclic
+ number field extension $L/K$ of degree $d$, $C$ is a \typ{VEC}
+ \kbd{[sigma,b]} with 2 components: \kbd{sigma} is a \typ{POLMOD} representing
+ an automorphism generating $\text{Gal}(L/K)$, $b$ is an element in $K^*$. This
+ represents the cyclic algebra~$(L/K,\sigma,b)$. Currently the element $b$ has
+ to be integral.
+ \bprog
+  ? Q = nfinit(y); T = polcyclo(5, 'x); F = rnfinit(Q, T);
+  ? A = alginit(F, [Mod(x^2,T), 3]);
+ @eprog defines the cyclic algebra $(L/\Q, \sigma, 3)$, where
+ $L = \Q(\zeta_5)$ and $\sigma:\zeta\mapsto\zeta^2$ generates
+ $\text{Gal}(L/\Q)$.
+
+ \item (quaternion algebra, special case of the above) $B$ is an \var{nf}
+ structure associated with a number field $K$, $C = [a,b]$ is a vector
+ containing two elements of $K^*$ with $a$ not a square in $K$, returns the quaternion algebra $(a,b)_K$.
+ The variable $v$ (\kbd{'x} by default) must have higher priority than the
+ variable of $K$\kbd{.pol} and is used to represent elements in the splitting
+ field $L = K[x]/(x^2-a)$.
+ \bprog
+  ? Q = nfinit(y); A = alginit(Q, [-1,-1]);  \\@com $(-1,-1)_\Q$
+ @eprog
+
+ \item (algebra/$K$ defined by local Hasse invariants)
+ $B$ is an \var{nf} structure associated with a number field $K$,
+ $C = [d, [\kbd{PR},h_f], h_i]$ is a triple
+ containing an integer $d > 1$, a pair $[\kbd{PR}, h_f]$ describing the
+ Hasse invariants at finite places, and $h_i$ the Hasse invariants
+ at archimedean (real) places. A local Hasse invariant belongs to $(1/d)\Z/\Z
+ \subset \Q/\Z$, and is given either as a \typ{FRAC} (lift to $(1/d)\Z$),
+ a \typ{INT} or \typ{INTMOD} modulo $d$ (lift to $\Z/d\Z$); a whole vector
+ of local invariants can also be given as a \typ{VECSMALL}, whose
+ entries are handled as \typ{INT}s. \kbd{PR} is a list of prime ideals
+ (\var{prid} structures), and $h_f$ is a vector of the same length giving the
+ local invariants at those maximal ideals. The invariants at infinite real
+ places are indexed by the real roots $K$\kbd{.roots}: if the Archimedean
+ place $v$ is associated with the $j$-th root, the value of
+ $h_v$ is given by $h_i[j]$, must be $0$ or $1/2$ (or~$d/2$ modulo~$d$), and
+ can be nonzero only if~$d$ is even.
+
+ By class field theory, provided the local invariants $h_v$ sum to $0$, up
+ to Brauer equivalence, there is a unique central simple algebra over $K$
+ with given local invariants and trivial invariant elsewhere. In particular,
+ up to isomorphism, there is a unique such algebra $A$ of degree $d$.
+
+ We realize $A$ as a cyclic algebra through class field theory. The variable $v$
+ (\kbd{'x} by default) must have higher priority than the variable of
+ $K$\kbd{.pol} and is used to represent elements in the (cyclic) splitting
+ field extension $L/K$ for $A$.
+
+ \bprog
+  ? nf = nfinit(y^2+1);
+  ? PR = idealprimedec(nf,5); #PR
+  %2 = 2
+  ? hi = [];
+  ? hf = [PR, [1/3,-1/3]];
+  ? A = alginit(nf, [3,hf,hi]);
+  ? algsplittingfield(A).pol
+  %6 = x^3 - 21*x + 7
+ @eprog
+
+ \item (matrix algebra, toy example) $B$ is an \var{nf} structure associated
+ to a number field $K$, $C = d$ is a positive integer. Returns a cyclic
+ algebra isomorphic to the matrix algebra $M_d(K)$.
+
+ In all cases, this function computes a maximal order for the algebra by default,
+ which may require a lot of time. Setting $\fl = 0$ prevents this computation.
+
+ The pari object representing such an algebra $A$ is a \typ{VEC} with the
+ following data:
+
+  \item A splitting field $L$ of $A$ of the same degree over $K$ as $A$, in
+ \kbd{rnfinit} format, accessed with \kbd{algsplittingfield}.
+
+  \item The same splitting field $L$ in \kbd{nfinit} format.
+
+  \item The Hasse invariants at the real places of $K$, accessed with
+ \kbd{alghassei}.
+
+  \item The Hasse invariants of $A$ at the finite primes of $K$ that ramify in
+ the natural order of $A$, accessed with \kbd{alghassef}.
+
+  \item A basis of an order ${\cal O}_0$ expressed on the basis of the natural
+ order, accessed with \kbd{algord}.
+
+  \item A basis of the natural order expressed on the basis of ${\cal O}_0$,
+ accessed with \kbd{alginvord}.
+
+  \item The left multiplication table of ${\cal O}_0$ on the previous basis,
+ accessed with \kbd{algmultable}.
+
+  \item The characteristic of $A$ (always $0$), accessed with \kbd{algchar}.
+
+  \item The absolute traces of the elements of the basis of ${\cal O}_0$.
+
+  \item If $A$ was constructed as a cyclic algebra~$(L/K,\sigma,b)$ of degree
+ $d$, a \typ{VEC} $[\sigma,\sigma^2,\dots,\sigma^{d-1}]$. The function
+ \kbd{algaut} returns $\sigma$.
+
+  \item If $A$ was constructed as a cyclic algebra~$(L/K,\sigma,b)$, the
+ element $b$, accessed with \kbd{algb}.
+
+  \item If $A$ was constructed with its multiplication table $mt$ over $K$,
+ the \typ{VEC} of \typ{MAT} $mt$, accessed with \kbd{algrelmultable}.
+
+  \item If $A$ was constructed with its multiplication table $mt$ over $K$,
+ a \typ{VEC} with three components: a \typ{COL} representing an element of $A$
+ generating the splitting field $L$ as a maximal subfield of $A$, a \typ{MAT}
+ representing an $L$-basis ${\cal B}$ of $A$ expressed on the $\Z$-basis of
+ ${\cal O}_0$, and a \typ{MAT} representing the $\Z$-basis of ${\cal O}_0$
+ expressed on ${\cal B}$. This data is accessed with \kbd{algsplittingdata}.
diff --git a/src/functions/algebras/alginv b/src/functions/algebras/alginv
new file mode 100644
index 0000000..ad508b3
--- /dev/null
+++ b/src/functions/algebras/alginv
@@ -0,0 +1,14 @@
+Function: alginv
+Section: algebras
+C-Name: alginv
+Prototype: GG
+Help: alginv(al,x): element 1/x in al.
+Doc: Given an element $x$ in \var{al}, computes its inverse $x^{-1}$ in the
+ algebra \var{al}. Assumes that $x$ is invertible.
+ \bprog
+ ? A = alginit(nfinit(y), [-1,-1]);
+ ? alginv(A,[1,1,0,0]~)
+ %2 = [1/2, 1/2, 0, 0]~
+ @eprog
+
+ Also accepts matrices with coefficients in \var{al}.
diff --git a/src/functions/algebras/alginvbasis b/src/functions/algebras/alginvbasis
new file mode 100644
index 0000000..3efee8b
--- /dev/null
+++ b/src/functions/algebras/alginvbasis
@@ -0,0 +1,21 @@
+Function: alginvbasis
+Section: algebras
+C-Name: alginvbasis
+Prototype: G
+Help: alginvbasis(al): basis of the natural order of the central simple algebra
+ al in terms of the stored order.
+Doc: Given an central simple algebra \var{al} output by \tet{alginit}, returns
+ a $\Z$-basis of the natural order in \var{al} with respect to the order~${\cal
+ O}_0$ stored in \var{al}.
+ \bprog
+ A = alginit(nfinit(y), [-1,-1]);
+ ? alginvbasis(A)
+ %2 =
+ [1 0 0 -1]
+
+ [0 1 0 -1]
+
+ [0 0 1 -1]
+
+ [0 0 0  2]
+ @eprog
diff --git a/src/functions/algebras/algisassociative b/src/functions/algebras/algisassociative
new file mode 100644
index 0000000..c8f2484
--- /dev/null
+++ b/src/functions/algebras/algisassociative
@@ -0,0 +1,20 @@
+Function: algisassociative
+Section: algebras
+C-Name: algisassociative
+Prototype: iGD0,G,
+Help: algisassociative(mt,p=0): true (1) if the multiplication table mt is
+ suitable for algtableinit(mt,p), false (0) otherwise.
+Doc: Returns 1 if the multiplication table \kbd{mt} is suitable for
+ \kbd{algtableinit(mt,p)}, 0 otherwise. More precisely, \kbd{mt} should be
+ a \typ{VEC} of $n$ matrices in $M_n(K)$, giving the left multiplications
+ by the basis elements $e_1, \dots, e_n$ (structure constants).
+ We check whether the first basis element $e_1$ is $1$ and $e_i(e_je_k) =
+ (e_ie_j)e_k$ for all $i,j,k$.
+ \bprog
+  ? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
+  ? algisassociative(mt)
+  %2 = 1
+ @eprog
+
+ May be used to check a posteriori an algebra: we also allow \kbd{mt} as
+ output by \tet{algtableinit} ($p$ is ignored in this case).
diff --git a/src/functions/algebras/algiscommutative b/src/functions/algebras/algiscommutative
new file mode 100644
index 0000000..58a81e9
--- /dev/null
+++ b/src/functions/algebras/algiscommutative
@@ -0,0 +1,18 @@
+Function: algiscommutative
+Section: algebras
+C-Name: algiscommutative
+Prototype: iG
+Help: algiscommutative(al): test whether the algebra al is commutative.
+Doc: \var{al} being a table algebra output by \tet{algtableinit} or a central
+ simple algebra output by \tet{alginit}, tests whether the algebra \var{al} is
+ commutative.
+ \bprog
+ ? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
+ ? A = algtableinit(mt);
+ ? algiscommutative(A)
+ %3 = 0
+ ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+ ? A = algtableinit(mt,2);
+ ? algiscommutative(A)
+ %6 = 1
+ @eprog
diff --git a/src/functions/algebras/algisdivision b/src/functions/algebras/algisdivision
new file mode 100644
index 0000000..f8391eb
--- /dev/null
+++ b/src/functions/algebras/algisdivision
@@ -0,0 +1,28 @@
+Function: algisdivision
+Section: algebras
+C-Name: algisdivision
+Prototype: iGDG
+Help: algisdivision(al,{pl}): test whether the central simple algebra al is a
+ division algebra. If pl is set, it should be a prime ideal of the center or an
+ integer between 1 and r1+r2, and in that case test whether al is locally a
+ division algebra at the place pl instead.
+Doc: Given a central simple algebra \var{al} output by \tet{alginit}, test
+ whether \var{al} is a division algebra. If \var{pl} is set, it should be a
+ prime ideal of~$K$ or an integer between~$1$ and~$r_1+r_2$, and in that case
+ test whether \var{al} is locally a division algebra at the place \var{pl}
+ instead.
+
+ \bprog
+ ? nf = nfinit(y^2-5);
+ ? A = alginit(nf, [-1,y]);
+ ? algisdivision(A, 1)
+ %3 = 1
+ ? algisdivision(A, 2)
+ %4 = 0
+ ? algisdivision(A, idealprimedec(nf,2)[1])
+ %5 = 1
+ ? algisdivision(A, idealprimedec(nf,5)[1])
+ %6 = 0
+ ? algisdivision(A)
+ %7 = 1
+ @eprog
diff --git a/src/functions/algebras/algisdivl b/src/functions/algebras/algisdivl
new file mode 100644
index 0000000..60b4c54
--- /dev/null
+++ b/src/functions/algebras/algisdivl
@@ -0,0 +1,20 @@
+Function: algisdivl
+Section: algebras
+C-Name: algisdivl
+Prototype: iGGGD&
+Help: algisdivl(al,x,y,{&z}): tests whether y is left divisible by x and sets z
+ to the left quotient x\y.
+Doc: Given two elements $x$ and $y$ in \var{al}, tests whether $y$ is left
+ divisible by $x$, that is whether there exists~$z$ in \var{al} such
+ that~$xz=y$, and sets $z$ to this element if it exists.
+ \bprog
+ ? A = alginit(nfinit(y), [-1,1]);
+ ? algisdivl(A,[x+2,-x-2]~,[x,1]~)
+ %2 = 0
+ ? algisdivl(A,[x+2,-x-2]~,[-x,x]~,&z)
+ %3 = 1
+ ? z
+ %4 = [Mod(-2/5*x - 1/5, x^2 + 1), 0]~
+ @eprog
+
+ Also accepts matrices with coefficients in \var{al}.
diff --git a/src/functions/algebras/algisinv b/src/functions/algebras/algisinv
new file mode 100644
index 0000000..a044844
--- /dev/null
+++ b/src/functions/algebras/algisinv
@@ -0,0 +1,19 @@
+Function: algisinv
+Section: algebras
+C-Name: algisinv
+Prototype: iGGD&
+Help: algisinv(al,x,{&ix}): tests whether x is invertible and sets ix to the
+ inverse of x.
+Doc: Given an element $x$ in \var{al}, tests whether $x$ is invertible, and sets
+ $ix$ to the inverse of $x$.
+ \bprog
+ ? A = alginit(nfinit(y), [-1,1]);
+ ? algisinv(A,[-1,1]~)
+ %2 = 0
+ ? algisinv(A,[1,2]~,&ix)
+ %3 = 1
+ ? ix
+ %4 = [Mod(Mod(-1/3, y), x^2 + 1), Mod(Mod(2/3, y), x^2 + 1)]~
+ @eprog
+
+ Also accepts matrices with coefficients in \var{al}.
diff --git a/src/functions/algebras/algisramified b/src/functions/algebras/algisramified
new file mode 100644
index 0000000..729f5fd
--- /dev/null
+++ b/src/functions/algebras/algisramified
@@ -0,0 +1,28 @@
+Function: algisramified
+Section: algebras
+C-Name: algisramified
+Prototype: iGDG
+Help: algisramified(al,{pl}): test whether the central simple algebra al is
+ ramified, i.e. not isomorphic to a matrix ring over its center. If pl is set,
+ it should be a prime ideal of the center or an integer between 1 and r1+r2, and
+ in that case test whether al is locally ramified at the place pl instead.
+Doc: Given a central simple algebra \var{al} output by \tet{alginit}, test
+ whether \var{al} is ramified, i.e. not isomorphic to a matrix algebra over its
+ center. If \var{pl} is set, it should be a prime ideal of~$K$ or an integer
+ between~$1$ and~$r_1+r_2$, and in that case test whether \var{al} is locally
+ ramified at the place \var{pl} instead.
+
+ \bprog
+ ? nf = nfinit(y^2-5);
+ ? A = alginit(nf, [-1,y]);
+ ? algisramified(A, 1)
+ %3 = 1
+ ? algisramified(A, 2)
+ %4 = 0
+ ? algisramified(A, idealprimedec(nf,2)[1])
+ %5 = 1
+ ? algisramified(A, idealprimedec(nf,5)[1])
+ %6 = 0
+ ? algisramified(A)
+ %7 = 1
+ @eprog
diff --git a/src/functions/algebras/algissemisimple b/src/functions/algebras/algissemisimple
new file mode 100644
index 0000000..0c49c64
--- /dev/null
+++ b/src/functions/algebras/algissemisimple
@@ -0,0 +1,21 @@
+Function: algissemisimple
+Section: algebras
+C-Name: algissemisimple
+Prototype: iG
+Help: algissemisimple(al): test whether the algebra al is semisimple.
+Doc: \var{al} being a table algebra output by \tet{algtableinit} or a central
+ simple algebra output by \tet{alginit}, tests whether the algebra \var{al} is
+ semisimple.
+ \bprog
+ ? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
+ ? A = algtableinit(mt);
+ ? algissemisimple(A)
+ %3 = 0
+ ? m_i=[0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0]; \\quaternion algebra (-1,-1)
+ ? m_j=[0,0,-1,0;0,0,0,1;1,0,0,0;0,-1,0,0];
+ ? m_k=[0,0,0,-1;0,0,-1,0;0,1,0,0;1,0,0,0];
+ ? mt = [matid(4), m_i, m_j, m_k];
+ ? A = algtableinit(mt);
+ ? algissemisimple(A)
+ %9 = 1
+ @eprog
diff --git a/src/functions/algebras/algissimple b/src/functions/algebras/algissimple
new file mode 100644
index 0000000..4faadac
--- /dev/null
+++ b/src/functions/algebras/algissimple
@@ -0,0 +1,28 @@
+Function: algissimple
+Section: algebras
+C-Name: algissimple
+Prototype: iGD0,L,
+Help: algissimple(al, {ss = 0}): test whether the algebra al is simple.
+Doc: \var{al} being a table algebra output by \tet{algtableinit} or a central
+ simple algebra output by \tet{alginit}, tests whether the algebra \var{al} is
+ simple. If $\var{ss}=1$, assumes that the algebra~\var{al} is semisimple
+ without testing it.
+ \bprog
+ ? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
+ ? A = algtableinit(mt); \\ matrices [*,*; 0,*]
+ ? algissimple(A)
+ %3 = 0
+ ? algissimple(A,1) \\ incorrectly assume that A is semisimple
+ %4 = 1
+ ? m_i=[0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0];
+ ? m_j=[0,0,-1,0;0,0,0,1;1,0,0,0;0,-1,0,0];
+ ? m_k=[0,0,0,-1;0,0,b,0;0,1,0,0;1,0,0,0];
+ ? mt = [matid(4), m_i, m_j, m_k];
+ ? A = algtableinit(mt); \\ quaternion algebra (-1,-1)
+ ? algissimple(A)
+ %10 = 1
+ ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+ ? A = algtableinit(mt,2); \\ direct sum F_4+F_2
+ ? algissimple(A)
+ %13 = 0
+ @eprog
diff --git a/src/functions/algebras/algissplit b/src/functions/algebras/algissplit
new file mode 100644
index 0000000..154fa7f
--- /dev/null
+++ b/src/functions/algebras/algissplit
@@ -0,0 +1,28 @@
+Function: algissplit
+Section: algebras
+C-Name: algissplit
+Prototype: iGDG
+Help: algissplit(al,{pl}): test whether the central simple algebra al is
+ split, i.e. isomorphic to a matrix ring over its center. If pl is set, it
+ should be a prime ideal of the center or an integer between 1 and r1+r2, and in
+ that case test whether al is locally split at the place pl instead.
+Doc: Given a central simple algebra \var{al} output by \tet{alginit}, test
+ whether \var{al} is split, i.e. isomorphic to a matrix algebra over its center.
+ If \var{pl} is set, it should be a prime ideal of~$K$ or an integer between~$1$
+ and~$r_1+r_2$, and in that case test whether \var{al} is locally split at the
+ place \var{pl} instead.
+
+ \bprog
+ ? nf = nfinit(y^2-5);
+ ? A = alginit(nf, [-1,y]);
+ ? algissplit(A, 1)
+ %3 = 0
+ ? algissplit(A, 2)
+ %4 = 1
+ ? algissplit(A, idealprimedec(nf,2)[1])
+ %5 = 0
+ ? algissplit(A, idealprimedec(nf,5)[1])
+ %6 = 1
+ ? algissplit(A)
+ %7 = 0
+ @eprog
diff --git a/src/functions/algebras/algmul b/src/functions/algebras/algmul
new file mode 100644
index 0000000..74fa67b
--- /dev/null
+++ b/src/functions/algebras/algmul
@@ -0,0 +1,14 @@
+Function: algmul
+Section: algebras
+C-Name: algmul
+Prototype: GGG
+Help: algmul(al,x,y): element x*y in al.
+Doc: Given two elements $x$ and $y$ in \var{al}, computes their product $x*y$
+ in the algebra~\var{al}.
+ \bprog
+ ? A = alginit(nfinit(y), [-1,-1]);
+ ? algmul(A,[1,1,0,0]~,[0,0,2,1]~)
+ %2 = [2, 3, 5, -4]~
+ @eprog
+
+ Also accepts matrices with coefficients in \var{al}.
diff --git a/src/functions/algebras/algmultable b/src/functions/algebras/algmultable
new file mode 100644
index 0000000..67d85e0
--- /dev/null
+++ b/src/functions/algebras/algmultable
@@ -0,0 +1,59 @@
+Function: algmultable
+Section: algebras
+C-Name: gp_algmultable
+Prototype: GDG
+Help: algmultable(al,x): left multiplication table of x.
+Doc: Given an element \var{x} in \var{al}, computes its left multiplication
+ table. If \var{x} is given in basis form, returns its multiplication table on
+ the integral basis; if \var{x} is given in algebraic form, returns its
+ multiplication table on the basis corresponding to the algebraic form of
+ elements of \var{al}. In every case, if \var{x} is a \typ{COL} of length $n$,
+ then the output is a $n\times n$ \typ{MAT}.
+ Also accepts a square matrix with coefficients in \var{al}.
+
+ If \var{x} is not set, returns a multiplication table of \var{al} over its
+ prime subfield ($\Q$ or $\F_p$), as a \typ{VEC} of \typ{MAT}: the left
+ multiplication tables of basis elements. If \var{al} was output by
+ \tet{algtableinit}, returns the multiplication table used to define \var{al}.
+ If \var{al} was output by \tet{alginit}, returns the multiplication table of
+ the order~${\cal O}_0$ stored in \var{al}.
+ \bprog
+ ? A = alginit(nfinit(y), [-1,-1]);
+ ? algmultable(A,[0,1,0,0]~)
+ %2 =
+ [0 -1  1  0]
+
+ [1  0  1  1]
+
+ [0  0  1  1]
+
+ [0  0 -2 -1]
+ @eprog
+
+ Another example:
+
+ \bprog
+ ? A = alginit(nfinit(y), [-1,-1]);
+ ? M = algmultable(A);
+ ? #M
+ %3 = 4
+ ? M[1]
+ %4 =
+ [1 0 0 0]
+
+ [0 1 0 0]
+
+ [0 0 1 0]
+
+ [0 0 0 1]
+
+ ? M[2]
+ %5 =
+ [0 -1  1  0]
+
+ [1  0  1  1]
+
+ [0  0  1  1]
+
+ [0  0 -2 -1]
+ @eprog
diff --git a/src/functions/algebras/algneg b/src/functions/algebras/algneg
new file mode 100644
index 0000000..d90bd6c
--- /dev/null
+++ b/src/functions/algebras/algneg
@@ -0,0 +1,14 @@
+Function: algneg
+Section: algebras
+C-Name: algneg
+Prototype: GG
+Help: algneg(al,x): element -x in al.
+Doc: Given an element $x$ in \var{al}, computes its opposite $-x$ in the
+ algebra \var{al}.
+ \bprog
+ ? A = alginit(nfinit(y), [-1,-1]);
+ ? algneg(A,[1,1,0,0]~)
+ %2 = [-1, -1, 0, 0]~
+ @eprog
+
+ Also accepts matrices with coefficients in \var{al}.
diff --git a/src/functions/algebras/algnorm b/src/functions/algebras/algnorm
new file mode 100644
index 0000000..9982b07
--- /dev/null
+++ b/src/functions/algebras/algnorm
@@ -0,0 +1,18 @@
+Function: algnorm
+Section: algebras
+C-Name: algnorm
+Prototype: GG
+Help: algnorm(al,x): (reduced) norm of x.
+Doc: Given an element \var{x} in \var{al}, computes its norm. If \var{al} is
+ a table algebra output by \tet{algtableinit}, returns the absolute norm of
+ \var{x}, which is an element of $\F_p$ of~$\Q$; if \var{al} is a central
+ simple algebra output by \tet{alginit}, returns the reduced norm of \var{x},
+ which is an element of the center of \var{al}.
+ \bprog
+ ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+ ? A = algtableinit(mt,19);
+ ? algnorm(A,[0,-2,3]~)
+ %3 = 18
+ @eprog
+
+ Also accepts a square matrix with coefficients in \var{al}.
diff --git a/src/functions/algebras/algpoleval b/src/functions/algebras/algpoleval
new file mode 100644
index 0000000..3755e72
--- /dev/null
+++ b/src/functions/algebras/algpoleval
@@ -0,0 +1,7 @@
+Function: algpoleval
+Section: algebras
+C-Name: algpoleval
+Prototype: GGG
+Help: algpoleval(al,T,b): T in K[X] evaluate T(b) in al.
+Doc: Given an element $b$ in \var{al} and a polynomial $T$ in $K[X]$,
+ computes $T(b)$ in \var{al}.
diff --git a/src/functions/algebras/algpow b/src/functions/algebras/algpow
new file mode 100644
index 0000000..c1ea475
--- /dev/null
+++ b/src/functions/algebras/algpow
@@ -0,0 +1,14 @@
+Function: algpow
+Section: algebras
+C-Name: algpow
+Prototype: GGG
+Help: algpow(al,x,n): element x^n in al.
+Doc: Given an element $x$ in \var{al} and an integer $n$, computes the
+ power $x^n$ in the algebra \var{al}.
+ \bprog
+ ? A = alginit(nfinit(y), [-1,-1]);
+ ? algpow(A,[1,1,0,0]~,7)
+ %2 = [8, -8, 0, 0]~
+ @eprog
+
+ Also accepts a square matrix with coefficients in \var{al}.
diff --git a/src/functions/algebras/algprimesubalg b/src/functions/algebras/algprimesubalg
new file mode 100644
index 0000000..7e24377
--- /dev/null
+++ b/src/functions/algebras/algprimesubalg
@@ -0,0 +1,22 @@
+Function: algprimesubalg
+Section: algebras
+C-Name: algprimesubalg
+Prototype: G
+Help: algprimesubalg(al): prime subalgebra of the positive characteristic,
+ semisimple algebra al.
+Doc: \var{al} being the output of \tet{algtableinit} representing a semisimple
+ algebra of positive characteristic, returns a basis of the prime subalgebra
+ of~\var{al}. The prime subalgebra of~\var{al} is the subalgebra fixed by the
+ Frobenius automorphism of the center of \var{al}. It is abstractly isomorphic
+ to a product of copies of $\F_p$.
+ \bprog
+ ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+ ? A = algtableinit(mt,2);
+ ? algprimesubalg(A)
+ %3 =
+ [1 0]
+
+ [0 1]
+
+ [0 0]
+ @eprog
diff --git a/src/functions/algebras/algquotient b/src/functions/algebras/algquotient
new file mode 100644
index 0000000..4aa40ae
--- /dev/null
+++ b/src/functions/algebras/algquotient
@@ -0,0 +1,19 @@
+Function: algquotient
+Section: algebras
+C-Name: alg_quotient
+Prototype: GGD0,L,
+Help: algquotient(al,I,{flag=0}): quotient of the algebra al by the two-sided
+ ideal I.
+Doc: \var{al} being a table algebra output by \tet{algtableinit} and \var{I}
+ being a basis of a two-sided ideal of \var{al} represented by a matrix,
+ returns the quotient $\var{al}/\var{I}$. When $\var{flag}=1$, returns a
+ \typ{VEC} $[\var{al}/\var{I},\var{proj},\var{lift}]$ where \var{proj} and
+ \var{lift} are matrices respectively representing the projection map and a
+ section of it.
+ \bprog
+ ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+ ? A = algtableinit(mt,2);
+ ? AQ = algquotient(A,[0;1;0]);
+ ? algdim(AQ)
+ %4 = 2
+ @eprog
diff --git a/src/functions/algebras/algradical b/src/functions/algebras/algradical
new file mode 100644
index 0000000..a44e7d1
--- /dev/null
+++ b/src/functions/algebras/algradical
@@ -0,0 +1,34 @@
+Function: algradical
+Section: algebras
+C-Name: algradical
+Prototype: G
+Help: algradical(al): Jacobson radical of the algebra al.
+Doc: \var{al} being a table algebra output by \tet{algtableinit}, returns a
+ basis of the Jacobson radical of the algebra \var{al} over its prime field
+ ($\Q$ or $\F_p$).
+
+ Here is an example with $A = \Q[x]/(x^2)$, generated by $(1,x)$:
+ \bprog
+ ? mt = [matid(2),[0,0;1,0]];
+ ? A = algtableinit(mt);
+ ? algradical(A) \\ = (x)
+ %3 =
+ [0]
+
+ [1]
+ @eprog
+
+ Another one with $2\times 2$ upper triangular matrices over $\Q$, generated
+ by $I_2$, $a = \kbd{[0,1;0,0]}$ and $b = \kbd{[0,0;0,1]}$, such that $a^2 =
+ 0$, $ab = a$, $ba = 0$, $b^2 = b$:
+ \bprog
+ ? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
+ ? A = algtableinit(mt);
+ ? algradical(A) \\ = (a)
+ %6 =
+ [0]
+
+ [1]
+
+ [0]
+ @eprog
diff --git a/src/functions/algebras/algramifiedplaces b/src/functions/algebras/algramifiedplaces
new file mode 100644
index 0000000..6c8bb30
--- /dev/null
+++ b/src/functions/algebras/algramifiedplaces
@@ -0,0 +1,18 @@
+Function: algramifiedplaces
+Section: algebras
+C-Name: algramifiedplaces
+Prototype: G
+Help: algramifiedplaces(al): vector of the places of the center of al that
+ ramify in al. Each place is described as an integer between 1 and r1 or as a
+ prime ideal.
+Doc: Given a central simple algebra \var{al} output by \tet{alginit}, return a
+ \typ{VEC} containing the list of places of the center of \var{al} that are
+ ramified in \var{al}. Each place is described as an integer between~$1$
+ and~$r_1$ or as a prime ideal.
+
+ \bprog
+ ? nf = nfinit(y^2-5);
+ ? A = alginit(nf, [-1,y]);
+ ? algramifiedplaces(A)
+ %3 = [1, [2, [2, 0]~, 1, 2, 1]]
+ @eprog
diff --git a/src/functions/algebras/algrandom b/src/functions/algebras/algrandom
new file mode 100644
index 0000000..250dc7c
--- /dev/null
+++ b/src/functions/algebras/algrandom
@@ -0,0 +1,7 @@
+Function: algrandom
+Section: algebras
+C-Name: algrandom
+Prototype: GG
+Help: algrandom(al,b): random element in al with coefficients in [-b,b].
+Doc: Given an algebra \var{al} and an integer \var{b}, returns a random
+ element in \var{al} with coefficients in~$[-b,b]$.
diff --git a/src/functions/algebras/algrelmultable b/src/functions/algebras/algrelmultable
new file mode 100644
index 0000000..e0b564f
--- /dev/null
+++ b/src/functions/algebras/algrelmultable
@@ -0,0 +1,31 @@
+Function: algrelmultable
+Section: algebras
+C-Name: algrelmultable
+Prototype: G
+Help: algrelmultable(al): multiplication table of the central simple
+ algebra al over its center.
+Doc: Given a central simple algebra \var{al} output by \tet{alginit} defined by a multiplication table over its center (a number field), returns this multiplication table.
+ \bprog
+ ? nf = nfinit(y^3-5); a = y; b = y^2;
+ ? {m_i = [0,a,0,0;
+           1,0,0,0;
+           0,0,0,a;
+           0,0,1,0];}
+ ? {m_j = [0, 0,b, 0;
+           0, 0,0,-b;
+           1, 0,0, 0;
+           0,-1,0, 0];}
+ ? {m_k = [0, 0,0,-a*b;
+           0, 0,b,   0;
+           0,-a,0,   0;
+           1, 0,0,   0];}
+ ? mt = [matid(4), m_i, m_j, m_k];
+ ? A = alginit(nf,mt,'x);
+ ? M = algrelmultable(A);
+ ? M[2] == m_i
+ %8 = 1
+ ? M[3] == m_j
+ %9 = 1
+ ? M[4] == m_k
+ %10 = 1
+ @eprog
diff --git a/src/functions/algebras/algsimpledec b/src/functions/algebras/algsimpledec
new file mode 100644
index 0000000..af875db
--- /dev/null
+++ b/src/functions/algebras/algsimpledec
@@ -0,0 +1,15 @@
+Function: algsimpledec
+Section: algebras
+C-Name: algsimpledec
+Prototype: GD0,L,
+Help: algsimpledec(al,{flag=0}): decomposition into simple algebras of the
+ semisimple algebra al.
+Doc: \var{al} being the output of \tet{algtableinit} representing a semisimple
+ algebra, returns a \typ{VEC} $[\var{al}_1,\var{al}_2,\dots,\var{al}_n]$ such
+ that~\var{al} is isomorphic to the direct sum of the simple algebras
+ $\var{al}_i$. When $\var{flag}=1$, each component is instead a \typ{VEC}
+ $[\var{al}_i,\var{proj}_i,\var{lift}_i]$ where $\var{proj}_i$
+ and~$\var{lift}_i$ are matrices respectively representing the projection map
+ on the $i$-th factor and a section of it.
+
+ \misctitle{Warning} The images of the $\var{lift}_i$ are not guaranteed to form a direct sum.
diff --git a/src/functions/algebras/algsplittingdata b/src/functions/algebras/algsplittingdata
new file mode 100644
index 0000000..e061fcd
--- /dev/null
+++ b/src/functions/algebras/algsplittingdata
@@ -0,0 +1,45 @@
+Function: algsplittingdata
+Section: algebras
+C-Name: algsplittingdata
+Prototype: G
+Help: algsplittingdata(al): data stored in the central simple algebra al to
+ compute a splitting of al over an extension.
+Doc: Given a central simple algebra \var{al} output by \tet{alginit} defined
+ by a multiplication table over its center~$K$ (a number field), returns data
+ stored to compute a splitting of \var{al} over an extension. This data is a
+ \typ{VEC} \kbd{[t,Lbas,Lbasinv]} with $3$ components:
+
+  \item an element $t$ of \var{al} such that $L=K(t)$ is a maximal subfield
+ of \var{al};
+
+  \item a matrix \kbd{Lbas} expressing a $L$-basis of \var{al} (given an
+ $L$-vector space structure by multiplication on the right) on the integral
+ basis of \var{al};
+
+  \item a matrix \kbd{Lbasinv} expressing the integral basis of \var{al} on
+ the previous $L$-basis.
+
+ \bprog
+ ? nf = nfinit(y^3-5); a = y; b = y^2;
+ ? {m_i = [0,a,0,0;
+           1,0,0,0;
+           0,0,0,a;
+           0,0,1,0];}
+ ? {m_j = [0, 0,b, 0;
+           0, 0,0,-b;
+           1, 0,0, 0;
+           0,-1,0, 0];}
+ ? {m_k = [0, 0,0,-a*b;
+           0, 0,b,   0;
+           0,-a,0,   0;
+           1, 0,0,   0];}
+ ? mt = [matid(4), m_i, m_j, m_k];
+ ? A = alginit(nf,mt,'x);
+ ? [t,Lb,Lbi] = algsplittingdata(A);
+ ? t
+ %8 = [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]~;
+ ? matsize(Lb)
+ %9 = [12, 2]
+ ? matsize(Lbi)
+ %10 = [2, 12]
+ @eprog
diff --git a/src/functions/algebras/algsplittingfield b/src/functions/algebras/algsplittingfield
new file mode 100644
index 0000000..839e924
--- /dev/null
+++ b/src/functions/algebras/algsplittingfield
@@ -0,0 +1,29 @@
+Function: algsplittingfield
+Section: algebras
+C-Name: algsplittingfield
+Prototype: G
+Help: algsplittingfield(al): the stored splitting field of the central simple
+ algebra al.
+Doc: Given a central simple algebra \var{al} output by \tet{alginit}, returns
+ an \var{rnf} structure: the splitting field of \var{al} that is stored in
+ \var{al}, as a relative extension of the center.
+ \bprog
+ nf = nfinit(y^3-5);
+ a = y; b = y^2;
+ {m_i = [0,a,0,0;
+        1,0,0,0;
+        0,0,0,a;
+        0,0,1,0];}
+ {m_j = [0, 0,b, 0;
+        0, 0,0,-b;
+        1, 0,0, 0;
+        0,-1,0, 0];}
+ {m_k = [0, 0,0,-a*b;
+        0, 0,b,   0;
+        0,-a,0,   0;
+        1, 0,0,   0];}
+ mt = [matid(4), m_i, m_j, m_k];
+ A = alginit(nf,mt,'x);
+ algsplittingfield(A).pol
+ %8 = x^2 - y
+ @eprog
diff --git a/src/functions/algebras/algsplittingmatrix b/src/functions/algebras/algsplittingmatrix
new file mode 100644
index 0000000..5bb97ce
--- /dev/null
+++ b/src/functions/algebras/algsplittingmatrix
@@ -0,0 +1,19 @@
+Function: algsplittingmatrix
+Section: algebras
+C-Name: algsplittingmatrix
+Prototype: GG
+Help: algsplittingmatrix(al,x): image of x under a splitting of al.
+Doc: A central simple algebra \var{al} output by \tet{alginit} contains data
+ describing an isomorphism~$\phi : A\otimes_K L \to M_d(L)$, where $d$ is the
+ degree of the algebra and $L$ is an extension of $L$ with~$[L:K]=d$. Returns
+ the matrix $\phi(x)$.
+ \bprog
+ ? A = alginit(nfinit(y), [-1,-1]);
+ ? algsplittingmatrix(A,[0,0,0,2]~)
+ %2 =
+ [Mod(x + 1, x^2 + 1) Mod(Mod(1, y)*x + Mod(-1, y), x^2 + 1)]
+
+ [Mod(x + 1, x^2 + 1)                   Mod(-x + 1, x^2 + 1)]
+ @eprog
+
+ Also accepts matrices with coefficients in \var{al}.
diff --git a/src/functions/algebras/algsqr b/src/functions/algebras/algsqr
new file mode 100644
index 0000000..5c40e0b
--- /dev/null
+++ b/src/functions/algebras/algsqr
@@ -0,0 +1,14 @@
+Function: algsqr
+Section: algebras
+C-Name: algsqr
+Prototype: GG
+Help: algsqr(al,x): element x^2 in al.
+Doc: Given an element $x$ in \var{al}, computes its square $x^2$ in the
+ algebra \var{al}.
+ \bprog
+ ? A = alginit(nfinit(y), [-1,-1]);
+ ? algsqr(A,[1,0,2,0]~)
+ %2 = [-3, 0, 4, 0]~
+ @eprog
+
+ Also accepts a square matrix with coefficients in \var{al}.
diff --git a/src/functions/algebras/algsub b/src/functions/algebras/algsub
new file mode 100644
index 0000000..9abb38e
--- /dev/null
+++ b/src/functions/algebras/algsub
@@ -0,0 +1,14 @@
+Function: algsub
+Section: algebras
+C-Name: algsub
+Prototype: GGG
+Help: algsub(al,x,y): element x-y in al.
+Doc: Given two elements $x$ and $y$ in \var{al}, computes their difference
+ $x-y$ in the algebra \var{al}.
+ \bprog
+ ? A = alginit(nfinit(y), [-1,-1]);
+ ? algsub(A,[1,1,0,0]~,[1,0,1,0]~)
+ %2 = [0, 1, -1, 0]~
+ @eprog
+
+ Also accepts matrices with coefficients in \var{al}.
diff --git a/src/functions/algebras/algsubalg b/src/functions/algebras/algsubalg
new file mode 100644
index 0000000..2ce6adb
--- /dev/null
+++ b/src/functions/algebras/algsubalg
@@ -0,0 +1,17 @@
+Function: algsubalg
+Section: algebras
+C-Name: algsubalg
+Prototype: GG
+Help: algsubalg(al,B): subalgebra of al with basis B.
+Doc: \var{al} being a table algebra output by \tet{algtableinit} and \var{B}
+ being a basis of a subalgebra of \var{al} represented by a matrix, returns an
+ algebra isomorphic to \var{B}.
+ \bprog
+ ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+ ? A = algtableinit(mt,2);
+ ? B = algsubalg(A,[1,0; 0,0; 0,1]);
+ ? algdim(A)
+ %4 = 3
+ ? algdim(B)
+ %5 = 2
+ @eprog
diff --git a/src/functions/algebras/algtableinit b/src/functions/algebras/algtableinit
new file mode 100644
index 0000000..78d2836
--- /dev/null
+++ b/src/functions/algebras/algtableinit
@@ -0,0 +1,52 @@
+Function: algtableinit
+Section: algebras
+C-Name: algtableinit
+Prototype: GDG
+Help: algtableinit(mt, {p}): initialize the associative algebra
+ over Q (resp. Fp) defined by the multiplication table mt.
+Doc: initialize the associative algebra over $K = \Q$ (p omitted) or $\F_p$
+ defined by the multiplication table \var{mt}.
+ As a $K$-vector space, the algebra is generated by a basis
+ $(e_1 = 1, e_2, \dots, e_n)$; the table is given as a \typ{VEC} of $n$ matrices in
+ $M_n(K)$, giving the left multiplication by the basis elements $e_i$, in the
+ given basis.
+ Assumes that $e_1=1$, that $K e_1\oplus \dots\oplus K e_n]$ describes an
+ associative algebra over $K$, and in the case $K=\Q$ that the multiplication
+ table is integral. If the algebra is already known to be central
+ and simple, then the case $K = \F_p$ is useless, and one should use
+ \tet{alginit} directly.
+
+ The point of this function is to input a finite dimensional $K$-algebra, so
+ as to later compute its radical, then to split the quotient algebra as a
+ product of simple algebras over $K$.
+
+ The pari object representing such an algebra $A$ is a \typ{VEC} with the
+ following data:
+
+  \item The characteristic of $A$, accessed with \kbd{algchar}.
+
+  \item The multiplication table of $A$, accessed with \kbd{algmultable}.
+
+  \item The traces of the elements of the basis.
+
+ A simple example: the $2\times 2$ upper triangular matrices over $\Q$,
+ generated by $I_2$, $a = \kbd{[0,1;0,0]}$ and $b = \kbd{[0,0;0,1]}$,
+ such that $a^2 = 0$, $ab = a$, $ba = 0$, $b^2 = b$:
+ \bprog
+ ? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
+ ? A = algtableinit(mt);
+ ? algradical(A) \\ = (a)
+ %6 =
+ [0]
+
+ [1]
+
+ [0]
+ ? algcenter(A) \\ = (I_2)
+ %7 =
+ [1]
+
+ [0]
+
+ [0]
+ @eprog
diff --git a/src/functions/algebras/algtensor b/src/functions/algebras/algtensor
new file mode 100644
index 0000000..e58b314
--- /dev/null
+++ b/src/functions/algebras/algtensor
@@ -0,0 +1,13 @@
+Function: algtensor
+Section: algebras
+C-Name: algtensor
+Prototype: GGD1,L,
+Help: algtensor(al1,al2,{maxord=1}): tensor product of al1 and al2.
+Doc: Given two algebras \var{al1} and \var{al2}, computes their tensor
+ product. For table algebras output by \tet{algtableinit}, the flag
+ \var{maxord} is ignored. For central simple algebras output by \tet{alginit},
+ computes a maximal order by default. Prevent this computation by setting
+ $\var{maxord}=0$.
+
+ Currently only implemented for cyclic algebras of coprime degree over the same
+ center~$K$, and the tensor product is over~$K$.
diff --git a/src/functions/algebras/algtrace b/src/functions/algebras/algtrace
new file mode 100644
index 0000000..09820e2
--- /dev/null
+++ b/src/functions/algebras/algtrace
@@ -0,0 +1,17 @@
+Function: algtrace
+Section: algebras
+C-Name: algtrace
+Prototype: GG
+Help: algtrace(al,x): (reduced) trace of x.
+Doc: Given an element \var{x} in \var{al}, computes its trace. If \var{al} is
+ a table algebra output by \tet{algtableinit}, returns the absolute trace of
+ \var{x}, which is an element of $\F_p$ or~$\Q$; if \var{al} is the output of
+ \tet{alginit}, returns the reduced trace of \var{x}, which is an element of
+ the center of \var{al}.
+ \bprog
+ ? A = alginit(nfinit(y), [-1,-1]);
+ ? algtrace(A,[5,0,0,1]~)
+ %2 = 11
+ @eprog
+
+ Also accepts a square matrix with coefficients in \var{al}.
diff --git a/src/functions/algebras/algtype b/src/functions/algebras/algtype
new file mode 100644
index 0000000..ad99826
--- /dev/null
+++ b/src/functions/algebras/algtype
@@ -0,0 +1,45 @@
+Function: algtype
+Section: algebras
+C-Name: algtype
+Prototype: lG
+Help: algtype(al): type of the algebra al.
+Doc: Given an algebra \var{al} output by \tet{alginit} or by \tet{algtableinit}, returns an integer indicating the type of algebra:
+
+ \item $0$: not a valid algebra.
+
+ \item $1$: table algebra output by \tet{algtableinit}.
+
+ \item $2$: central simple algebra output by \tet{alginit} and represented by
+ a multiplication table over its center.
+
+ \item $3$: central simple algebra output by \tet{alginit} and represented by
+ a cyclic algebra.
+ \bprog
+ ? algtype([])
+ %1 = 0
+ ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+ ? A = algtableinit(mt,2);
+ ? algtype(A)
+ %4 = 1
+ ? nf = nfinit(y^3-5);
+ ?  a = y; b = y^2;
+ ?  {m_i = [0,a,0,0;
+            1,0,0,0;
+            0,0,0,a;
+            0,0,1,0];}
+ ?  {m_j = [0, 0,b, 0;
+            0, 0,0,-b;
+            1, 0,0, 0;
+            0,-1,0, 0];}
+ ?  {m_k = [0, 0,0,-a*b;
+            0, 0,b,   0;
+            0,-a,0,   0;
+            1, 0,0,   0];}
+ ?  mt = [matid(4), m_i, m_j, m_k];
+ ?  A = alginit(nf,mt,'x);
+ ? algtype(A)
+ %12 = 2
+ ? A = alginit(nfinit(y), [-1,-1]);
+ ? algtype(A)
+ %14 = 3
+ @eprog
diff --git a/src/functions/conversions/Ser b/src/functions/conversions/Ser
index 1e43e68..1ec46db 100644
--- a/src/functions/conversions/Ser
+++ b/src/functions/conversions/Ser
@@ -6,7 +6,7 @@ Help: Ser(s,{v='x},{d=seriesprecision}): convert s into a power series with
  variable v and precision d, starting with the constant coefficient.
 Doc: transforms the object $s$ into a power series with main variable $v$
  ($x$ by default) and precision (number of significant terms) equal to
- $d$ (= the default \kbd{seriesprecision} by default). If $s$ is a
+ $d \geq 0$ ($d = \kbd{seriesprecision}$ by default). If $s$ is a
  scalar, this gives a constant power series in $v$ with precision \kbd{d}.
  If $s$ is a polynomial, the polynomial is truncated to $d$ terms if needed
  \bprog
diff --git a/src/functions/conversions/digits b/src/functions/conversions/digits
index 1cca009..d4e05a1 100644
--- a/src/functions/conversions/digits
+++ b/src/functions/conversions/digits
@@ -6,3 +6,4 @@ Help: digits(x,{b=10}): gives the vector formed by the digits of x in base b (x
  integers).
 Doc:
  outputs the vector of the digits of $|x|$ in base $b$, where $x$ and $b$ are integers.
+ See \kbd{fromdigits} for the reverse operation.
diff --git a/src/functions/conversions/fromdigits b/src/functions/conversions/fromdigits
new file mode 100644
index 0000000..90dfa76
--- /dev/null
+++ b/src/functions/conversions/fromdigits
@@ -0,0 +1,14 @@
+Function: fromdigits
+Section: conversions
+C-Name: fromdigits
+Prototype: GDG
+Help: fromdigits(x,{b=10}): gives the integer formed by the elements of x seen
+ as the digits of a number in base b.
+Doc: gives the integer formed by the elements of $x$ seen as the digits of a
+ number in base $b$.  This is the reverse of \kbd{digits}:
+ \bprog
+ ? digits(1234,5)
+ %1 = [1,4,4,1,4]
+ ? fromdigits([1,4,4,1,4],5)
+ %2 = 1234
+ @eprog
diff --git a/src/functions/conversions/oo b/src/functions/conversions/oo
new file mode 100644
index 0000000..cacf9ad
--- /dev/null
+++ b/src/functions/conversions/oo
@@ -0,0 +1,11 @@
+Function: oo
+Section: conversions
+C-Name: mkoo
+Prototype:
+Help: oo: infinity.
+Description:
+Doc: returns an object meaning $+\infty$, for use in functions such as
+ \kbd{intnum}. It can be negated (\kbd{-oo} represents $-\infty$), and
+ compared to real numbers (\typ{INT}, \typ{FRAC}, \typ{REAL}), with the
+ expected meaning: $+\infty$ is greater than any real number and $-\infty$ is
+ smaller.
diff --git a/src/functions/conversions/precision b/src/functions/conversions/precision
index 5d657ec..7b31a4a 100644
--- a/src/functions/conversions/precision
+++ b/src/functions/conversions/precision
@@ -11,6 +11,7 @@ Description:
  (real,#small):real    rtor($1, ndec2prec($2))
  (gen,#small):gen      gprec($1, $2)
  (real,small):real     precision0($1, $2)
+ (mp,small):mp         precision0($1, $2)
  (gen,small):gen       precision0($1, $2)
 
 Doc: the function has two different behaviors according to whether $n$ is present or not.
diff --git a/src/functions/conversions/random b/src/functions/conversions/random
index b805707..bcb671b 100644
--- a/src/functions/conversions/random
+++ b/src/functions/conversions/random
@@ -67,7 +67,7 @@ Doc:
  by means of linear congruences, which were not well distributed in arithmetic
  progressions. We now
  use Brent's XORGEN algorithm, based on Feedback Shift Registers, see
- \kbd{http://wwwmaths.anu.edu.au/\til{}brent/random.html}. The generator has period
+ \url{http://wwwmaths.anu.edu.au/~brent/random.html}. The generator has period
  $2^{4096}-1$, passes the Crush battery of statistical tests of L'Ecuyer and
  Simard, but is not suitable for cryptographic purposes: one can reconstruct
  the state vector from a small sample of consecutive values, thus predicting
diff --git a/src/functions/conversions/sizedigit b/src/functions/conversions/sizedigit
index 4d2dbca..9236219 100644
--- a/src/functions/conversions/sizedigit
+++ b/src/functions/conversions/sizedigit
@@ -2,9 +2,17 @@ Function: sizedigit
 Section: conversions
 C-Name: sizedigit
 Prototype: lG
-Help: sizedigit(x): maximum number of decimal digits minus one of (the
- coefficients of) x.
+Help: sizedigit(x): rough upper bound for the number of decimal digits
+ of (the components of) $x$. DEPRECATED.
 Doc:
- outputs a quick bound for the number of decimal
- digits of (the components of) $x$, off by at most $1$. If you want the
- exact value, you can use \kbd{\#Str(x)}, which is slower.
+ outputs a quick upper bound for the number of decimal digits of (the
+ components of) $x$, off by at most $1$. More precisely, for a positive
+ integer $x$, it computes (approximately) the ceiling of
+ $$\kbd{floor}(1 + \log_2 x) \log_{10}2,$$
+
+ This function is DEPRECATED, essentially meaningless, and provided for
+ backwards compatibility only. Don't use it!
+
+ To count the number of decimal digits of a positive integer $x$, use
+ \kbd{\#digits(x)}. To estimate (recursively) the size of $x$, use
+ \kbd{normlp(x)}.
diff --git a/src/functions/conversions/valuation b/src/functions/conversions/valuation
index 313dd89..88df7ed 100644
--- a/src/functions/conversions/valuation
+++ b/src/functions/conversions/valuation
@@ -1,7 +1,7 @@
 Function: valuation
 Section: conversions
-C-Name: gvaluation
-Prototype: lGG
+C-Name: gpvaluation
+Prototype: GG
 Help: valuation(x,p): valuation of x with respect to p.
 Doc:
  computes the highest
@@ -15,7 +15,10 @@ Doc:
  valuation of a vector, complex or quadratic number is the minimum of the
  component valuations.
 
- If $x=0$, the result is \tet{LONG_MAX} ($2^{31}-1$ for 32-bit machines or
- $2^{63}-1$ for 64-bit machines) if $x$ is an exact object. If $x$ is a
+ If $x=0$, the result is \kbd{+oo} if $x$ is an exact object. If $x$ is a
  $p$-adic numbers or power series, the result is the exponent of the zero.
  Any other type combinations gives an error.
+
+Variant: Also available is
+ \fun{long}{gvaluation}{GEN x, GEN p}, which returns \tet{LONG_MAX} if $x = 0$
+ and the valuation as a \kbd{long} integer.
diff --git a/src/functions/conversions/varhigher b/src/functions/conversions/varhigher
new file mode 100644
index 0000000..46edc2b
--- /dev/null
+++ b/src/functions/conversions/varhigher
@@ -0,0 +1,63 @@
+Function: varhigher
+Section: conversions
+C-Name: varhigher
+Prototype: sDn
+Help: varhigher(name,{v}): return a variable 'name' whose priority is
+ higher than the priority of v (of all existing variables if v is omitted).
+Doc: return a variable \emph{name} whose priority is higher
+ than the priority of $v$ (of all existing variables if $v$ is omitted).
+ This is a counterpart to \tet{varlower}.
+ \bprog
+ ? Pol([x,x], t)
+  ***   at top-level: Pol([x,x],t)
+  ***                 ^------------
+  *** Pol: incorrect priority in gtopoly: variable x <= t
+ ? t = varhigher("t", x);
+ ? Pol([x,x], t)
+ %3 = x*t + x
+ @eprog\noindent This routine is useful since new GP variables directly
+ created by the interpreter always have lower priority than existing
+ GP variables. When some basic objects already exist in a variable
+ that is incompatible with some function requirement, you can now
+ create a new variable with a suitable priority instead of changing variables
+ in existing objects:
+ \bprog
+ ? K = nfinit(x^2+1);
+ ? rnfequation(K,y^2-2)
+  ***   at top-level: rnfequation(K,y^2-2)
+  ***                 ^--------------------
+  *** rnfequation: incorrect priority in rnfequation: variable y >= x
+ ? y = varhigher("y", x);
+ ? rnfequation(K, y^2-2)
+ %3 = y^4 - 2*y^2 + 9
+ @eprog\noindent
+ \misctitle{Caution 1}
+ The \emph{name} is an arbitrary character string, only used for display
+ purposes and need not be related to the GP variable holding the result, nor
+ to be a valid variable name. In particular the \emph{name} can
+ not be used to retrieve the variable, it is not even present in the parser's
+ hash tables.
+ \bprog
+ ? x = varhigher("#");
+ ? x^2
+ %2 = #^2
+ @eprog
+ \misctitle{Caution 2} There are a limited number of variables and if no
+ existing variable with the given display name has the requested
+ priority, the call to \kbd{varhigher} uses up one such slot. Do not create
+ new variables in this way unless it's absolutely necessary,
+ reuse existing names instead and choose sensible priority requirements:
+ if you only need a variable with higher priority than $x$, state so
+ rather than creating a new variable with highest priority.
+ \bprog
+ \\ quickly use up all variables
+ ? n = 0; while(1,varhigher("tmp"); n++)
+  ***   at top-level: n=0;while(1,varhigher("tmp");n++)
+  ***                             ^-------------------
+  *** varhigher: no more variables available.
+  ***   Break loop: type 'break' to go back to GP prompt
+ break> n
+ 65510
+ \\ infinite loop: here we reuse the same 'tmp'
+ ? n = 0; while(1,varhigher("tmp", x); n++)
+ @eprog
diff --git a/src/functions/conversions/variable b/src/functions/conversions/variable
index 42fb81d..40cfae8 100644
--- a/src/functions/conversions/variable
+++ b/src/functions/conversions/variable
@@ -27,8 +27,18 @@ Doc:
  @eprog\noindent can be used to test whether a variable is attached to $x$.
 
  If $x$ is omitted, returns the list of user variables known to the
- interpreter, by order of decreasing priority. (Highest priority is $x$,
- which always come first.)
+ interpreter, by order of decreasing priority. (Highest priority is initially
+ $x$, which come first until \tet{varhigher} is used.) If \kbd{varhigher}
+ or \kbd{varlower} are used, it is quite possible to end up with different
+ variables (with different priorities) printed in the same way: they
+ will then appear multiple times in the output:
+ \bprog
+ ? varhigher("y");
+ ? varlower("y");
+ ? variable()
+ %4 = [y, x, y]
+ @eprog\noindent Using \kbd{v = variable()} then \kbd{v[1]}, \kbd{v[2]},
+ etc.~allows to recover and use existing variables.
 
 Variant: However, in library mode, this function should not be used for $x$
  non-\kbd{NULL}, since \tet{gvar} is more appropriate. Instead, for
diff --git a/src/functions/conversions/variables b/src/functions/conversions/variables
new file mode 100644
index 0000000..dfe5031
--- /dev/null
+++ b/src/functions/conversions/variables
@@ -0,0 +1,31 @@
+Function: variables
+Section: conversions
+C-Name: variables_vec
+Prototype: DG
+Help: variables({x}): all variables occuring in object x, sorted by
+ decreasing priority. Returns the list of user variables if x is omitted.
+Doc:
+ returns the list of all variables occuring in object $x$ (all user
+ variables known to the interpreter if $x$ is omitted), sorted by
+ decreasing priority.
+ \bprog
+ ? variables([x^2 + y*z + O(t), a+x])
+ %1 = [x, y, z, t, a]
+ @eprog\noindent The construction
+ \bprog
+    if (!variables(x),...)
+ @eprog\noindent can be used to test whether a variable is attached to $x$.
+
+ If \kbd{varhigher} or \kbd{varlower} are used, it is quite possible to end up
+ with different variables (with different priorities) printed in the same
+ way: they will then appear multiple times in the output:
+ \bprog
+ ? y1 = varhigher("y");
+ ? y2 = varlower("y");
+ ? variables(y*y1*y2)
+ %4 = [y, y, y]
+ @eprog
+
+Variant:
+ Also available is \fun{GEN}{variables_vecsmall}{GEN x} which returns
+ the (sorted) variable numbers instead of the associated monomials of degree 1.
diff --git a/src/functions/conversions/varlower b/src/functions/conversions/varlower
new file mode 100644
index 0000000..04430c4
--- /dev/null
+++ b/src/functions/conversions/varlower
@@ -0,0 +1,82 @@
+Function: varlower
+Section: conversions
+C-Name: varlower
+Prototype: sDn
+Help: varlower(name,{v}): return a variable 'name' whose priority is lower
+ than the priority of v (of all existing variables if v is omitted.
+Doc: return a variable \emph{name} whose priority is lower
+ than the priority of $v$ (of all existing variables if $v$ is omitted).
+ This is a counterpart to \tet{varhigher}.
+
+ New GP variables directly created by the interpreter always
+ have lower priority than existing GP variables, but it is not easy
+ to check whether an identifier is currently unused, so that the
+ corresponding variable has the expected priority when it's created!
+ Thus, depending on the session history, the same command may fail or succeed:
+ \bprog
+ ? t; z;  \\ now t > z
+ ? rnfequation(t^2+1,z^2-t)
+  ***   at top-level: rnfequation(t^2+1,z^
+  ***                 ^--------------------
+  *** rnfequation: incorrect priority in rnfequation: variable t >= t
+ @eprog\noindent Restart and retry:
+ \bprog
+ ? z; t;  \\ now z > t
+ ? rnfequation(t^2+1,z^2-t)
+ %2 = z^4 + 1
+ @eprog\noindent It is quite annoying for package authors, when trying to
+ define a base ring, to notice that the package may fail for some users
+ depending on their session history. The safe way to do this is as follows:
+ \bprog
+ ? z; t;  \\ In new session: now z > t
+ ...
+ ? t = varlower("t", 'z);
+ ? rnfequation(t^2+1,z^2-2)
+ %2 = z^4 - 2*z^2 + 9
+ ? variable()
+ %3 = [x, y, z, t]
+ @eprog
+ \bprog
+ ? t; z;  \\ In new session: now t > z
+ ...
+ ? t = varlower("t", 'z); \\ create a new variable, still printed "t"
+ ? rnfequation(t^2+1,z^2-2)
+ %2 = z^4 - 2*z^2 + 9
+ ? variable()
+ %3 = [x, y, t, z, t]
+ @eprog\noindent Now both constructions succeed. Note that in the
+ first case, \kbd{varlower} is essentially a no-op, the existing variable $t$
+ has correct priority. While in the second case, two different variables are
+ displayed as \kbd{t}, one with higher priority than $z$ (created in the first
+  line) and another one with lower priority (created by \kbd{varlower}).
+
+ \misctitle{Caution 1}
+ The \emph{name} is an arbitrary character string, only used for display
+ purposes and need not be related to the GP variable holding the result, nor
+ to be a valid variable name. In particular the \emph{name} can
+ not be used to retrieve the variable, it is not even present in the parser's
+ hash tables.
+ \bprog
+ ? x = varlower("#");
+ ? x^2
+ %2 = #^2
+ @eprog
+ \misctitle{Caution 2} There are a limited number of variables and if no
+ existing variable with the given display name has the requested
+ priority, the call to \kbd{varlower} uses up one such slot. Do not create
+ new variables in this way unless it's absolutely necessary,
+ reuse existing names instead and choose sensible priority requirements:
+ if you only need a variable with higher priority than $x$, state so
+ rather than creating a new variable with highest priority.
+ \bprog
+ \\ quickly use up all variables
+ ? n = 0; while(1,varlower("x"); n++)
+  ***   at top-level: n=0;while(1,varlower("x");n++)
+  ***                             ^-------------------
+  *** varlower: no more variables available.
+  ***   Break loop: type 'break' to go back to GP prompt
+ break> n
+ 65510
+ \\ infinite loop: here we reuse the same 'tmp'
+ ? n = 0; while(1,varlower("tmp", x); n++)
+ @eprog
diff --git a/src/functions/default/breakloop b/src/functions/default/breakloop
index 7b418fa..a3905d1 100644
--- a/src/functions/default/breakloop
+++ b/src/functions/default/breakloop
@@ -1,5 +1,5 @@
 Function: _def_breakloop
-Class: gp_default
+Class: default
 Section: default
 C-Name: sd_breakloop
 Prototype:
diff --git a/src/functions/default/compatible b/src/functions/default/compatible
index d80ab34..17a294a 100644
--- a/src/functions/default/compatible
+++ b/src/functions/default/compatible
@@ -4,42 +4,4 @@ Section: default
 C-Name: sd_compatible
 Prototype:
 Help:
-Doc: The GP function names and syntax
- have changed tremendously between versions 1.xx and 2.00. To help you cope
- with this we provide some kind of backward compatibility, depending on the
- value of this default:
-
- \quad \kbd{compatible} = 0: no backward compatibility. In this mode, a very
- handy function, to be described in \secref{se:whatnow}, is \kbd{whatnow},
- which tells you what has become of your favorite functions, which \kbd{gp}
- suddenly can't seem to remember.
-
- \quad \kbd{compatible} = 1: warn when using obsolete functions, but
- otherwise accept them. The output uses the new conventions though, and
- there may be subtle incompatibilities between the behavior of former and
- current functions, even when they share the same name (the current function
- is used in such cases, of course!). We thought of this one as a transitory
- help for \kbd{gp} old-timers. Thus, to encourage switching to \kbd{compatible}=0,
- it is not possible to disable the warning.
-
- \quad \kbd{compatible} = 2: use only the old function naming scheme (as
- used up to version 1.39.15), but \emph{taking case into account}. Thus
- \kbd{I} (${}=\sqrt{-1}$) is not the same as \kbd{i} (user variable, unbound
- by default), and you won't get an error message using \kbd{i} as a loop
- index as used to be the case.
-
- \quad \kbd{compatible} = 3: try to mimic exactly the former behavior. This
- is not always possible when functions have changed in a fundamental way.
- But these differences are usually for the better (they were meant to,
- anyway), and will probably not be discovered by the casual user.
-
- One adverse side effect is that any user functions and aliases that have
- been defined \emph{before} changing \kbd{compatible} will get erased if this
- change modifies the function list, i.e.~if you move between groups
- $\{0,1\}$ and $\{2,3\}$ (variables are unaffected). We of course strongly
- encourage you to try and get used to the setting \kbd{compatible}=0.
-
- Note that the default \tet{new_galois_format} is another compatibility setting,
- which is completely independent of \kbd{compatible}.
-
- The default value is \kbd{0}.
+Doc: OBSOLETE. This default is now a no-op.
diff --git a/src/functions/default/echo b/src/functions/default/echo
index e6c1cae..0440706 100644
--- a/src/functions/default/echo
+++ b/src/functions/default/echo
@@ -1,5 +1,5 @@
 Function: _def_echo
-Class: gp_default
+Class: default
 Section: default
 C-Name: sd_echo
 Prototype:
diff --git a/src/functions/default/graphcolormap b/src/functions/default/graphcolormap
index 011012a..cc02773 100644
--- a/src/functions/default/graphcolormap
+++ b/src/functions/default/graphcolormap
@@ -1,5 +1,5 @@
 Function: _def_graphcolormap
-Class: gp_default
+Class: default
 Section: default
 C-Name: sd_graphcolormap
 Prototype:
diff --git a/src/functions/default/graphcolors b/src/functions/default/graphcolors
index 4b490b3..7e83062 100644
--- a/src/functions/default/graphcolors
+++ b/src/functions/default/graphcolors
@@ -1,5 +1,5 @@
 Function: _def_graphcolors
-Class: gp_default
+Class: default
 Section: default
 C-Name: sd_graphcolors
 Prototype:
diff --git a/src/functions/default/help b/src/functions/default/help
index b25aaeb..33d42a6 100644
--- a/src/functions/default/help
+++ b/src/functions/default/help
@@ -1,5 +1,5 @@
 Function: _def_help
-Class: gp_default
+Class: default
 Section: default
 C-Name: sd_help
 Prototype:
diff --git a/src/functions/default/histfile b/src/functions/default/histfile
index 74be8bc..18eb8b0 100644
--- a/src/functions/default/histfile
+++ b/src/functions/default/histfile
@@ -1,5 +1,5 @@
 Function: _def_histfile
-Class: gp_default
+Class: default
 Section: default
 C-Name: sd_histfile
 Prototype:
diff --git a/src/functions/default/lines b/src/functions/default/lines
index f21615d..2a140e1 100644
--- a/src/functions/default/lines
+++ b/src/functions/default/lines
@@ -1,5 +1,5 @@
 Function: _def_lines
-Class: gp_default
+Class: default
 Section: default
 C-Name: sd_lines
 Prototype:
diff --git a/src/functions/default/linewrap b/src/functions/default/linewrap
index 0050eb2..19dcf0d 100644
--- a/src/functions/default/linewrap
+++ b/src/functions/default/linewrap
@@ -1,5 +1,5 @@
 Function: _def_linewrap
-Class: gp_default
+Class: default
 Section: default
 C-Name: sd_linewrap
 Prototype:
diff --git a/src/functions/default/parisize b/src/functions/default/parisize
index 0aceeb1..2a5ec9c 100644
--- a/src/functions/default/parisize
+++ b/src/functions/default/parisize
@@ -5,13 +5,14 @@ C-Name: sd_parisize
 Prototype:
 Help:
 Doc: \kbd{gp}, and in fact any program using the PARI
- library, needs a \tev{stack} in which to do its computations. \kbd{parisize}
- is the stack size, in bytes. It is strongly recommended you increase this
- default (using the \kbd{-s} command-line switch, or a \tet{gprc}) if you can
- afford it. Don't increase it beyond the actual amount of RAM installed on
- your computer or \kbd{gp} will spend most of its time paging.
-
- In case of emergency, you can use the \tet{allocatemem} function to
- increase \kbd{parisize}, once the session is started.
+ library, needs a \tev{stack} in which to do its computations; \kbd{parisize}
+ is the stack size, in bytes. It is recommended to increase this
+ default using a \tet{gprc}, to the value you believe PARI should be happy
+ with, given your typical computation. We strongly recommend to also
+ set \tet{parisizemax} to a much larger value, about what you believe your
+ machine can stand: PARI will then try to fit its computations within about
+ \kbd{parisize} bytes, but will increase the stack size if needed (up to
+ \kbd{parisizemax}). Once the memory intensive computation is over, PARI
+ will restore the stack size to the originally requested \kbd{parisize}.
 
  The default value is 4M, resp.~8M on a 32-bit, resp.~64-bit machine.
diff --git a/src/functions/default/parisizemax b/src/functions/default/parisizemax
new file mode 100644
index 0000000..4cead7c
--- /dev/null
+++ b/src/functions/default/parisizemax
@@ -0,0 +1,19 @@
+Function: _def_parisizemax
+Class: default
+Section: default
+C-Name: sd_parisizemax
+Prototype:
+Help:
+Doc: \kbd{gp}, and in fact any program using the PARI library, needs a
+ \tev{stack} in which to do its computations.  If non-zero,  \kbd{parisizemax}
+ is the maximum size the stack can grow to, in bytes.  If zero, the stack will
+ not automatically grow, and will be limited to the value of \kbd{parisize}.
+
+ We strongly recommend to set \tet{parisizemax} to a non-zero value, about
+ what you believe your machine can stand: PARI will then try to fit its
+ computations within about \kbd{parisize} bytes, but will increase the stack
+ size if needed (up to \kbd{parisizemax}). Once the memory intensive
+ computation is over, PARI will restore the stack size to the originally
+ requested \kbd{parisize}.
+
+ The default value is $0$.
diff --git a/src/functions/default/prompt b/src/functions/default/prompt
index 2e5b016..82087e7 100644
--- a/src/functions/default/prompt
+++ b/src/functions/default/prompt
@@ -1,5 +1,5 @@
 Function: _def_prompt
-Class: gp_default
+Class: default
 Section: default
 C-Name: sd_prompt
 Prototype:
diff --git a/src/functions/default/prompt_cont b/src/functions/default/prompt_cont
index 2af6aa2..197ae9c 100644
--- a/src/functions/default/prompt_cont
+++ b/src/functions/default/prompt_cont
@@ -1,5 +1,5 @@
 Function: _def_prompt_cont
-Class: gp_default
+Class: default
 Section: default
 C-Name: sd_prompt_cont
 Prototype:
diff --git a/src/functions/default/psfile b/src/functions/default/psfile
index 207ec91..3793499 100644
--- a/src/functions/default/psfile
+++ b/src/functions/default/psfile
@@ -1,5 +1,5 @@
 Function: _def_psfile
-Class: gp_default
+Class: default
 Section: default
 C-Name: sd_psfile
 Prototype:
diff --git a/src/functions/default/readline b/src/functions/default/readline
index 20d0b20..cad1c9f 100644
--- a/src/functions/default/readline
+++ b/src/functions/default/readline
@@ -1,5 +1,5 @@
 Function: _def_readline
-Class: gp_default
+Class: default
 Section: default
 C-Name: sd_readline
 Prototype:
diff --git a/src/functions/default/recover b/src/functions/default/recover
index e9694ad..f8eda80 100644
--- a/src/functions/default/recover
+++ b/src/functions/default/recover
@@ -1,5 +1,5 @@
 Function: _def_recover
-Class: gp_default
+Class: default
 Section: default
 C-Name: sd_recover
 Prototype:
diff --git a/src/functions/default/strictmatch b/src/functions/default/strictmatch
index 7ec1d9b..8953876 100644
--- a/src/functions/default/strictmatch
+++ b/src/functions/default/strictmatch
@@ -4,11 +4,4 @@ Section: default
 C-Name: sd_strictmatch
 Prototype:
 Help:
-Doc: this toggle is either 1 (on) or 0 (off). If on, unused characters after a
- sequence has been
- processed will produce an error. Otherwise just a warning is printed. This
- can be useful when you are unsure how many parentheses you have to close
- after complicated nested loops. Please do not use this; find a decent
- text-editor instead.
-
- The default value is \kbd{1}.
+Doc: OBSOLETE. This toggle is now a no-op.
diff --git a/src/functions/default/threadsizemax b/src/functions/default/threadsizemax
new file mode 100644
index 0000000..80e4094
--- /dev/null
+++ b/src/functions/default/threadsizemax
@@ -0,0 +1,15 @@
+Function: _def_threadsizemax
+Class: default
+Section: default
+C-Name: sd_threadsizemax
+Prototype:
+Help:
+Doc: In parallel mode, each threads needs its own private \tev{stack} in which
+ to do its computations, see \kbd{parisize}. This value determines the maximal
+ size in bytes of the stacks of each thread, so the total memory allocated will
+ be between $\kbd{parisize}+\kbd{nbthreads}\times\kbd{threadsize}$. and
+ $\kbd{parisize}+\kbd{nbthreads}\times\kbd{threadsizemax}$.
+
+ If set to $0$, the value used is the same as \kbd{threadsize}.
+
+ The default value is $0$.
diff --git a/src/functions/default/timer b/src/functions/default/timer
index 513f4ba..3fd3b70 100644
--- a/src/functions/default/timer
+++ b/src/functions/default/timer
@@ -1,5 +1,5 @@
 Function: _def_timer
-Class: gp_default
+Class: default
 Section: default
 C-Name: sd_timer
 Prototype:
diff --git a/src/functions/elliptic_curves/ellL1 b/src/functions/elliptic_curves/ellL1
index 18bb491..2f4dc43 100644
--- a/src/functions/elliptic_curves/ellL1
+++ b/src/functions/elliptic_curves/ellL1
@@ -1,18 +1,16 @@
 Function: ellL1
 Section: elliptic_curves
 C-Name: ellL1
-Prototype: GLp
-Help: ellL1(e, r): returns the value at s=1 of the derivative of order r of the L-function of the elliptic curve e assuming that r is at most the order of vanishing of the function at s=1.
+Prototype: GD0,L,p
+Help: ellL1(e, {r = 0}): returns the value at s=1 of the derivative of order r of the L-function of the elliptic curve e assuming that r is at most the order of vanishing of the function at s=1.
 Doc: returns the value at $s=1$ of the derivative of order $r$ of the
- $L$-function of the elliptic curve $e$ assuming that $r$ is at most the order
- of vanishing of the $L$-function at $s=1$. (The result is wrong if $r$ is
- strictly larger than the order of vanishing at 1.)
+ $L$-function of the elliptic curve $e$.
  \bprog
  ? e = ellinit("11a1"); \\ order of vanishing is 0
- ? ellL1(e, 0)
+ ? ellL1(e)
  %2 = 0.2538418608559106843377589233
  ? e = ellinit("389a1");  \\ order of vanishing is 2
- ? ellL1(e, 0)
+ ? ellL1(e)
  %4 = -5.384067311837218089235032414 E-29
  ? ellL1(e, 1)
  %5 = 0
@@ -26,12 +24,12 @@ Doc: returns the value at $s=1$ of the derivative of order $r$ of the
  \bprog
  ? \p18
    realprecision = 18 significant digits
- ? ellanalyticrank(ellinit([0, 0, 1, -7, 6]))
- time = 32 ms.
+ ? e = ellinit("5077a1"); ellanalyticrank(e)
+ time = 8 ms.
  %1 = [3, 10.3910994007158041]
  ? \p200
    realprecision = 202 significant digits (200 digits displayed)
  ? ellL1(e, 3)
- time = 23,113 ms.
+ time = 104 ms.
  %3 = 10.3910994007158041387518505103609170697263563756570092797 at com$[\dots]$
  @eprog
diff --git a/src/functions/elliptic_curves/ellap b/src/functions/elliptic_curves/ellap
index 81aaeed..d7aaf9e 100644
--- a/src/functions/elliptic_curves/ellap
+++ b/src/functions/elliptic_curves/ellap
@@ -46,8 +46,8 @@ Doc:
  quadratic order we use a fast explicit formula (involving essentially Kronecker
  symbols and Cornacchia's algorithm), in $O(\log q)^2$.
  Otherwise, we use Shanks-Mestre's baby-step/giant-step method, which runs in
- time $q(p^{1/4})$ using $O(q^{1/4})$ storage, hence becomes unreasonable when
- $q$ has about 30~digits. If the \tet{seadata} package is installed, the
- \tet{SEA} algorithm becomes available, heuristically in $\tilde{O}(\log
- q)^4$, and primes of the order of 200~digits become feasible. In very small
- characteristic (2,3,5,7 or $13$), we use Harley's algorithm.
+ time $\tilde{O}(q^{1/4})$ using $\tilde{O}(q^{1/4})$ storage, hence becomes
+ unreasonable when $q$ has about 30~digits. If the \tet{seadata} package is
+ installed, the \tet{SEA} algorithm becomes available, heuristically in
+ $\tilde{O}(\log q)^4$, and primes of the order of 200~digits become feasible.
+ In very small characteristic (2,3,5,7 or $13$), we use Harley's algorithm.
diff --git a/src/functions/elliptic_curves/ellbil b/src/functions/elliptic_curves/ellbil
index 3821feb..b4ee64b 100644
--- a/src/functions/elliptic_curves/ellbil
+++ b/src/functions/elliptic_curves/ellbil
@@ -2,12 +2,5 @@ Function: ellbil
 Section: elliptic_curves
 C-Name: bilhell
 Prototype: GGGp
-Help: ellbil(E,z1,z2): canonical bilinear form for the points z1,z2 on the
- elliptic curve E. Either z1 or z2 can also be a vector/matrix of points.
-Doc:
- if $z1$ and $z2$ are points on the elliptic
- curve $E$ this function
- computes the value of the canonical bilinear form on $z1$, $z2$:
- $$ ( h(E,z1\kbd{+}z2) - h(E,z1) - h(E,z2) ) / 2 $$
- where \kbd{+} denotes of course addition on $E$. In addition, $z1$ or $z2$
- (but not both) can be vectors or matrices.
+Help: ellbil(E,z1,z2): deprecated alias for ellheight(E,P,Q).
+Doc: deprecated alias for \kbd{ellheight(E,P,Q)}.
diff --git a/src/functions/elliptic_curves/ellcard b/src/functions/elliptic_curves/ellcard
index d830502..e5d2317 100644
--- a/src/functions/elliptic_curves/ellcard
+++ b/src/functions/elliptic_curves/ellcard
@@ -11,7 +11,7 @@ Doc: Let $E$ be an \var{ell} structure as output by \kbd{ellinit}, defined over
  computed by \tet{ellgroup}).
 
  If the curve is defined over $\Q$, $p$ must be explicitly given and the
- function computes the cardinal of the reduction over $\F_p$; the
+ function computes the cardinality of the reduction over $\F_p$; the
  equation need not be minimal at $p$, but a minimal model will be more
  efficient. The reduction is allowed to be singular, and we return the order
  of the group of non-singular points in this case.
diff --git a/src/functions/elliptic_curves/elleisnum b/src/functions/elliptic_curves/elleisnum
index c8c3282..3cea378 100644
--- a/src/functions/elliptic_curves/elleisnum
+++ b/src/functions/elliptic_curves/elleisnum
@@ -11,7 +11,7 @@ Doc: $k$ being an even positive integer, computes the numerical value of the
  \tet{ellperiods}, namely
  $$
  (2i \pi/\omega_2)^k
- \Big(1 + 2/\zeta(1-k) \sum_{n\geq 0} n^{k-1}q^n / (1-q^n)\Big),
+ \Big(1 + 2/\zeta(1-k) \sum_{n\geq 1} n^{k-1}q^n / (1-q^n)\Big),
  $$
  where $q = \exp(2i\pi \tau)$ and $\tau:=\omega_1/\omega_2$ belongs to the
  complex upper half-plane. It is also possible to directly input $w =
diff --git a/src/functions/elliptic_curves/ellformaldifferential b/src/functions/elliptic_curves/ellformaldifferential
new file mode 100644
index 0000000..d80b7bc
--- /dev/null
+++ b/src/functions/elliptic_curves/ellformaldifferential
@@ -0,0 +1,22 @@
+Function: ellformaldifferential
+Section: elliptic_curves
+C-Name: ellformaldifferential
+Prototype: GDPDn
+Help:ellformaldifferential(E, {n=seriesprecision}, {t = 'x}) : E elliptic curve,
+ n integer. Returns n terms of the power series [f, g] such that
+ omega = dx/(2y+a_1x+a_3) = f(t) dt and eta = x(t) * omega = g(t) dt in the
+ local parameter t=-x/y.
+Doc:Let $\omega := dx / (2y+a_1x+a_3$ be the invariant differential form
+ associated to the model $E$ of some elliptic curve (\kbd{ellinit} form),
+ and $\eta := x(t)\omega$. Return $n$ terms (\tet{seriesprecision} by default)
+ of $f(t),g(t)$ two power series in the formal parameter $t=-x/y$ such that
+ $\omega = f(t) dt$, $\eta = g(t) dt$:
+  $$f(t) = 1+a_1 t + (a_1^2 + a_2) t^2 + \dots,\quad
+    g(t) = t^{-2} +\dots $$
+  \bprog
+  ? E = ellinit([-1,1/4]); [f,g] = ellformaldifferential(E,7,'t);
+  ? f
+  %2 = 1 - 2*t^4 + 3/4*t^6 + O(t^7)
+  ? g
+  %3 = t^-2 - t^2 + 1/2*t^4 + O(t^5)
+ @eprog
diff --git a/src/functions/elliptic_curves/ellformalexp b/src/functions/elliptic_curves/ellformalexp
new file mode 100644
index 0000000..b3b2a7a
--- /dev/null
+++ b/src/functions/elliptic_curves/ellformalexp
@@ -0,0 +1,18 @@
+Function: ellformalexp
+Section: elliptic_curves
+C-Name: ellformalexp
+Prototype: GDPDn
+Help:ellformalexp(E, {n = seriesprecision}, {z = 'x}) : E elliptic curve,
+ returns n terms of the formal elliptic exponential on E as a series in z
+Doc:The elliptic formal exponential \kbd{Exp} attached to $E$ is the
+ isomorphism from the formal additive law to the formal group of $E$. It is
+ normalized so as to be the inverse of the elliptic logarithm (see
+ \tet{ellformallog}): $\kbd{Exp} \circ L = \Id$. Return $n$ terms of this
+ power series:
+ \bprog
+ ? E=ellinit([-1,1/4]); Exp = ellformalexp(E,10,'z)
+ %1 = z + 2/5*z^5 - 3/28*z^7 + 2/15*z^9 + O(z^11)
+ ? L = ellformallog(E,10,'t);
+ ? subst(Exp,z,L)
+ %3 = t + O(t^11)
+ @eprog
diff --git a/src/functions/elliptic_curves/ellformallog b/src/functions/elliptic_curves/ellformallog
new file mode 100644
index 0000000..dd62c03
--- /dev/null
+++ b/src/functions/elliptic_curves/ellformallog
@@ -0,0 +1,17 @@
+Function: ellformallog
+Section: elliptic_curves
+C-Name: ellformallog
+Prototype: GDPDn
+Help:ellformallog(E, {n = seriesprecision}, {v = 't}): E elliptic curve,
+ returns n terms of the elliptic logarithm as a series of t =-x/y.
+Doc: The formal elliptic logarithm is a series $L$ in $t K[[t]]$
+ such that $d L = \omega = dx / (2y + a_1x + a_3$, the canonical invariant
+ differential attached to the model $E$. It gives an isomorphism
+ from the formal group of $E$ to the additive formal group.
+ \bprog
+ ? E = ellinit([-1,1/4]); L = ellformallog(E, 9, 't)
+ %1 = t - 2/5*t^5 + 3/28*t^7 + 2/3*t^9 + O(t^10)
+ ? [f,g] = ellformaldifferential(E,8,'t);
+ ? L' - f
+ %3 = O(t^8)
+ @eprog
diff --git a/src/functions/elliptic_curves/ellformalpoint b/src/functions/elliptic_curves/ellformalpoint
new file mode 100644
index 0000000..5b5363d
--- /dev/null
+++ b/src/functions/elliptic_curves/ellformalpoint
@@ -0,0 +1,23 @@
+Function: ellformalpoint
+Section: elliptic_curves
+C-Name: ellformalpoint
+Prototype: GDPDn
+Help: ellformalpoint(E, {n = seriesprecision}, {v = 'x}): E elliptic curve,
+ n integer; return the coordinates [x(t), y(t)] on the elliptic curve as a
+ formal expansion in the formal parameter t = -x/y.
+Doc: If $E$ is an elliptic curve, return the coordinates $x(t), y(t)$ in the
+ formal group of the elliptic curve $E$ in the formal parameter $t = -x/y$
+ at $\infty$:
+ $$ x = t^{-2} -a_1 t^{-1} - a_2 - a_3 t + \dots $$
+ $$ y = - t^{-3} -a_1 t^{-2} - a_2t^{-1} -a_3 + \dots $$
+ Return $n$ terms (\tet{seriesprecision} by default) of these two power
+ series, whose coefficients are in $\Z[a_1,a_2,a_3,a_4,a_6]$.
+ \bprog
+ ? E = ellinit([0,0,1,-1,0]); [x,y] = ellformalpoint(E,8);
+ ? x
+ %2 = x^-2 - x + x^2 - x^4 + 2*x^5 + O(x^6)
+ ? y
+ %3 = -x^-3 + 1 - x + x^3 - 2*x^4 + O(x^5)
+ ? E = ellinit([0,1/2]); ellformalpoint(E,7)
+ %4 = [x^-2 - 1/2*x^4 + O(x^5), -x^-3 + 1/2*x^3 + O(x^4)]
+ @eprog
diff --git a/src/functions/elliptic_curves/ellformalw b/src/functions/elliptic_curves/ellformalw
new file mode 100644
index 0000000..45661ce
--- /dev/null
+++ b/src/functions/elliptic_curves/ellformalw
@@ -0,0 +1,17 @@
+Function: ellformalw
+Section: elliptic_curves
+C-Name: ellformalw
+Prototype: GDPDn
+Help:ellformalw(E, {n = seriesprecision}, {t = 'x}): E elliptic curve,
+ n integer; returns n terms of the formal expansion of w = -1/y in the formal
+ parameter t = -x/y.
+Doc:Return the formal power series $w$ associated to the elliptic curve $E$,
+ in the variable $t$:
+ $$ w(t) = t^3 + a_1 t^4 + (a_2 + a_1^2) t^5 + \cdots + O(t^{n+3}),$$
+ which is the formal expansion of $-1/y$ in the formal parameter $t := -x/y$
+ at $\infty$ (take $n = \tet{seriesprecision}$ if $n$ is omitted). The
+ coefficients of $w$ belong to $\Z[a_1,a_2,a_3,a_4,a_6]$.
+ \bprog
+ ? E=ellinit([3,2,-4,-2,5]); ellformalw(E, 5, 't)
+ %1 = t^3 + 3*t^4 + 11*t^5 + 35*t^6 + 101*t^7 + O(t^8)
+ @eprog
diff --git a/src/functions/elliptic_curves/ellheight b/src/functions/elliptic_curves/ellheight
index f046bf3..0bdcdc2 100644
--- a/src/functions/elliptic_curves/ellheight
+++ b/src/functions/elliptic_curves/ellheight
@@ -1,21 +1,17 @@
 Function: ellheight
 Section: elliptic_curves
 C-Name: ellheight0
-Prototype: GGD2,L,p
-Help: ellheight(E,x,{flag=2}): canonical height of point x on elliptic curve
- E. flag is optional and selects the algorithm
- used to compute the Archimedean local height. Its meaning is 0: use
- theta-functions, 1: use Tate's method, 2: use Mestre's AGM.
-Doc: global N\'eron-Tate height of the point $z$ on the elliptic curve
- $E$ (defined over $\Q$), using the normalization in Cremona's
- \emph{Algorithms for modular elliptic curves}. $E$
- must be an \kbd{ell} as output by \kbd{ellinit}; it needs not be given by a
- minimal model although the computation will be faster if it is. \fl\ selects
- the algorithm used to compute the Archimedean local height. If $\fl=0$,
- we use sigma and theta-functions and Silverman's trick (Computing
- heights on elliptic curves, \emph{Math.~Comp.} {\bf 51}; note that
- our height is twice Silverman's height). If
- $\fl=1$, use Tate's $4^n$ algorithm. If $\fl=2$, use Mestre's AGM algorithm.
- The latter converges quadratically and is much faster than the other two.
-Variant: Also available is \fun{GEN}{ghell}{GEN E, GEN x, long prec}
- ($\fl=2$).
+Prototype: GGDGp
+Help: ellheight(E,P,{Q}): canonical height of point P on elliptic curve E,
+ resp. the value of the associated bilinear form at (P,Q).
+Doc: global N\'eron-Tate height $h(P)$ of the point $P$ on the elliptic curve
+ $E/\Q$, using the normalization in Cremona's \emph{Algorithms for modular
+ elliptic curves}. $E$ must be an \kbd{ell} as output by \kbd{ellinit}; it
+ needs not be given by a minimal model although the computation will be faster
+ if it is.
+
+ If the argument $Q$ is present, computes the value of the bilinear
+ form $(h(P+Q)-h(P-Q)) / 4$.
+
+Variant: Also available is \fun{GEN}{ellheight}{GEN E, GEN P, long prec}
+ ($Q$ omitted).
diff --git a/src/functions/elliptic_curves/ellheightmatrix b/src/functions/elliptic_curves/ellheightmatrix
index fd3f3e1..c2a0a7b 100644
--- a/src/functions/elliptic_curves/ellheightmatrix
+++ b/src/functions/elliptic_curves/ellheightmatrix
@@ -1,6 +1,6 @@
 Function: ellheightmatrix
 Section: elliptic_curves
-C-Name: mathell
+C-Name: ellheightmatrix
 Prototype: GGp
 Help: ellheightmatrix(E,x): gives the height matrix for vector of points x
  on elliptic curve E.
diff --git a/src/functions/elliptic_curves/ellinit b/src/functions/elliptic_curves/ellinit
index 5984394..e4f77ba 100644
--- a/src/functions/elliptic_curves/ellinit
+++ b/src/functions/elliptic_curves/ellinit
@@ -50,6 +50,12 @@ Doc:
  \kbd{precision}$(x)$. If no such argument is given, the value of
  \kbd{realprecision} at the time \kbd{ellinit} is called will be used.
 
+ \item a number field $K$, given by a \var{nf} or \var{bnf} structure.
+
+ \item a prime ideal $\goth{p}$, given by a \var{prid} structure; valid if
+ $x$ is a curve defined over a number field $K$ and the equation is integral
+ and minimal at $\goth{p}$.
+
  This argument $D$ is indicative: the curve coefficients are checked for
  compatibility, possibly changing $D$; for instance if $D = 1$ and
  an \typ{INTMOD} is found. If inconsistencies are detected, an error is
diff --git a/src/functions/elliptic_curves/ellisdivisible b/src/functions/elliptic_curves/ellisdivisible
new file mode 100644
index 0000000..79f0c1b
--- /dev/null
+++ b/src/functions/elliptic_curves/ellisdivisible
@@ -0,0 +1,27 @@
+Function: ellisdivisible
+Section: elliptic_curves
+C-Name: ellisdivisible
+Prototype: lGGGD&
+Help: ellisdivisible(E,P,n,{&Q})): given E/K and P in E(K),
+ checks whether P = [n]R for some R in E(K) and sets Q to one such R if so;
+ the integer n >= 0 may be given as ellxn(E,n)
+Doc: given $E/K$ a number field and $P$ in $E(K)$
+ return $1$ if $P = [n]R$ for some $R$ in $E(K)$ and set $Q$ to one such $R$;
+ and return $0$ otherwise. The integer $n \geq 0$ may be given as
+ \kbd{ellxn(E,n)}, if many points need to be tested.
+ \bprog
+ ? K = nfinit(polcyclo(11,t));
+ ? E = ellinit([0,-1,1,0,0], K);
+ ? P = [0,0];
+ ? ellorder(E,P)
+ %4 = 5
+ ? ellisdivisible(E,P,5, &Q)
+ %5 = 1
+ ? lift(Q)
+ %6 = [-t^7-t^6-t^5-t^4+1, -t^9-2*t^8-2*t^7-3*t^6-3*t^5-2*t^4-2*t^3-t^2-1]
+ ? ellorder(E, Q)
+ %7 = 25
+ @eprog\noindent The complexity of the underlying algorithm is at least in
+ $O(n^4)$, so it is advisable to first factor $n$, then use a chain of checks
+ associated to the prime divisors of n: the function will do it itself unless
+ $n$ is given in \kbd{ellxn} form.
diff --git a/src/functions/elliptic_curves/ellisogeny b/src/functions/elliptic_curves/ellisogeny
new file mode 100644
index 0000000..0e31190
--- /dev/null
+++ b/src/functions/elliptic_curves/ellisogeny
@@ -0,0 +1,23 @@
+Function: ellisogeny
+Section: elliptic_curves
+C-Name: ellisogeny
+Prototype: GGD0,L,DnDn
+Help: ellisogeny(E, G, {only_image = 0}, {x = 'x}, {y = 'y}): compute the image and isogeny corresponding to the quotient of E by the subgroup G.
+Doc:
+ Given an elliptic curve $E$, a finite subgroup $G$ of $E$ is given either
+ as a generating point $P$ (for a cyclic $G$) or as a polynomial whose roots
+ vanish on the $x$-coordinates of the non-zero elements of $G$ (general case
+ and more efficient if available). This function returns the
+ $[a_1,a_2,a_3,a_4,a_6]$ invariants of the quotient elliptic curve $E/G$ and
+ (if \var{only\_image} is zero (the default)) a vector of rational
+ functions $[f, g, h]$ such that the isogeny $E \to E/G$ is given by $(x,y)
+ \mapsto (f(x)/h(x)^2, g(x,y)/h(x)^3)$.
+ \bprog
+ ? E = ellinit([0,1]);
+ ? elltors(E)
+ %2 = [6, [6], [[2, 3]]]
+ ? ellisogeny(E, [2,3], 1)  \\ Weierstrass model for E/<P>
+ %3 = [0, 0, 0, -135, -594]
+ ? ellisogeny(E,[-1,0])
+ %4 = [[0,0,0,-15,22], [x^3+2*x^2+4*x+3, y*x^3+3*y*x^2-2*y, x+1]]
+ @eprog
diff --git a/src/functions/elliptic_curves/ellisogenyapply b/src/functions/elliptic_curves/ellisogenyapply
new file mode 100644
index 0000000..424dcc2
--- /dev/null
+++ b/src/functions/elliptic_curves/ellisogenyapply
@@ -0,0 +1,32 @@
+Function: ellisogenyapply
+Section: elliptic_curves
+C-Name: ellisogenyapply
+Prototype: GG
+Help: ellisogenyapply(f, g): Given an isogeny f and g either a point P (in the
+ domain of f) or an isogeny, apply f to x: return the image of P under f or
+ the composite isogeny fog.
+Doc:
+ Given an isogeny of elliptic curves $f:E'\to E$ (being the result of a call
+ to \tet{ellisogeny}), apply $f$ to $x$:
+
+ \item if $x$ is a point $P$ in the domain of $f$, return the image $f(P)$;
+
+ \item if $x$ is a compatible isogeny $g:E''\to E'$, return the composite
+ isogeny $f \circ g:  E''\to E$.
+
+ \bprog
+ ? one = ffgen(101, 't)^0;
+ ? E = ellinit([6, 53, 85, 32, 34] * one);
+ ? P = [84, 71] * one;
+ ? ellorder(E, P)
+ %4 = 5
+ ? [F, f] = ellisogeny(E, P);  \\ f: E->F = E/<P>
+ ? ellisogenyapply(f, P)
+ %6 = [0]
+ ? F = ellinit(F);
+ ? Q = [89, 44] * one;
+ ? ellorder(F, Q)
+ %9 = 2;
+ ? [G, g] = ellisogeny(F, Q); \\  g: F->G = F/<Q>
+ ? gof = ellisogenyapply(g, f); \\ gof: E -> G
+ @eprog
diff --git a/src/functions/elliptic_curves/ellissupersingular b/src/functions/elliptic_curves/ellissupersingular
new file mode 100644
index 0000000..560b58b
--- /dev/null
+++ b/src/functions/elliptic_curves/ellissupersingular
@@ -0,0 +1,22 @@
+Function: ellissupersingular
+Section: elliptic_curves
+C-Name: ellissupersingular
+Prototype: iGDG
+Help: ellissupersingular(E,{p}): return whether the elliptic curve E, defined
+ over Q or a finite field, is supersingular at p or not.
+Doc:
+ Return 1 if the elliptic curve $E$ defined over Q or a finite field is supersingular
+ at $p$, and $0$ otherwise.
+ If the curve is defined over $\Q$, $p$ must be explicitly given and have good
+ reduction at $p$.
+ Alternatively, $E$ can be given byt its $j$-invariant in a finite field. In
+ this case $p$ must be omitted.
+ \bprog
+ ? g = ffprimroot(ffgen(7^5))
+ %1 = x^3 + 2*x^2 + 3*x + 1
+ ? [g^n | n <- [1 .. 7^5 - 1], ellissupersingular(g^n)]
+ %2 = [6]
+ @eprog
+Variant: Also available is
+ \fun{int}{elljissupersingular}{GEN j} where $j$ is a $j$-invariant of a curve
+ over a finite field.
diff --git a/src/functions/elliptic_curves/elllocalred b/src/functions/elliptic_curves/elllocalred
index 66155de..6cb040f 100644
--- a/src/functions/elliptic_curves/elllocalred
+++ b/src/functions/elliptic_curves/elllocalred
@@ -8,8 +8,10 @@ Help: elllocalred(E,p): E being an elliptic curve, returns
  minimal at p, and c is the local Tamagawa number c_p.
 Doc:
  calculates the \idx{Kodaira} type of the local fiber of the elliptic curve
- $E$ at the prime $p$. $E$ must be an \var{ell} structure as output by
- \kbd{ellinit}, and is assumed to have all its coefficients $a_i$ in $\Z$.
+ $E$ at $p$. $E$ must be an \var{ell} structure as output by
+ \kbd{ellinit}, over $\Q$ ($p$ a rational prime) or a number field $K$ ($p$
+ a maximal ideal given by a \var{prid} structure), and is assumed to have all
+ its coefficients $a_i$ integral.
  The result is a 4-component vector $[f,kod,v,c]$. Here $f$ is the exponent of
  $p$ in the arithmetic conductor of $E$, and $kod$ is the Kodaira type which
  is coded as follows:
@@ -21,3 +23,6 @@ Doc:
  giving the coordinate changes done during the local reduction;
  $u = 1$ if and only if the given equation was already minimal at $p$.
  Finally, the last component $c$ is the local \idx{Tamagawa number} $c_p$.
+
+ \misctitle{Caveat} If $E$ is not defined over $\Q$, the current
+ implementation requires that $p$ be above a prime $\geq 5$.
diff --git a/src/functions/elliptic_curves/ellnonsingularmultiple b/src/functions/elliptic_curves/ellnonsingularmultiple
new file mode 100644
index 0000000..2c442e0
--- /dev/null
+++ b/src/functions/elliptic_curves/ellnonsingularmultiple
@@ -0,0 +1,19 @@
+Function: ellnonsingularmultiple
+Section: elliptic_curves
+C-Name: ellnonsingularmultiple
+Prototype: GG
+Help: ellnonsingularmultiple(E,P):
+Doc: given an elliptic curve $E/\Q$ (more precisely, a model defined over $\Q$
+ of a curve) and a rational point $P \in E(\Q)$, returns the pair $[R,n]$,
+ where $n$ is the least positive integer such that $R := [n]P$ has good
+ reduction at every prime. More precisely, its image in a minimal model is
+ everywhere non-singular.
+ \bprog
+ ? e = ellinit("57a1"); P = [2,-2];
+ ? ellnonsingularmultiple(e, P)
+ %2 = [[1, -1], 2]
+ ? e = ellinit("396b2"); P = [35, -198];
+ ? [R,n] = ellnonsingularmultiple(e, P);
+ ? n
+ %5 = 12
+ @eprog
diff --git a/src/functions/elliptic_curves/ellorder b/src/functions/elliptic_curves/ellorder
index 0607d71..53dcd16 100644
--- a/src/functions/elliptic_curves/ellorder
+++ b/src/functions/elliptic_curves/ellorder
@@ -2,27 +2,29 @@ Function: ellorder
 Section: elliptic_curves
 C-Name: ellorder
 Prototype: GGDG
-Help: ellorder(E,z,{o}): order of the point z on the elliptic curve E over Q
- or a finite field, 0 if non-torsion. The parameter o, if present,
- represents a non-zero multiple of the order of z.
+Help: ellorder(E,z,{o}): order of the point z on the elliptic curve E over
+ a number field or a finite field, 0 if non-torsion. The parameter o,
+ if present, represents a non-zero multiple of the order of z.
 Doc: gives the order of the point $z$ on the elliptic
- curve $E$, defined over $\Q$ or a finite field.
- If the curve is defined over $\Q$, return (the impossible value) zero if the
- point has infinite order.
+ curve $E$, defined over a finite field or a number field.
+ Return (the impossible value) zero if the point has infinite order.
  \bprog
  ? E = ellinit([-157^2,0]);  \\ the "157-is-congruent" curve
  ? P = [2,2]; ellorder(E, P)
  %2 = 2
  ? P = ellheegner(E); ellorder(E, P) \\ infinite order
  %3 = 0
+ ? K = nfinit(polcyclo(11,t)); E=ellinit("11a3", K); T = elltors(E);
+ ? ellorder(E, T.gen[1])
+ %5 = 25
  ? E = ellinit(ellfromj(ffgen(5^10)));
  ? ellcard(E)
- %5 = 9762580
+ %7 = 9762580
  ? P = random(E); ellorder(E, P)
- %6 = 4881290
+ %8 = 4881290
  ? p = 2^160+7; E = ellinit([1,2], p);
  ? N = ellcard(E)
- %8 = 1461501637330902918203686560289225285992592471152
+ %9 = 1461501637330902918203686560289225285992592471152
  ? o = [N, factor(N)];
  ? for(i=1,100, ellorder(E,random(E)))
  time = 260 ms.
diff --git a/src/functions/elliptic_curves/ellpadicL b/src/functions/elliptic_curves/ellpadicL
new file mode 100644
index 0000000..6a9d2a7
--- /dev/null
+++ b/src/functions/elliptic_curves/ellpadicL
@@ -0,0 +1,64 @@
+Function: ellpadicL
+Section: elliptic_curves
+C-Name: ellpadicL
+Prototype: GGLD0,L,DGDG
+Help: ellpadicL(E, p, n, {r = 0}, {D}, {char}): returns the value
+  on a character of the derivative of order r of the L-function of
+  the elliptic curve E (twisted by D > 0, if present). For the moment, only
+  the case of the trivial character is implemented
+Doc:
+  The $p$-adic $L$ function is defined on the set of continuous characters
+  of $\text{Gal}(\Q(\mu_{p^{\infty}})/ \Q)$, identified to $\Z_p^*$
+  via the cyclotomic character $\chi_p$ with values in $\overline{Q_p}^*$.
+  Denote by $tau:\Z_p^*\to\Z_p^*$ the Teichm\"uller character.
+
+  When $E$ has good supersingular reduction, the $L$ function takes its
+  values in $\Q_p \otimes H^1_{dR}(E/\Q)$ and satisfies
+  $$(1-p^{-1} F)^{-2} L_p(E, \tau^0)= (L(E,1) / \Omega) \cdot \omega$$
+  where $F$ is the Frobenius, $L(E,1)$ is the value of the complex $L$
+  function at $1$, $\omega$ is the N\'eron differential
+  and $\Omega$ its associated period on $E(\R)$. Here, $\tau^0$ represents
+  the trivial character.
+
+  The derivative is taken at $s=1$ along $\langle\chi_p^s\rangle$.
+  In other words, the function $L_p$ is defined as
+  $\int_{\Z_p^*} d \mu$ for a certain $p$-adic distribution $\mu$ on
+  $\Z_p^*$, and we have
+   $$L_p^{(r)}(E, \tau^0) = \int_{\Z_p^*} \log_p^r(a) d\mu(a).$$
+  The function returns the components of $L_p{(r)}(E,\tau^0)$ in
+  the basis $(\omega, F(\omega))$.
+  \smallskip
+
+  When $E$ has ordinary good reduction, this method only defines
+  the projection of $L_p(E,\tau^0)$ on the $\alpha$-eigenspace,
+  where $\alpha$ is the unit eigenvalue for $F$. This is what the function
+  returns. This value satisfies
+  $$(1- \alpha^{-1})^{-2} L_{p,\alpha}(E,\tau^0)= L(E,1) / \Omega.$$
+
+  \bprog
+  ? cxL(e) = bestappr( ellL1(e,0) / e.omega[1] );
+
+  ? e = ellinit("17a1"); p=3; \\ supersingular
+  ? L = ellpadicL(e,p,4);
+  ? F = [0,-p;1,ellap(e,p)]; \\ Frobenius matrix in the basis (omega,F(omega)
+  ? (1-p^(-1)*F)^-2 * L~ / cxL(e)
+  %4 = [1 + O(3^4), O(3^4)]~
+
+  ? p=5; ap = ellap(e,p); \\ ordinary
+  ? L = ellpadicL(e,p,4);
+  ? al = padicappr(x^2 - ap*x + p, ap + O(p^7))[1];
+  ? (1-al^(-1))^(-2) * L / cxL(e)
+  %8 = 1 + O(5^4)
+
+  ? e = ellinit("116a1"); p=3; \\ supersingular
+  ? L = ellpadicL(e,p,4);
+  ? F = [0,-p; 1,ellap(e,p)];
+  ? (1-p^(-1)*F)^-2*L~ / cxL(e)
+  %12 = [1 + O(3^4), O(3^5)]~
+
+  ? e = ellinit("26b1"); p=3;
+  ? L = ellpadicL(e,p,4);
+  ? F = [0,-p;1,ellap(e,p)];
+  ? (1-p^(-1)*F)^-2*L~ / cxL(e)
+  %16 = [1 + O(3^4), O(3^5)]~
+  @eprog
diff --git a/src/functions/elliptic_curves/ellpadicfrobenius b/src/functions/elliptic_curves/ellpadicfrobenius
new file mode 100644
index 0000000..4899252
--- /dev/null
+++ b/src/functions/elliptic_curves/ellpadicfrobenius
@@ -0,0 +1,27 @@
+Function: ellpadicfrobenius
+Section: elliptic_curves
+C-Name: ellpadicfrobenius
+Prototype: GLL
+Help: ellpadicfrobenius(E,p,n): matrix of the Frobenius at p>2 in the standard
+ basis of H^1_dR(E) to absolute p-adic precision p^n.
+Doc: If $p>2$ is a prime and $E$ is a elliptic curve on $\Q$ with good
+ reduction at $p$, return the matrix of the Frobenius endomorphism $\varphi$ on
+ the crystalline module $D_p(E)= \Q_p \otimes H^1_{dR}(E/\Q)$ with respect to
+ the basis of the given model $(\omega, \eta=x\*\omega)$, where
+ $\omega = dx/(2\*y+a_1\*x+a_3)$ is the invariant differential.
+ The characteristic polynomial of $\varphi$ is $x^2 - a_p\*x + p$.
+ The matrix is computed to absolute $p$-adic precision $p^n$.
+
+ \bprog
+ ? E = ellinit([1,-1,1,0,0]);
+ ? F = ellpadicfrobenius(E,5,3);
+ ? lift(F)
+ %3 =
+ [120 29]
+
+ [ 55  5]
+ ? charpoly(F)
+ %4 = x^2 + O(5^3)*x + (5 + O(5^3))
+ ? ellap(E, 5)
+ %5 = 0
+ @eprog
diff --git a/src/functions/elliptic_curves/ellpadicheight b/src/functions/elliptic_curves/ellpadicheight
new file mode 100644
index 0000000..a98d6d7
--- /dev/null
+++ b/src/functions/elliptic_curves/ellpadicheight
@@ -0,0 +1,65 @@
+Function: ellpadicheight
+Section: elliptic_curves
+C-Name: ellpadicheight0
+Prototype: GGLGDG
+Help:ellpadicheight(E, p,n, P,{Q}): E elliptic curve/Q, P in E(Q),
+ p prime, n an integer; returns the cyclotomic p-adic heights of P.
+ Resp. the value of the associated bilinear form at (P,Q).
+Doc: cyclotomic $p$-adic height of the rational point $P$ on the elliptic curve
+ $E$ (defined over $\Q$), given to $n$ $p$-adic digits.
+ If the argument $Q$ is present, computes the value of the bilinear
+ form $(h(P+Q)-h(P-Q)) / 4$.
+
+ Let $D_{dR}(E) := H^1_{dR}(E) \otimes_\Q \Q_p$ be the $\Q_p$ vector space
+ spanned by $\omega$
+ (invariant differential $dx/(2y+a_1x+a3)$ related to the given model) and
+ $\eta = x \omega$. Then the cyclotomic $p$-adic height associates to
+ $P\in E(\Q)$ an element $f \omega + g\eta$ in $D_{dR}$.
+ This routine returns the vector $[f, g]$ to $n$ $p$-adic digits.
+
+ If $P\in E(\Q)$ is in the kernel of reduction mod $p$ and if its reduction
+ at all finite places is non singular, then $g = -(\log_E P)^2$, where
+ $\log_E$ is the logarithm for the formal group of $E$ at $p$.
+
+ If furthermore the model is of the form $Y^2 = X^3 + a X + b$ and $P = (x,y)$,
+ then
+   $$ f = \log_p(\kbd{denominator}(x)) - 2 \log_p(\sigma(P))$$
+ where $\sigma(P)$ is given by \kbd{ellsigma}$(E,P)$.
+
+ Recall (\emph{Advanced topics in the arithmetic of elliptic
+ curves}, Theorem~3.2) that the local height function over the complex numbers
+ is of the form
+   $$ \lambda(z) = -\log (|\kbd{E.disc}|) / 6 + \Re(z \eta(z)) - 2 \log(
+   \sigma(z). $$
+ (N.B. our normalization for local and global heights is twice that of
+ Silverman's).
+ \bprog
+  ? E = ellinit([1,-1,1,0,0]); P = [0,0];
+  ? ellpadicheight(E,5,4, P)
+  %2 = [3*5 + 5^2 + 2*5^3 + O(5^4), 5^2 + 4*5^4 + O(5^6)]
+  ? E = ellinit("11a1"); P = [5,5]; \\ torsion point
+  ? ellpadicheight(E,19,6, P)
+  %4 = O(19^6)
+  ? E = ellinit([0,0,1,-4,2]); P = [-2,1];
+  ? ellpadicheight(E,3,5, P)
+  %6 = [2*3^2 + 2*3^3 + 3^4 + O(3^5), 2*3^2 + 3^4 + 2*3^5 + 3^6 + O(3^7)]
+  ? ellpadicheight(E,3,5, P, elladd(E,P,P))
+ @eprog
+
+ One can replace the parameter $p$ prime by a vector $[p,[a,b]]$, in which
+ case the routine returns the $p$-adic number $af + bg$.
+
+ When $E$ has good ordinary reduction at $p$, the ``canonical''
+ $p$-adic height is given by
+ \bprog
+ s2 = ellpadics2(E,p,n);
+ ellpadicheight(E, [p,[1,-s2]], n, P)
+ @eprog\noindent Since $s_2$ does not depend on $P$, it is preferable to
+ compute it only once:
+ \bprog
+ ? E = ellinit("5077a1"); p = 5; n = 7;
+ ? s2 = ellpadics2(E,p,n);
+ ? M = ellpadicheightmatrix(E,[p,[1,-s2]], n, E.gen);
+ ? matdet(M)   \\ p-adic regulator
+ %4 = 5 + 5^2 + 4*5^3 + 2*5^4 + 2*5^5 + 5^6 + O(5^7)
+ @eprog
diff --git a/src/functions/elliptic_curves/ellpadicheightmatrix b/src/functions/elliptic_curves/ellpadicheightmatrix
new file mode 100644
index 0000000..97cba86
--- /dev/null
+++ b/src/functions/elliptic_curves/ellpadicheightmatrix
@@ -0,0 +1,14 @@
+Function: ellpadicheightmatrix
+Section: elliptic_curves
+C-Name: ellpadicheightmatrix
+Prototype: GGLG
+Help: ellpadicheightmatrix(E,p,n,v): gives the height-pairing matrix for vector
+ of points v on elliptic curve E.
+Doc: $v$ being a vector of points, this function outputs the Gram matrix of
+ $v$ with respect to the cyclotomic $p$-adic height, given to $n$ $p$-adic
+ digits; in other words, the $(i,j)$ component of the matrix is equal to
+ \kbd{ellpadicheight}$(E,p,n, v[i],v[j]) = [f,g]$.
+
+ See \tet{ellpadicheight}; in particular one can replace the parameter $p$
+ prime by a vector $[p,[a,b]]$, in which case the routine returns the matrix
+ containing the $p$-adic numbers $af + bg$.
diff --git a/src/functions/elliptic_curves/ellpadiclog b/src/functions/elliptic_curves/ellpadiclog
new file mode 100644
index 0000000..fed2197
--- /dev/null
+++ b/src/functions/elliptic_curves/ellpadiclog
@@ -0,0 +1,12 @@
+Function: ellpadiclog
+Section: elliptic_curves
+C-Name: ellpadiclog
+Prototype: GGLG
+Help: ellpadiclog(E,p,n,P): returns the logarithm of P (in the kernel of
+ reduction) to absolute p-adic precision p^n.
+Doc: Given $E$ defined over $K = \Q$ or $\Q_p$ and $P = [x,y]$ on $E(K)$ in the
+ kernel of reduction mod $p$, let $t(P) = -x/y$ be the formal group
+ parameter; this function returns $L(t)$, where $L$ denotes the formal
+ logarithm (mapping  the formal group of $E$  to the additive formal group)
+ attached to the canonical invariant differential:
+ $dL = dx/(2y + a_1x + a_3)$.
diff --git a/src/functions/elliptic_curves/ellpadics2 b/src/functions/elliptic_curves/ellpadics2
new file mode 100644
index 0000000..74ab227
--- /dev/null
+++ b/src/functions/elliptic_curves/ellpadics2
@@ -0,0 +1,28 @@
+Function: ellpadics2
+Section: elliptic_curves
+C-Name: ellpadics2
+Prototype: GGL
+Help: ellpadics2(E,p,n): returns s2 to absolute p-adic precision p^n
+Doc: If $p>2$ is a prime and $E/\Q$ is a elliptic curve with ordinary good
+ reduction at $p$, returns the slope of the unit eigenvector
+ of \kbd{ellpadicfrobenius(E,p,n)}, i.e. the action of Frobenius $\varphi$ on
+ the crystalline module $D_p(E)= \Q_p \otimes H^1_{dR}(E/\Q)$ in the basis of
+ the given model $(\omega, \eta=x\*\omega)$, where $\omega$ is the invariant
+ differential $dx/(2\*y+a_1\*x+a_3)$. In other words, $\eta + s_2\omega$
+ is an eigenvector for the unit eigenvalue of $\varphi$.
+
+ This slope is the unique $c \in 3^{-1}\Z_p$ such that the odd solution
+   $\sigma(t) = t + O(t^2)$ of
+ $$ - d(\dfrac{1}{\sigma} \dfrac{d \sigma}{\omega})
+  = (x(t) + c) \omega$$
+ is in $t\Z_p[[t]]$.
+
+ It is equal to $b_2/12 - E_2/12$ where $E_2$ is the value of the Katz
+ $p$-adic Eisenstein series of weight 2 on $(E,\omega)$. This is
+ used to construct a canonical $p$-adic height when $E$ has good ordinary
+ reduction at $p$ as follows
+ \bprog
+ s2 = ellpadics2(E,p,n);
+ h(E,p,n, P, s2) = ellpadicheight(E, [p,[1,-s2]],n, P);
+ @eprog\noindent Since $s_2$ does not depend on the point $P$, we compute it
+ only once.
diff --git a/src/functions/elliptic_curves/elltors b/src/functions/elliptic_curves/elltors
index 63c5fb5..757f165 100644
--- a/src/functions/elliptic_curves/elltors
+++ b/src/functions/elliptic_curves/elltors
@@ -1,32 +1,20 @@
 Function: elltors
 Section: elliptic_curves
-C-Name: elltors0
-Prototype: GD0,L,
-Help: elltors(E,{flag=0}): torsion subgroup of elliptic curve E: order,
- structure, generators. If flag = 0, use division polynomials; if flag = 1, use
- Lutz-Nagell; if flag = 2, use Doud's algorithm.
+C-Name: elltors
+Prototype: G
+Help: elltors(E): torsion subgroup of elliptic curve E: order, structure,
+ generators.
 Doc:
- if $E$ is an elliptic curve \emph{defined over $\Q$}, outputs the torsion
- subgroup of $E$ as a 3-component vector \kbd{[t,v1,v2]}, where \kbd{t} is the
- order of the torsion group, \kbd{v1} gives the structure of the torsion group
- as a product of cyclic groups (sorted by decreasing order), and \kbd{v2}
- gives generators for these cyclic groups. $E$ must be an \var{ell} structure
- as output by \kbd{ellinit}, defined over $\Q$.
-
+ if $E$ is an elliptic curve defined over a number field or a finite field,
+ outputs the torsion subgroup of $E$ as a 3-component vector \kbd{[t,v1,v2]},
+ where \kbd{t} is the order of the torsion group, \kbd{v1} gives the structure
+ of the torsion group as a product of cyclic groups (sorted by decreasing
+ order), and \kbd{v2} gives generators for these cyclic groups. $E$ must be an
+ \var{ell} structure as output by \kbd{ellinit}.
  \bprog
  ?  E = ellinit([-1,0]);
  ?  elltors(E)
  %1 = [4, [2, 2], [[0, 0], [1, 0]]]
- @eprog
+ @eprog\noindent
  Here, the torsion subgroup is isomorphic to $\Z/2\Z \times \Z/2\Z$, with
  generators $[0,0]$ and $[1,0]$.
-
- If $\fl = 0$, find rational roots of division polynomials.
-
- If $\fl = 1$, use Lutz-Nagell (\emph{much} slower).
-
- If $\fl = 2$, use Doud's algorithm: bound torsion by computing $\#E(\F_p)$
- for small primes of good reduction, then look for torsion points using
- Weierstrass $\wp$ function (and Mazur's classification). For this variant,
- $E$ must be an \var{ell}.
-Variant: Also available is \fun{GEN}{elltors}{GEN E} for \kbd{elltors(E, 0)}.
diff --git a/src/functions/elliptic_curves/ellxn b/src/functions/elliptic_curves/ellxn
new file mode 100644
index 0000000..bff696b
--- /dev/null
+++ b/src/functions/elliptic_curves/ellxn
@@ -0,0 +1,13 @@
+Function: ellxn
+Section: elliptic_curves
+C-Name: ellxn
+Prototype: GLDn
+Help: ellxn(E,n,{v='x}): polynomials [phi_n, (psi_n)^2] in variable v,
+ where x([n]P) = phi_n/(psi_n)^2
+Doc: In standard notation, for any affine point $P = (v,w)$ on the
+ curve $E$, we have
+ $$[n]P = (\phi_n(P)\psi_n(P) : \omega_n(P) : \psi_n(P)^3)$$
+ for some polynomials $\phi_n,\omega_n,\psi_n$ in
+ $\Z[a_1,a_2,a_3,a_4,a_6][v,w]$. This function returns
+ $[\phi_n(P),\psi_n(P)^2]$, which give the numerator and denominator of
+ the abcissa of $[n]P$ and depend only on $v$.
diff --git a/src/functions/elliptic_curves/genus2red b/src/functions/elliptic_curves/genus2red
index 5d713c9..4679be2 100644
--- a/src/functions/elliptic_curves/genus2red
+++ b/src/functions/elliptic_curves/genus2red
@@ -1,21 +1,25 @@
 Function: genus2red
 Section: elliptic_curves
 C-Name: genus2red
-Prototype: GGDG
-Help: genus2red(Q,P,{p}): let Q,P be polynomials with integer coefficients.
+Prototype: GDG
+Help: genus2red(P,{p}): let P be a polynomial with integer coefficients.
  Determines the reduction at p > 2 of the
- (proper, smooth) hyperelliptic curve C/Q: y^2+Qy = P, of genus 2.
+ (proper, smooth) hyperelliptic curve C/Q: y^2 = P, of genus 2.
  (The special fiber X_p of the minimal regular model X of C over Z.)
-Doc: Let $Q,P$ be polynomials with integer coefficients.
+Doc: Let $P$ be a polynomial with integer coefficients.
  Determines the reduction at $p > 2$ of the (proper, smooth) genus~2
- curve $C/\Q$, defined by the hyperelliptic equation $y^2+Qy = P$. (The
+ curve $C/\Q$, defined by the hyperelliptic equation $y^2 = P$. (The
  special fiber $X_p$ of the minimal regular model $X$ of $C$ over $\Z$.)
+ The special syntax \kbd{genus2red}$([P,Q])$ is also allowed, where the
+ polynomials $P$ and $Q$ have integer coefficients, to represent the model
+ $y^2 + Q(x)y = P(x)$.
+
  If $p$ is omitted, determines the reduction type for all (odd) prime
  divisors of the discriminant.
 
- \noindent This function rewritten from an implementation of Liu's algorithm by
- Cohen and Liu (1994), \kbd{genus2reduction-0.3}, see
- \kbd{http://www.math.u-bordeaux1.fr/\til liu/G2R/}.
+ \noindent This function was rewritten from an implementation of Liu's
+ algorithm by Cohen and Liu (1994), \kbd{genus2reduction-0.3}, see
+ \url{http://www.math.u-bordeaux1.fr/~liu/G2R/}.
 
  \misctitle{CAVEAT} The function interface may change: for the
  time being, it returns $[N,\var{FaN}, T, V]$
@@ -30,7 +34,7 @@ Doc: Let $Q,P$ be polynomials with integer coefficients.
 
  \bprog
  ? default(debuglevel, 1);
- ? genus2red(0,x^6 + 3*x^3 + 63, 3)
+ ? genus2red(x^6 + 3*x^3 + 63, 3)
  (potential) stable reduction: [1, []]
  reduction at p: [III{9}] page 184, [3, 3], f = 10
  %1 = [59049, Mat([3, 10]), x^6 + 3*x^3 + 63, [3, [1, []],
diff --git a/src/functions/elliptic_curves/hyperellcharpoly b/src/functions/elliptic_curves/hyperellcharpoly
new file mode 100644
index 0000000..ccbd613
--- /dev/null
+++ b/src/functions/elliptic_curves/hyperellcharpoly
@@ -0,0 +1,15 @@
+Function: hyperellcharpoly
+Section: elliptic_curves
+C-Name: hyperellcharpoly
+Prototype: G
+Help: hyperellcharpoly(X): X being a non-singular hyperelliptic curve defined
+ over a finite field, return the characteristic polynomial of the Frobenius
+ automorphism.  X can be given either by a squarefree polynomial P such that
+ X:y^2=P(x) or by a vector [P,Q] such that X:y^2+Q(x)*y=P(x) and Q^2+4P is
+ squarefree.
+Doc:
+ $X$ being a non-singular hyperelliptic curve defined over a finite field,
+ return the characteristic polynomial of the Frobenius automorphism.
+ $X$ can be given either by a squarefree polynomial P such that $X: y^2 = P(x)$
+ or by a vector $[P,Q]$ such that $X: y^2 + Q(x)\*y = P(x)$ and $Q^2+4\*P$ is
+ squarefree.
diff --git a/src/functions/elliptic_curves/hyperellpadicfrobenius b/src/functions/elliptic_curves/hyperellpadicfrobenius
new file mode 100644
index 0000000..6b6e9a9
--- /dev/null
+++ b/src/functions/elliptic_curves/hyperellpadicfrobenius
@@ -0,0 +1,17 @@
+Function: hyperellpadicfrobenius
+Section: elliptic_curves
+C-Name: hyperellpadicfrobenius
+Prototype: GUL
+Help: hyperellpadicfrobenius(Q,p,n): Q being a  rational polynomial of degree
+ d, return the matrix of the Frobenius at p>=d in the standard
+ basis of H^1_dR(E) to absolute p-adic precision p^n.
+Doc:
+ Let $X$ be the curve defined by $y^2=Q(x)$, where  $Q$ is a polynomial of
+ degree $d$ over $\Q$ and $p\ge d$ a prime such that $X$ has good reduction
+ at $p$ return the matrix of the Frobenius endomorphism $\varphi$ on the
+ crystalline module $D_p(E) = \Q_p \otimes H^1_{dR}(E/\Q)$ with respect to the
+ basis of the given model $(\omega, x\*\omega,\ldots,x^{g-1}\*\omega)$, where
+ $\omega = dx/(2\*y)$ is the invariant differential, where $g$ is the genus of
+ $X$ (either $d=2\*g+1$ or $d=2\*g+2$).  The characteristic polynomial of
+ $\varphi$ is the numerator of the zeta-function of the reduction of the curve
+ $X$ modlo $p$. The matrix is computed to absolute $p$-adic precision $p^n$.
diff --git a/src/functions/gp2c/clone b/src/functions/gp2c/clone
index cb0418d..54f807a 100644
--- a/src/functions/gp2c/clone
+++ b/src/functions/gp2c/clone
@@ -8,4 +8,7 @@ Description:
  (vecsmall):vecsmall              gclone($1)
  (vec):vec                        gclone($1)
  (pol):pol                        gclone($1)
+ (list):list                      gclone($1)
+ (closure):closure                gclone($1)
+ (genstr):genstr                  gclone($1)
  (gen):gen                        gclone($1)
diff --git a/src/functions/gp2c_internal/_cast b/src/functions/gp2c_internal/_cast
index 77ba135..30000ac 100644
--- a/src/functions/gp2c_internal/_cast
+++ b/src/functions/gp2c_internal/_cast
@@ -7,6 +7,7 @@ Description:
  (empty, bptr, small)
  (empty, bool, lg, small)
  (empty, bool, small_int, small)
+ (empty, bool, usmall, small)
  (empty, void, negbool, bool)
  (empty, typ, str, genstr,gen)
  (empty, errtyp, str)
@@ -30,6 +31,7 @@ Description:
  (#negbool):bool       ${1 value not}
  (negbool):bool        !$(1)
  (small_int):bool
+ (usmall):bool
  (small):bool
  (lg):bool:parens      $(1)!=1
  (bptr):bool           *$(1)
@@ -54,14 +56,21 @@ Description:
  (typ):small_int
  (small):small_int
 
+ (bool):usmall
+ (typ):usmall
+ (small):usmall
+
  (bool):small
  (typ):small
  (small_int):small
+ (usmall):small
  (bptr):small           *$(1)
  (int):small            itos($1)
+ (int):usmall           itou($1)
  (#lg):small:parens     ${1 value 1 sub}
  (lg):small:parens      $(1)-1
  (gen):small            gtos($1)
+ (gen):usmall           gtou($1)
 
  (void):int             gen_0
  (-2):int               gen_m2
@@ -71,6 +80,7 @@ Description:
  (2):int                gen_2
  (bool):int             stoi($1)
  (small):int            stoi($1)
+ (usmall):int           utoi($1)
  (mp):int
  (gen):int
 
diff --git a/src/functions/gp2c_internal/_gc_needed b/src/functions/gp2c_internal/_gc_needed
new file mode 100644
index 0000000..101b594
--- /dev/null
+++ b/src/functions/gp2c_internal/_gc_needed
@@ -0,0 +1,4 @@
+Function: _gc_needed
+Class: gp2c_internal
+Description:
+ (pari_sp):bool                gc_needed($1, 1)
diff --git a/src/functions/gp2c_internal/_tovec b/src/functions/gp2c_internal/_tovec
index 3eab566..a64c123 100644
--- a/src/functions/gp2c_internal/_tovec
+++ b/src/functions/gp2c_internal/_tovec
@@ -2,19 +2,21 @@ Function: _tovec
 Class: gp2c_internal
 Help: Create a vector holding the arguments (shallow)
 Description:
- ():vec                  cgetg(1, t_VEC)
- (gen):vec               mkvec($1)
- (gen,gen):vec           mkvec2($1, $2)
- (gen,gen,gen):vec       mkvec3($1, $2, $3)
- (gen,gen,gen,gen):vec   mkvec4($1, $2, $3, $4)
- (gen,...):vec           mkvecn($#, $2)
+ ():vec                      cgetg(1, t_VEC)
+ (gen):vec                   mkvec($1)
+ (gen,gen):vec               mkvec2($1, $2)
+ (gen,gen,gen):vec           mkvec3($1, $2, $3)
+ (gen,gen,gen,gen):vec       mkvec4($1, $2, $3, $4)
+ (gen,gen,gen,gen,gen):vec   mkvec5($1, $2, $3, $4, $5)
+ (gen,...):vec               mkvecn($#, $2)
 
 Function: _tovecprec
 Class: gp2c_internal
 Help: Create a vector holding the arguments and prec (shallow)
 Description:
- ():vec:prec             mkvecs(prec)
- (gen):vec:prec          mkvec2($1, stoi(prec))
- (gen,gen):vec:prec      mkvec3($1, $2, stoi(prec))
- (gen,gen,gen):vec:prec  mkvec4($1, $2, $3, stoi(prec))
- (gen,...):vec:prec      mkvecn(${nbarg 1 add}, $2, stoi(prec))
+ ():vec:prec                mkvecs(prec)
+ (gen):vec:prec             mkvec2($1, stoi(prec))
+ (gen,gen):vec:prec         mkvec3($1, $2, stoi(prec))
+ (gen,gen,gen):vec:prec     mkvec4($1, $2, $3, stoi(prec))
+ (gen,gen,gen,gen):vec:prec mkvec5($1, $2, $3, $4, stoi(prec))
+ (gen,...):vec:prec         mkvecn(${nbarg 1 add}, $2, stoi(prec))
diff --git a/src/functions/gp2c_internal/_typedef b/src/functions/gp2c_internal/_typedef
index 2fe0e0b..726a74b 100644
--- a/src/functions/gp2c_internal/_typedef
+++ b/src/functions/gp2c_internal/_typedef
@@ -3,6 +3,7 @@ Class: gp2c_internal
 Description:
  (C!void)            void
  (C!long)            long
+ (C!ulong)           ulong
  (C!int)             int
  (C!GEN)             GEN
  (C!char*)           char
@@ -28,6 +29,7 @@ Description:
  (negbool)      long
  (bool)         long
  (small_int)    int
+ (usmall)       ulong
  (small)        long
  (int)          GEN
  (real)         GEN
@@ -67,6 +69,7 @@ Description:
  (C!void)       v
  (C!int)        i
  (C!long)       l
+ (C!ulong)      u
  (C!GEN)
 
 Function: _proto_max_args
@@ -81,6 +84,7 @@ Help: Code for argument of a function
 Description:
  (var)          n
  (C!long)       L
+ (C!ulong)      U
  (C!GEN)        G
  (C!char*)      s
 
diff --git a/src/functions/gp2c_internal/_wrap b/src/functions/gp2c_internal/_wrap
index 43f9a19..49dfc44 100644
--- a/src/functions/gp2c_internal/_wrap
+++ b/src/functions/gp2c_internal/_wrap
@@ -5,6 +5,13 @@ Prototype: G
 Description:
   (gen):gen    $1
 
+Function: _wrap_GG
+Class: gp2c_internal
+C-Name: gp_call2
+Prototype: GG
+Description:
+  (gen):gen    $1
+
 Function: _wrap_vG
 Class: gp2c_internal
 C-Name: gp_callvoid
diff --git a/src/functions/linear_algebra/matkerint b/src/functions/linear_algebra/matkerint
index 3c0cde8..d48d517 100644
--- a/src/functions/linear_algebra/matkerint
+++ b/src/functions/linear_algebra/matkerint
@@ -3,20 +3,12 @@ Section: linear_algebra
 C-Name: matkerint0
 Prototype: GD0,L,
 Help: matkerint(x,{flag=0}): LLL-reduced Z-basis of the kernel of the matrix
- x with integral entries. flag is optional, and may be set to 0: default,
- uses LLL, 1: uses matrixqz (much slower).
+ x with integral entries. flag is deprecated, and may be set to 0 or 1
+ for backward compatibility.
 Doc: gives an \idx{LLL}-reduced $\Z$-basis
- for the lattice equal to the kernel of the matrix $x$ as columns of the
- matrix $x$ with integer entries (rational entries are not permitted).
+ for the lattice equal to the kernel of the matrix $x$ with rational entries.
 
- If $\fl=0$, uses an integer LLL algorithm.
+ \fl is deprecated, kept for backward compatibility.
 
- If $\fl=1$, uses $\kbd{matrixqz}(x,-2)$. Many orders of magnitude slower
- than the default: never use this.
-
-Variant: See also \fun{GEN}{kerint}{GEN x} ($\fl=0$), which is a trivial
- wrapper around
- \bprog
- ZM_lll(ZM_lll(x, 0.99, LLL_KER), 0.99, LLL_INPLACE);
- @eprog\noindent Remove the outermost \kbd{ZM\_lll} if LLL-reduction is not
- desired (saves time).
+Variant: Use directly \fun{GEN}{kerint}{GEN x} if $x$ is known to have
+ integer entries, and \tet{Q_primpart} first otherwise.
diff --git a/src/functions/linear_algebra/matqr b/src/functions/linear_algebra/matqr
index 1bea007..e7a030a 100644
--- a/src/functions/linear_algebra/matqr
+++ b/src/functions/linear_algebra/matqr
@@ -14,8 +14,8 @@ Doc: returns $[Q,R]$, the \idx{QR-decomposition} of the square invertible
  \bprog
    [Q,R] = matqr(M);
    [q,r] = matqr(M, 1);
- @eprog\noindent then $r = R$ and \kbd{mathouseholder}$(q, M)$ is $R$;
- furthermore
+ @eprog\noindent then $r = R$ and \kbd{mathouseholder}$(q, M)$ is
+ (close to) $R$; furthermore
  \bprog
    mathouseholder(q, matid(#M)) == Q~
  @eprog\noindent the inverse of $Q$. This function raises an error if the
diff --git a/src/functions/linear_algebra/qfparam b/src/functions/linear_algebra/qfparam
new file mode 100644
index 0000000..bbf6ac3
--- /dev/null
+++ b/src/functions/linear_algebra/qfparam
@@ -0,0 +1,31 @@
+Function: qfparam
+Section: linear_algebra
+C-Name: qfparam
+Prototype: GGD0,L,
+Help: qfparam(G, sol, {flag = 0}):
+ coefficients of binary quadratic forms that parametrize the
+ solutions of the ternary quadratic form G, using the particular
+ solution sol.
+Doc: coefficients of binary quadratic forms that parametrize the
+ solutions of the ternary quadratic form $G$, using the particular
+ solution~\var{sol}.
+ \fl is optional and can be 1, 2, or 3, in which case the \fl-th form is
+ reduced. The default is \fl=0 (no reduction).
+ \bprog
+ ? G = [1,0,0;0,1,0;0,0,-34];
+ ? M = qfparam(G, qfsolve(G))
+ %2 =
+ [ 3 -10 -3]
+
+ [-5  -6  5]
+
+ [ 1   0  1]
+ @eprog
+ Indeed, the solutions can be parametrized as
+ $$(3x^2 - 10xy - 3y^2)^2  + (-5x^2 - 6xy + 5y^2)^2 -34(x^2 + y^2)^2 = 0.$$
+ \bprog
+ ? v = y^2 * M*[1,x/y,(x/y)^2]~
+ %3 = [3*x^2 - 10*y*x - 3*y^2, -5*x^2 - 6*y*x + 5*y^2, -x^2 - y^2]~
+ ? v~*G*v
+ %4 = 0
+ @eprog
diff --git a/src/functions/linear_algebra/qfsolve b/src/functions/linear_algebra/qfsolve
new file mode 100644
index 0000000..34d3be6
--- /dev/null
+++ b/src/functions/linear_algebra/qfsolve
@@ -0,0 +1,26 @@
+Function: qfsolve
+Section: linear_algebra
+C-Name: qfsolve
+Prototype: G
+Help: qfsolve(G): solve over Q the quadratic equation X^t G X = 0, where
+ G is a symmetric matrix.
+Doc: Given a square symmetric matrix $G$ of dimension $n \geq 1$, solve over
+ $\Q$ the quadratic equation $X^tGX = 0$. The matrix $G$ must have rational
+ coefficients. The solution might be a single non-zero vector (vectorv) or a
+ matrix (whose columns generate a totally isotropic subspace).
+
+ If no solution exists, returns an integer, that can be a prime $p$ such that
+ there is no local solution at $p$, or $-1$ if there is no real solution,
+ or $-2$ if $n = 2$ and $-\det G$ is positive but not a square (which implies
+ there is a real solution, but no local solution at some $p$ dividing $\det G$).
+ \bprog
+ ? G = [1,0,0;0,1,0;0,0,-34];
+ ? qfsolve(G)
+ %1 = [-3, -5, 1]~
+ ? qfsolve([1,0; 0,2])
+ %2 = -1   \\ no real solution
+ ? qfsolve([1,0,0;0,3,0; 0,0,-2])
+ %3 = 3    \\ no solution in Q_3
+ ? qfsolve([1,0; 0,-2])
+ %4 = -2   \\ no solution, n = 2
+ @eprog
diff --git a/src/functions/linear_algebra/vecsearch b/src/functions/linear_algebra/vecsearch
index 7eb6510..635a168 100644
--- a/src/functions/linear_algebra/vecsearch
+++ b/src/functions/linear_algebra/vecsearch
@@ -10,9 +10,9 @@ Doc: determines whether $x$ belongs to the sorted vector or list $v$: return
  $v$.
 
  If the comparison function cmpf is omitted, we assume that $v$ is sorted in
- increasing order, according to the standard comparison function $<$, thereby
- restricting the possible types for $x$ and the elements of $v$ (integers,
- fractions or reals).
+ increasing order, according to the standard comparison function \kbd{lex},
+ thereby restricting the possible types for $x$ and the elements of $v$
+ (integers, fractions, reals, and vectors of such).
 
  If \kbd{cmpf} is present, it is understood as a comparison function and we
  assume that $v$ is sorted according to it, see \tet{vecsort} for how to
diff --git a/src/functions/linear_algebra/vecsum b/src/functions/linear_algebra/vecsum
index 0aed1f5..0f3ab4d 100644
--- a/src/functions/linear_algebra/vecsum
+++ b/src/functions/linear_algebra/vecsum
@@ -2,5 +2,12 @@ Function: vecsum
 Section: linear_algebra
 C-Name: vecsum
 Prototype: G
-Help: vecsum(v): return the sum of the component of the vector v
-Doc: return the sum of the component of the vector $v$
+Help: vecsum(v): return the sum of the components of the vector v
+Doc: return the sum of the components of the vector $v$. Return $0$ on an
+ empty vector.
+ \bprog
+ ? vecsum([1,2,3])
+ %1 = 6
+ ? vecsum([])
+ %2 = 0
+ @eprog
diff --git a/src/functions/modular_forms/msatkinlehner b/src/functions/modular_forms/msatkinlehner
new file mode 100644
index 0000000..8d95ab8
--- /dev/null
+++ b/src/functions/modular_forms/msatkinlehner
@@ -0,0 +1,24 @@
+Function: msatkinlehner
+Section: modular_forms
+C-Name: msatkinlehner
+Prototype: GLDG
+Help: msatkinlehner(M,Q,{H}): Let M be a full modular symbol space of level N,
+ as given by msinit, let Q | N, (Q,N/Q) = 1, and let H be a subspace stable
+ under the Atkin-Lehner involution w_Q. Return the matrix of w_Q
+ acting on H (M if omitted).
+Doc: Let $M$ be a full modular symbol space of level $N$,
+ as given by \kbd{msinit}, let $Q \mid N$, $(Q,N/Q) = 1$,
+ and let $H$ be a subspace stable under the Atkin-Lehner involution $w_Q$.
+ Return the matrix of $w_Q$ acting on $H$ ($M$ if omitted).
+ \bprog
+ ? M = msinit(36,2); \\ M_2(Gamma_0(36))
+ ? w = msatkinlehner(M,4); w^2 == 1
+ %2 = 1
+ ? #w   \\ involution acts on a 13-dimensional space
+ %3 = 13
+ ? M = msinit(36,2, -1); \\ M_2(Gamma_0(36))^-
+ ? w = msatkinlehner(M,4); w^2 == 1
+ %5 = 1
+ ? #w
+ %6 = 4
+ @eprog
diff --git a/src/functions/modular_forms/mscuspidal b/src/functions/modular_forms/mscuspidal
new file mode 100644
index 0000000..e068319
--- /dev/null
+++ b/src/functions/modular_forms/mscuspidal
@@ -0,0 +1,39 @@
+Function: mscuspidal
+Section: modular_forms
+C-Name: mscuspidal
+Prototype: GD0,L,
+Help: mscuspidal(M, {flag=0}): M being a full modular symbol space, as given
+ by msinit, return its cuspidal part S. If flag = 1, return [S,E] its
+ decomposition into Eisenstein and cuspidal parts
+Doc:
+ $M$ being a full modular symbol space, as given by \kbd{msinit},
+ return its cuspidal part $S$. If $\fl = 1$, return
+ $[S,E]$ its decomposition into cuspidal and Eisenstein parts.
+
+ A subspace is given by a structure allowing quick projection and
+ restriction of linear operators; its first component is
+ a matrix with integer coefficients whose columns form a $\Q$-basis of
+ the subspace.
+ \bprog
+ ? M = msinit(2,8, 1); \\ M_8(Gamma_0(2))^+
+ ? [S,E] = mscuspidal(M, 1);
+ ? E[1]  \\ 2-dimensional
+ %3 =
+ [0 -10]
+
+ [0 -15]
+
+ [0  -3]
+
+ [1   0]
+
+ ? S[1]  \\ 1-dimensional
+ %4 =
+ [ 3]
+
+ [30]
+
+ [ 6]
+
+ [-8]
+ @eprog
diff --git a/src/functions/modular_forms/mseisenstein b/src/functions/modular_forms/mseisenstein
new file mode 100644
index 0000000..2705fe4
--- /dev/null
+++ b/src/functions/modular_forms/mseisenstein
@@ -0,0 +1,31 @@
+Function: mseisenstein
+Section: modular_forms
+C-Name: mseisenstein
+Prototype: G
+Help: mseisenstein(M): M being a full modular symbol space, as given by msinit,
+ return its Eisenstein subspace
+Doc:
+ $M$ being a full modular symbol space, as given by \kbd{msinit},
+ return its Eisenstein subspace.
+ A subspace is given by a structure allowing quick projection and
+ restriction of linear operators; its first component is
+ a matrix with integer coefficients whose columns form a $\Q$-basis of
+ the subspace.
+ This is the same basis as given by the second component of
+ \kbd{mscuspidal}$(M, 1)$.
+ \bprog
+ ? M = msinit(2,8, 1); \\ M_8(Gamma_0(2))^+
+ ? E = mseisenstein(M);
+ ? E[1]  \\ 2-dimensional
+ %3 =
+ [0 -10]
+
+ [0 -15]
+
+ [0  -3]
+
+ [1   0]
+
+ ? E == mscuspidal(M,1)[2]
+ %4 = 1
+ @eprog
diff --git a/src/functions/modular_forms/mseval b/src/functions/modular_forms/mseval
new file mode 100644
index 0000000..400df9c
--- /dev/null
+++ b/src/functions/modular_forms/mseval
@@ -0,0 +1,41 @@
+Function: mseval
+Section: modular_forms
+C-Name: mseval
+Prototype: GGDG
+Help: mseval(M,s,{p}): M being a full modular symbol space, as given by
+ msinit, s being a modular symbol from M and p being a path between two
+ elements in P^1(Q), return s(p).
+Doc: Let $\Delta:=\text{Div}^0(\P^1 (\Q))$.
+ Let $M$ be a full modular symbol space, as given by \kbd{msinit},
+ let $s$ be a modular symbol from $M$, i.e. an element
+ of $\text{Hom}_G(\Delta, V)$, and let $p=[a,b] \in \Delta$ be a path between
+ two elements in $\P^1(\Q)$, return $s(p)\in V$. The path extremities $a$ and
+ $b$ may be given as \typ{INT}, \typ{FRAC} or $\kbd{oo} = (1:0)$.
+ The symbol $s$ is either
+
+ \item a \typ{COL} coding an element of a modular symbol subspace in terms of
+ the fixed basis of $\text{Hom}_G(\Delta,V)$ chosen in $M$;
+
+ \item a \typ{VEC} $(v_i)$ of elements of $V$, where the $v_i = s(g_i)$ give
+ the image of the generators $g_i$ of $\Delta$, see \tet{mspathgens}.
+ We assume that $s$ is a proper symbol, i.e.~that the $v_i$ satisfy
+ the \kbd{mspathgens} relations.
+
+ If $p$ is omitted, convert the symbol $s$ to the second form: a vector of
+ the $s(g_i)$.
+ \bprog
+ ? M = msinit(2,8,1); \\ M_8(Gamma_0(2))^+
+ ? g = mspathgens(M)[1]
+ %2 = [[+oo, 0], [0, 1]]
+ ? N = msnew(M)[1]; \\ Q-basis of new subspace
+ ? s = N[,1]         \\ t_COL representation
+ %4 = [3, 30, 6, -8]~
+ ? S = mseval(M, s)   \\ t_VEC representation
+ %5 = [64*x^6-272*x^4+136*x^2-8, 384*x^5+960*x^4+192*x^3-672*x^2-432*x-72]
+ ? mseval(M,s, g[1])
+ %6 = 64*x^6 - 272*x^4 + 136*x^2 - 8
+ ? mseval(M,S, g[1])
+ %6 = 64*x^6 - 272*x^4 + 136*x^2 - 8
+ @eprog\noindent Note that the symbol should have values in
+ $V = \Q[x,y]_{k-2}$, we return the de-homogenized values corresponding to $y
+ = 1$ instead.
diff --git a/src/functions/modular_forms/msfromell b/src/functions/modular_forms/msfromell
new file mode 100644
index 0000000..f3aae52
--- /dev/null
+++ b/src/functions/modular_forms/msfromell
@@ -0,0 +1,34 @@
+Function: msfromell
+Section: modular_forms
+C-Name: msfromell
+Prototype: GD1,L,
+Help: msfromell(E, {sign=1}): return the [M, x], where M is msinit(N,2)
+ and x is the modular symbol in M associated to the elliptic curve E/Q.
+Doc: Let $E/\Q$ be an elliptic curve of conductor $N$. Return the (cuspidal,
+ new) modular symbol $x^+$ in $H^1_c(X_0(N),\Q)^+$ (resp.~$x^-$ in
+ $H^1_c(X_0(N),\Q)^-$ if $\var{sign} = -1$) associated to
+ $E$. For all primes $p$ not dividing $N$ we have
+ $T_p(x^\pm) =  a_p x^\pm$, where $a_p = p+1-\#E(\F_p)$.
+ This defines a unique symbol up to multiplication by a constant
+ and we normalize it so that the associated $p$-adic measure yields the
+ $p$-adic $L$-function. Namely, we have
+ $$ x^{\pm}([0]-[\infty]) = L(E,1) / \Omega,$$
+ for $\Omega$ the real period of $E$ (which fixes $x^{\pm}$ unless $L(E,1)=0$).
+ Furthermore, for all odd fundamental discriminants $d$ coprime to $N$ such
+ that $\var{sign}\cdot d > 0$ and $L(E^{(d)},1) \neq 0$, we also have
+ $$\sum_{0\leq a<|d|} (d|a) x^{\pm}([a/|d|]-[\infty])
+    = L(E^{(d)},1) / \Omega_d,$$
+ where $(d|a)$ is the Kronecker symbol and $\Omega_d$ is the real
+ period of the twist $E^{(d)}$.
+
+ This function returns the pair $[M, x]$, where $M$ is
+ \kbd{msinit}$(N,2)$ and $x$ is $x^\pm$ as a \typ{COL} (in terms
+ of the fixed basis of $\text{Hom}_G(\Delta,\Q)$ chosen in $M$).
+ \bprog
+ ? E=ellinit([0,-1,1,-10,-20]);  \\ X_0(11)
+ ? [M,xpm]= msfromell(E,1);
+ ? xpm
+ %3 = [1/5, -1/2, -1/2]~
+ ? p = 101; (mshecke(M,p) - ellap(E,p))*xpm
+ %4 = [0, 0, 0]~ \\ true at all primes
+ @eprog
diff --git a/src/functions/modular_forms/mshecke b/src/functions/modular_forms/mshecke
new file mode 100644
index 0000000..c883a5c
--- /dev/null
+++ b/src/functions/modular_forms/mshecke
@@ -0,0 +1,41 @@
+Function: mshecke
+Section: modular_forms
+C-Name: mshecke
+Prototype: GLDG
+Help: mshecke(M,p,{H}): M being a full modular symbol space, as given by msinit,
+ p being a prime number, and H being a Hecke-stable subspace (M if omitted),
+ return the matrix of T_p acting on H (U_p if p divides the level).
+Doc: $M$ being a full modular symbol space, as given by \kbd{msinit},
+ $p$ being a prime number, and $H$ being a Hecke-stable subspace ($M$ if
+ omitted) return the matrix of $T_p$ acting on $H$
+ ($U_p$ if $p$ divides $N$). Result is undefined if $H$ is not stable
+ by $T_p$ (resp.~$U_p$).
+ \bprog
+ ? M = msinit(11,2); \\ M_2(Gamma_0(11))
+ ? T2 = mshecke(M,2)
+ %2 =
+ [3  0  0]
+
+ [1 -2  0]
+
+ [1  0 -2]
+ ? M = msinit(11,2, 1); \\ M_2(Gamma_0(11))^+
+ ? T2 = mshecke(M,2)
+ %4 =
+ [ 3  0]
+
+ [-1 -2]
+
+ ? N = msnew(M)[1]; \\ Q-basis of new cuspidal subspace
+ %5 =
+ [ 0]
+
+ [-1]
+
+ [-1]
+ ? p = 1009; mshecke(M, p, N) \\ action of T_1009 on N
+ %6 =
+ [-10]
+ ? ellap(ellinit("11a1"), p)
+ %7 = -10
+ @eprog
diff --git a/src/functions/modular_forms/msinit b/src/functions/modular_forms/msinit
new file mode 100644
index 0000000..258e296
--- /dev/null
+++ b/src/functions/modular_forms/msinit
@@ -0,0 +1,23 @@
+Function: msinit
+Section: modular_forms
+C-Name: msinit
+Prototype: GGD0,L,
+Help: msinit(G, V, {sign=0}): given G a finite index subgroup of SL(2,Z)
+ and a finite dimensional representation V of GL(2,Q), creates a space of
+ modular symbols, the G-module Hom_G(Div^0(P^1 Q), V). This is canonically
+ isomorphic to H^1_c(X(G), V), and allows to compute modular forms for G.
+ If sign is present and non-zero, it must be +1 or -1 and we consider
+ the subspace defined by Ker (Sigma - sign), where Sigma is induced by
+ [-1,0;0,1]. Currently the only supported groups are the Gamma_0(N), coded by
+ the integer N. The only supported representation is V_k = Q[X,Y]_{k-2}, coded
+ by the integer k >= 2.
+Doc: given $G$ a finite index subgroup of $\text{SL}(2,\Z)$
+ and a finite dimensional representation $V$ of $\text{GL}(2,\Q)$, creates a
+ space of modular symbols, the $G$-module $\text{Hom}_G(\text{Div}^0(\P^1
+ (\Q)), V)$. This is canonically isomorphic to $H^1_c(X(G), V)$, and allows to
+ compute modular forms for $G$. If \emph{sign} is present and non-zero, it
+ must be $\pm1$ and we consider the subspace defined by $\text{Ker} (\sigma -
+ \var{sign})$, where $\sigma$ is induced by \kbd{[-1,0;0,1]}. Currently the
+ only supported groups are the $\Gamma_0(N)$, coded by the integer $N > 1$.
+ The only supported representation is $V_k = \Q[X,Y]_{k-2}$, coded by the
+ integer $k \geq 2$.
diff --git a/src/functions/modular_forms/msissymbol b/src/functions/modular_forms/msissymbol
new file mode 100644
index 0000000..ab87f4f
--- /dev/null
+++ b/src/functions/modular_forms/msissymbol
@@ -0,0 +1,26 @@
+Function: msissymbol
+Section: modular_forms
+C-Name: msissymbol
+Prototype: lGG
+Help: msissymbol(M,s): M being a full modular symbol space, as given by msinit,
+ check whether s is a modular symbol associated to M
+Doc:
+ $M$ being a full modular symbol space, as given by \kbd{msinit},
+ check whether $s$ is a modular symbol associated to $M$.
+ \bprog
+ ? M = msinit(7,8, 1); \\ M_8(Gamma_0(7))^+
+ ? N = msnew(M)[1];
+ ? s = N[,1];
+ ? msissymbol(M, s)
+ %4 = 1
+ ? S = mseval(M,s);
+ ? msissymbol(M, S)
+ %6 = 1
+ ? [g,R] = mspathgens(M); g
+ %7 = [[+oo, 0], [0, 1/2], [1/2, 1]]
+ ? #R  \\ 3 relations among the generators g_i
+ %8 = 3
+ ? T = S; T[3]++; \\ randomly perturb S(g_3)
+ ? msissymbol(M, T)
+ %10 = 0  \\ no longer satisfies the relations
+ @eprog
diff --git a/src/functions/modular_forms/msnew b/src/functions/modular_forms/msnew
new file mode 100644
index 0000000..a75b4db
--- /dev/null
+++ b/src/functions/modular_forms/msnew
@@ -0,0 +1,18 @@
+Function: msnew
+Section: modular_forms
+C-Name: msnew
+Prototype: G
+Help: msnew(M): M being a full modular symbol space, as given by msinit,
+ return its new cuspidal subspace
+Doc:
+ $M$ being a full modular symbol space, as given by \kbd{msinit},
+ return the \emph{new} part of its cuspidal subspace. A subspace is given by
+ a structure allowing quick projection and restriction of linear operators;
+ its first component is a matrix with integer coefficients whose columns form
+ a $\Q$-basis of the subspace.
+ \bprog
+ ? M = msinit(11,8, 1); \\ M_8(Gamma_0(11))^+
+ ? N = msnew(M);
+ ? #N[1]  \\ 6-dimensional
+ %3 = 6
+ @eprog
diff --git a/src/functions/modular_forms/mspathgens b/src/functions/modular_forms/mspathgens
new file mode 100644
index 0000000..2fd7436
--- /dev/null
+++ b/src/functions/modular_forms/mspathgens
@@ -0,0 +1,50 @@
+Function: mspathgens
+Section: modular_forms
+C-Name: mspathgens
+Prototype: G
+Help: mspathgens(M): M being a full modular symbol space, as given by
+ msinit, return a set of Z[G]-generators for Div^0(P^1 Q). The output
+ is [g,R], where g is a minimal system of generators and R the vector of
+ Z[G]-relations between the given generators.
+Doc: Let $\Delta:=\text{Div}^0(\P^1(\Q))$.
+ Let $M$ being a full modular symbol space, as given by \kbd{msinit},
+ return a set of $\Z[G]$-generators for $\Delta$. The output
+ is $[g,R]$, where $g$ is a minimal system of generators and $R$
+ the vector of $\Z[G]$-relations between the given generators. A
+ relation is coded by a vector of pairs $[a_i,i]$ with $a_i\in \Z[G]$
+ and $i$ the index of a generator, so that $\sum_i a_i g[i] = 0$.
+
+ An element $[v]-[u]$ in $\Delta$ is coded by the ``path'' $[u,v]$,
+ where \kbd{oo} denotes the point at infinity $(1:0)$ on the projective
+ line.
+ An element of $\Z[G]$ is coded by a ``factorization matrix'': the first
+ column contains distinct elements of $G$, and the second integers:
+ \bprog
+ ? M = msinit(11,8); \\ M_8(Gamma_0(11))
+ ? [g,R] = mspathgens(M);
+ ? g
+ %3 = [[+oo, 0], [0, 1/3], [1/3, 1/2]] \\ 3 paths
+ ? #R  \\ a single relation
+ %4 = 1
+ ? r = R[1]; #r \\ ...involving all 3 generators
+ %5 = 3
+ ? r[1]
+ %6 = [[1, 1; [1, 1; 0, 1], -1], 1]
+ ? r[2]
+ %7 = [[1, 1; [7, -2; 11, -3], -1], 2]
+ ? r[3]
+ %8 = [[1, 1; [8, -3; 11, -4], -1], 3]
+ @eprog\noindent
+ The given relation is of the form $\sum_i (1-\gamma_i) g_i = 0$, with
+ $\gamma_i\in \Gamma_0(11)$. There will always be a single relation involving
+ all generators (corresponding to a round trip along all cusps), then
+ relations involving a single generator (corresponding to $2$ and $3$-torsion
+ elements in the group:
+ \bprog
+ ? M = msinit(2,8); \\ M_8(Gamma_0(2))
+ ? [g,R] = mspathgens(M);
+ ? g
+ %3 = [[+oo, 0], [0, 1]]
+ @eprog\noindent
+ Note that the output depends only on the group $G$, not on the
+ representation $V$.
diff --git a/src/functions/modular_forms/mspathlog b/src/functions/modular_forms/mspathlog
new file mode 100644
index 0000000..fe29a4e
--- /dev/null
+++ b/src/functions/modular_forms/mspathlog
@@ -0,0 +1,35 @@
+Function: mspathlog
+Section: modular_forms
+C-Name: mspathlog
+Prototype: GG
+Help: mspathlog(M,p): M being a full modular symbol space, as given by
+ msinit and p being a path between two elements in P^1(Q), return (p_i)
+ in Z[G] such that p = \sum p_i g_i, and the g_i are fixed Z[G]-generators
+ for Div^0(P^1 Q), see mspathgens.
+Doc: Let $\Delta:=\text{Div}^0(\P^1(\Q))$.
+ Let $M$ being a full modular symbol space, as given by \kbd{msinit},
+ encoding fixed $\Z[G]$-generators $(g_i)$ of $\Delta$ (see \tet{mspathgens}).
+ A path $p=[a,b]$ between two elements in $\P^1(\Q)$ corresponds to
+ $[b]-[a]\in \Delta$. The path extremities $a$ and $b$ may be given as
+ \typ{INT}, \typ{FRAC} or $\kbd{oo} = (1:0)$.
+
+ Returns $(p_i)$ in $\Z[G]$ such that $p = \sum_i p_i g_i$.
+ \bprog
+ ? M = msinit(2,8); \\ M_8(Gamma_0(2))
+ ? [g,R] = mspathgens(M);
+ ? g
+ %3 = [[+oo, 0], [0, 1]]
+ ? p = mspathlog(M, [1/2,2/3]);
+ ? p[1]
+ %6 =
+ [[1, 0; 2, 1] 1]
+
+ ? p[2]
+ %7 =
+ [  [1, 0; 0, 1] 1]
+
+ [[3, -1; 4, -1] 1]
+
+ @eprog\noindent
+ Note that the output depends only on the group $G$, not on the
+ representation $V$.
diff --git a/src/functions/modular_forms/msqexpansion b/src/functions/modular_forms/msqexpansion
new file mode 100644
index 0000000..16b9dce
--- /dev/null
+++ b/src/functions/modular_forms/msqexpansion
@@ -0,0 +1,25 @@
+Function: msqexpansion
+Section: modular_forms
+C-Name: msqexpansion
+Prototype: GGDP
+Help: msqexpansion(M,projH,{B = seriesprecision}): M being a full modular
+ symbol space, as given by msinit, and projH being a projector on a
+ Hecke-simple subspace, return the Fourier coefficients [a_n, n <= B]
+ of the corresponding normalized newform. If B omitted, use seriesprecision
+Doc:
+ $M$ being a full modular symbol space, as given by \kbd{msinit},
+ and \var{projH} being a projector on a Hecke-simple subspace (as given
+ by \tet{mssplit}), return the Fourier coefficients $a_n$, $n\leq B$ of the
+ corresponding normalized newform. If $B$ is omitted, use
+ \kbd{seriesprecision}.
+
+ This function uses a naive $O(B^2 d^3)$
+ algorithm, where $d = O(kN)$ is the dimension of $M_k(\Gamma_0(N))$.
+ \bprog
+ ? M = msinit(11,2, 1); \\ M_2(Gamma_0(11))^+
+ ? L = mssplit(M, msnew(M));
+ ? msqexpansion(M,L[1], 20)
+ %3 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2, 1, -2, 4, 4, -1, -4, -2, 4, 0, 2]
+ ? ellan(ellinit("11a1"), 20)
+ %4 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2, 1, -2, 4, 4, -1, -4, -2, 4, 0, 2]
+ @eprog
diff --git a/src/functions/modular_forms/mssplit b/src/functions/modular_forms/mssplit
new file mode 100644
index 0000000..d98e383
--- /dev/null
+++ b/src/functions/modular_forms/mssplit
@@ -0,0 +1,29 @@
+Function: mssplit
+Section: modular_forms
+C-Name: mssplit
+Prototype: GG
+Help: mssplit(M,H): M being a full modular symbol space, as given by msinit,
+ and H being a subspace, split H into Hecke-simple subspaces.
+Doc:
+ $M$ being a full modular symbol space, as given by \kbd{msinit}$(N,k,1)$
+ or $\kbd{msinit}(N,k,-1)$
+ and $H$ being a Hecke-stable subspace of \kbd{msnew}$(M)$, split $H$ into
+ Hecke-simple subspaces.
+ A subspace is given by a structure allowing quick projection and restriction
+ of linear operators; its first component is a matrix with integer
+ coefficients whose columns form a $\Q$-basis of the subspace.
+ \bprog
+ ? M = msinit(11,8, 1); \\ M_8(Gamma_0(11))^+
+ ? L = mssplit(M, msnew(M));
+ ? #L
+ %3 = 2
+ ? f = msqexpansion(M,L[1],5); f[1].mod
+ %4 = x^2 + 8*x - 44
+ ? lift(f)
+ %5 = [1, x, -6*x - 27, -8*x - 84, 20*x - 155]
+ ? g = msqexpansion(M,L[2],5); g[1].mod
+ %6 = x^4 - 558*x^2 + 140*x + 51744
+ @eprog\noindent To a Hecke-simple subspace corresponds an orbit of
+ (normalized) newforms, defined over a number field. In the above example,
+ we printed the polynomials defining the said fields, as well as the first
+ 5 Fourier coefficients (at the infinite cusp) of one such form.
diff --git a/src/functions/modular_forms/msstar b/src/functions/modular_forms/msstar
new file mode 100644
index 0000000..cd14628
--- /dev/null
+++ b/src/functions/modular_forms/msstar
@@ -0,0 +1,16 @@
+Function: msstar
+Section: modular_forms
+C-Name: msstar
+Prototype: GDG
+Help: msstar(M,{H}): M being a full modular symbol space,
+ as given by msinit, return the matrix of the * involution, induced by
+ complex conjugation, acting on the (stable) subspace H (M if omitted).
+Doc: $M$ being a full modular symbol space, as given by \kbd{msinit},
+ return the matrix of the \kbd{*} involution, induced by complex conjugation,
+ acting on the (stable) subspace $H$ ($M$ if omitted).
+ \bprog
+ ? M = msinit(11,2); \\ M_2(Gamma_0(11))
+ ? w = msstar(M);
+ ? w^2 == 1
+ %3 = 1
+ @eprog
diff --git a/src/functions/number_fields/bnrgaloisapply b/src/functions/number_fields/bnrgaloisapply
new file mode 100644
index 0000000..9d5b410
--- /dev/null
+++ b/src/functions/number_fields/bnrgaloisapply
@@ -0,0 +1,10 @@
+Function: bnrgaloisapply
+Section: number_fields
+C-Name: bnrgaloisapply
+Prototype: GGG
+Help: bnrgaloisapply(bnr, mat, H): apply the automorphism given by its matrix
+ mat to the cngruence subgroup H given as a HNF matrix. The matrix mat can be
+ computed with bnrgaloismatrix
+Doc: apply the automorphism given by its matrix \var{mat} to the congruence
+ subgroup $H$ given as a HNF matrix.
+ The matrix \var{mat} can be computed with \tet{bnrgaloismatrix}.
diff --git a/src/functions/number_fields/bnrgaloismatrix b/src/functions/number_fields/bnrgaloismatrix
new file mode 100644
index 0000000..740241a
--- /dev/null
+++ b/src/functions/number_fields/bnrgaloismatrix
@@ -0,0 +1,20 @@
+Function: bnrgaloismatrix
+Section: number_fields
+C-Name: bnrgaloismatrix
+Prototype: GG
+Help: bnrgaloismatrix(bnr,aut): return the matrix of the action of the
+ automorphism aut of the base field bnf.nf on the generators of the ray class
+ field bnr.gen. aut can be given as a polynomial, or a vector of automorphisms
+ or a galois group as output by galoisinit, in which case a vector of matrices
+ is returned (in the later case, only for the generators aut.gen).
+
+Doc: return the matrix of the action of the automorphism \var{aut} of the base
+ field \kbd{bnf.nf} on the generators of the ray class field \kbd{bnr.gen}.
+ \var{aut} can be given as a polynomial, an algebraic number, or a vector of
+ automorphisms or a Galois group as output by \kbd{galoisinit}, in which case a
+ vector of matrices is returned (in the later case, only for the generators
+ \kbd{aut.gen}).
+
+ See \kbd{bnrisgalois} for an example.
+Variant: When $aut$ is a polynomial or an algebraic number,
+ \fun{GEN}{bnrautmatrix}{GEN bnr, GEN aut} is available.
diff --git a/src/functions/number_fields/bnrinit b/src/functions/number_fields/bnrinit
index 89e6429..0263dde 100644
--- a/src/functions/number_fields/bnrinit
+++ b/src/functions/number_fields/bnrinit
@@ -39,5 +39,5 @@ Doc: $\var{bnf}$ is as
 Variant: Instead the above  hardcoded  numerical flags,  one should rather use
  \fun{GEN}{Buchray}{GEN bnf, GEN module, long flag}
  where flag is an or-ed combination of \kbd{nf\_GEN} (include generators)
- and \kbd{nf\_INIT} (if omitted, return just the cardinal of the ray class group
- and its structure), possibly 0.
+ and \kbd{nf\_INIT} (if omitted, return just the cardinality of the ray class
+ group and its structure), possibly 0.
diff --git a/src/functions/number_fields/bnrisgalois b/src/functions/number_fields/bnrisgalois
new file mode 100644
index 0000000..a9073cb
--- /dev/null
+++ b/src/functions/number_fields/bnrisgalois
@@ -0,0 +1,32 @@
+Function: bnrisgalois
+Section: number_fields
+C-Name: bnrisgalois
+Prototype: lGGG
+Help: bnrisgalois(bnr, gal, H): check whether the class field associated to
+ the subgroup H is Galois over the subfield of bnr.nf fixed by the Galois
+ group gal, which can be given as output by galoisinit, or as a matrix or a
+ vector of matrices as output by bnrgaloismatrix. The ray class field
+ associated to bnr need to be Galois, which is not checked.
+Doc: check whether the class field associated to the subgroup $H$ is Galois
+ over the subfield of \kbd{bnr.nf} fixed by the group \var{gal}, which can be
+ given as output by \tet{galoisinit}, or as a matrix or a vector of matrices as
+ output by \kbd{bnrgaloismatrix}, the second option being preferable, since it
+ saves the recomputation of the matrices.  Note: The function assumes that the
+ ray class field associated to bnr is Galois, which is not checked.
+
+ In the following example, we lists the congruence subgroups of subextension of
+ degree at most $3$ of the ray class field of conductor $9$ which are Galois
+ over the rationals.
+
+ \bprog
+ K=bnfinit(a^4-3*a^2+253009);
+ G=galoisinit(K);
+ B=bnrinit(K,9,1);
+ L1=[H|H<-subgrouplist(B,3), bnrisgalois(B,G,H)]
+ ##
+ M=bnrgaloismatrix(B,G)
+ L2=[H|H<-subgrouplist(B,3), bnrisgalois(B,M,H)]
+ ##
+ @eprog
+ The second computation is much faster since \kbd{bnrgaloismatrix(B,G)} is
+ computed only once.
diff --git a/src/functions/number_fields/galoissubgroups b/src/functions/number_fields/galoissubgroups
index 31fcbe0..294ee60 100644
--- a/src/functions/number_fields/galoissubgroups
+++ b/src/functions/number_fields/galoissubgroups
@@ -7,7 +7,7 @@ Doc: outputs all the subgroups of the Galois group \kbd{gal}. A subgroup is a
  vector [\var{gen}, \var{orders}], with the same meaning
  as for $\var{gal}.gen$ and $\var{gal}.orders$. Hence \var{gen} is a vector of
  permutations generating the subgroup, and \var{orders} is the relatives
- orders of the generators. The cardinal of a subgroup is the product of the
+ orders of the generators. The cardinality of a subgroup is the product of the
  relative orders. Such subgroup can be used instead of a Galois group in the
  following command: \kbd{galoisisabelian}, \kbd{galoissubgroups},
  \kbd{galoisexport} and \kbd{galoisidentify}.
diff --git a/src/functions/number_fields/idealprimedec b/src/functions/number_fields/idealprimedec
index 7f3695e..fc23bf1 100644
--- a/src/functions/number_fields/idealprimedec
+++ b/src/functions/number_fields/idealprimedec
@@ -1,14 +1,17 @@
 Function: idealprimedec
 Section: number_fields
-C-Name: idealprimedec
-Prototype: GG
-Help: idealprimedec(nf,p): prime ideal decomposition of the prime number p
- in the number field nf as a vector of 5 component vectors [p,a,e,f,b]
+C-Name: idealprimedec_limit_f
+Prototype: GGD0,L,
+Help: idealprimedec(nf,p,{f=0}): prime ideal decomposition of the prime number
+ p in the number field nf as a vector of 5 component vectors [p,a,e,f,b]
  representing the prime ideals pZ_K+a. Z_K, e,f as usual, a as vector of
- components on the integral basis, b Lenstra's constant.
+ components on the integral basis, b Lenstra's constant. If f is present
+ and non-zero, restrict the result to primes of residue degree <= f.
 Doc: computes the prime ideal
  decomposition of the (positive) prime number $p$ in the number field $K$
  represented by \var{nf}. If a non-prime $p$ is given the result is undefined.
+ If $f$ is present and non-zero, restrict the result to primes of residue
+ degree $\leq f$.
 
  The result is a vector of \tev{prid} structures, each representing one of the
  prime ideals above $p$ in the number field $\var{nf}$. The representation
@@ -29,10 +32,10 @@ Doc: computes the prime ideal
  \kbd{pr.e}, \kbd{pr.f}, and \kbd{pr.gen} (returns the vector $[p,a]$):
  \bprog
  ? K = nfinit(x^3-2);
- ? L = idealprimedec(K, 5);
- ? #L       \\ 2 primes above 5 in Q(2^(1/3))
+ ? P = idealprimedec(K, 5);
+ ? #P       \\ 2 primes above 5 in Q(2^(1/3))
  %3 = 2
- ? p1 = L[1]; p2 = L[2];
+ ? [p1,p2] = P;
  ? [p1.e, p1.f]    \\ the first is unramified of degree 1
  %4 = [1, 1]
  ? [p2.e, p2.f]    \\ the second is unramified of degree 2
@@ -41,4 +44,6 @@ Doc: computes the prime ideal
  %6 = [5, [2, 1, 0]~]
  ? nfbasistoalg(K, %[2])  \\ a uniformizer for p1
  %7 = Mod(x + 2, x^3 - 2)
+ ? #idealprimedec(K, 5, 1) \\ restrict to f = 1
+ %8 = 1            \\ now only p1
  @eprog
diff --git a/src/functions/number_fields/idealval b/src/functions/number_fields/idealval
index 9d654ac..ef16ed0 100644
--- a/src/functions/number_fields/idealval
+++ b/src/functions/number_fields/idealval
@@ -1,8 +1,12 @@
 Function: idealval
 Section: number_fields
-C-Name: idealval
-Prototype: lGGG
+C-Name: gpidealval
+Prototype: GGG
 Help: idealval(nf,x,pr): valuation at pr given in idealprimedec format of the
  ideal x in the number field nf.
 Doc: gives the valuation of the ideal $x$ at the prime ideal \var{pr} in the
  number field $\var{nf}$, where \var{pr} is in \kbd{idealprimedec} format.
+ The valuation of the $0$ ideal is \kbd{+oo}.
+Variant: Also available is
+ \fun{long}{idealval}{GEN nf, GEN x, GEN pr}, which returns
+ \tet{LONG_MAX} if $x = 0$ and the valuation as a \kbd{long} integer.
diff --git a/src/functions/number_fields/nfbasis b/src/functions/number_fields/nfbasis
index 227260f..f3be0cd 100644
--- a/src/functions/number_fields/nfbasis
+++ b/src/functions/number_fields/nfbasis
@@ -1,7 +1,7 @@
 Function: nfbasis
 Section: number_fields
 C-Name: nfbasis_gp
-Prototype: GDGDG
+Prototype: G
 Help: nfbasis(T): integral basis of the field Q[a], where a is
  a root of the polynomial T, using the round 4 algorithm. An argument
  [T,listP] is possible, where listP is a list of primes (to get an
diff --git a/src/functions/number_fields/nfcompositum b/src/functions/number_fields/nfcompositum
new file mode 100644
index 0000000..85f2c40
--- /dev/null
+++ b/src/functions/number_fields/nfcompositum
@@ -0,0 +1,66 @@
+Function: nfcompositum
+Section: number_fields
+C-Name: nfcompositum
+Prototype: GGGD0,L,
+Help: nfcompositum(nf,P,Q,{flag=0}): vector of all possible compositums
+ of the number fields defined by the polynomials P and Q; flag is
+ optional, whose binary digits mean 1: output for each compositum, not only
+ the compositum polynomial pol, but a vector [R,a,b,k] where a (resp. b) is a
+ root of P (resp. Q) expressed as a polynomial modulo R, and a small integer k
+ such that al2+k*al1 is the chosen root of R; 2: assume that the number
+ fields defined by P and Q are linearly disjoint.
+
+Doc: Let \var{nf} be a number field structure associated to the field $K$
+ and let \sidx{compositum} $P$ and $Q$
+ be squarefree polynomials in $K[X]$ in the same variable. Outputs
+ the simple factors of the \'etale $K$-algebra $A = K(X, Y) / (P(X), Q(Y))$.
+ The factors are given by a list of polynomials $R$ in $K[X]$, associated to
+ the number field $K(X)/ (R)$, and sorted by increasing degree (with respect
+ to lexicographic ordering for factors of equal degrees). Returns an error if
+ one of the polynomials is not squarefree.
+
+ Note that it is more efficient to reduce to the case where $P$ and $Q$ are
+ irreducible first. The routine will not perform this for you, since it may be
+ expensive, and the inputs are irreducible in most applications anyway. In
+ this case, there will be a single factor $R$ if and only if the number
+ fields defined by $P$ and $Q$ are linearly disjoint (their intersection is
+ $K$).
+
+ The binary digits of $\fl$ mean
+
+ 1: outputs a vector of 4-component vectors $[R,a,b,k]$, where $R$
+ ranges through the list of all possible compositums as above, and $a$
+ (resp. $b$) expresses the root of $P$ (resp. $Q$) as an element of
+ $K(X)/(R)$. Finally, $k$ is a small integer such that $b + ka = X$ modulo
+ $R$.
+
+ 2: assume that $P$ and $Q$ define number fields which are linearly disjoint:
+ both polynomials are irreducible and the corresponding number fields
+ have no common subfield besides $K$. This allows to save a costly
+ factorization over $K$. In this case return the single simple factor
+ instead of a vector with one element.
+
+ A compositum is often defined by a complicated polynomial, which it is
+ advisable to reduce before further work. Here is an example involving
+ the field $K(\zeta_5, 5^{1/5})$, $K=\Q(\sqrt{5})$:
+ \bprog
+ ? K = nfinit(y^2-5);
+ ? L = nfcompositum(K, x^5 - y, polcyclo(5), 1); \\@com list of $[R,a,b,k]$
+ ? [R, a] = L[1];  \\@com pick the single factor, extract $R,a$ (ignore $b,k$)
+ ? lift(R)         \\@com defines the compositum
+ %3 = x^10 + (-5/2*y + 5/2)*x^9 + (-5*y + 20)*x^8 + (-20*y + 30)*x^7 + \
+ (-45/2*y + 145/2)*x^6 + (-71/2*y + 121/2)*x^5 + (-20*y + 60)*x^4 +    \
+ (-25*y + 5)*x^3 + 45*x^2 + (-5*y + 15)*x + (-2*y + 6)
+ ? a^5 - y         \\@com a fifth root of $y$
+ %4 = 0
+ ? [T, X] = rnfpolredbest(K, R, 1);
+ ? lift(T)     \\@com simpler defining polynomial for $K[x]/(R)$
+ %6 = x^10 + (-11/2*y + 25/2)
+ ? liftall(X)  \\ @com root of $R$ in $K[x]/(T(x))$
+ %7 = (3/4*y + 7/4)*x^7 + (-1/2*y - 1)*x^5 + 1/2*x^2 + (1/4*y - 1/4)
+ ? a = subst(a.pol, 'x, X);  \\@com \kbd{a} in the new coordinates
+ ? liftall(a)
+ %8 = (-3/4*y - 7/4)*x^7 - 1/2*x^2
+ ? a^5 - y
+ %9 = 0
+ @eprog
diff --git a/src/functions/number_fields/nfdisc b/src/functions/number_fields/nfdisc
index ec0bcc8..7eb3d9a 100644
--- a/src/functions/number_fields/nfdisc
+++ b/src/functions/number_fields/nfdisc
@@ -1,7 +1,7 @@
 Function: nfdisc
 Section: number_fields
-C-Name: nfdisc_gp
-Prototype: GDGDG
+C-Name: nfdisc
+Prototype: G
 Help: nfdisc(T): discriminant of the number field defined by
  the polynomial T. An argument [T,listP] is possible, where listP is a list
  of primes or a prime bound.
diff --git a/src/functions/number_fields/nfeltval b/src/functions/number_fields/nfeltval
index 62100e0..18b5198 100644
--- a/src/functions/number_fields/nfeltval
+++ b/src/functions/number_fields/nfeltval
@@ -1,12 +1,40 @@
 Function: nfeltval
 Section: number_fields
-C-Name: nfval
-Prototype: lGGG
-Help: nfeltval(nf,x,pr): valuation of element x at the prime pr as output by
- idealprimedec.
+C-Name: gpnfvalrem
+Prototype: GGGD&
+Help: nfeltval(nf,x,pr,{&y}): valuation of element x at the prime pr as output
+ by idealprimedec.
 Doc: given an element $x$ in
  \var{nf} and a prime ideal \var{pr} in the format output by
- \kbd{idealprimedec}, computes the valuation at \var{pr} of the
- element $x$. The same result can be obtained using
+ \kbd{idealprimedec}, computes the valuation $v$ at \var{pr} of the
+ element $x$. The valuation of $0$ is \kbd{+oo}.
+ \bprog
+ ? nf = nfinit(x^2 + 1);
+ ? P = idealprimedec(nf, 2)[1];
+ ? nfeltval(nf, x+1, P)
+ %3 = 1
+ @eprog\noindent
+ This particular valuation can also be obtained using
  \kbd{idealval(\var{nf},x,\var{pr})}, since $x$ is then converted to a
  principal ideal.
+
+ If the $y$ argument is present, sets $y = x \tau^v$, where $\tau$ is a
+ fixed ``anti-uniformizer'' for \var{pr}: its valuation at \var{pr} is $-1$;
+ its valuation is $0$ at other prime ideals dividing \kbd{\var{pr}.p} and
+ nonnegative at all other primes. In other words $y$ is the part of $x$
+ coprime to \var{pr}. If $x$ is an algebraic integer, so is $y$.
+ \bprog
+ ? nfeltval(nf, x+1, P, &y); y
+ %4 = [0, 1]~
+ @eprog
+ For instance if $x = \prod_i x_i^{e_i}$ is known to be coprime to \var{pr},
+ where the $x_i$ are algebraic integers and $e_i\in\Z$ then,
+ if $v_i = \kbd{nfeltval}(\var{nf}, x_i, \var{pr}, \&y_i)$, we still
+ have $x = \prod_i y_i^{e_i}$, where the $y_i$ are still algebraic integers
+ but now all of them are coprime to \var{pr}. They can then be mapped to
+ the residue field of \var{pr} more efficiently than if the product had
+ been expanded beforehand: we can reduce mod \var{pr} after each ring
+ operation.
+Variant: Also available is
+ \fun{long}{nfvalrem}{GEN nf, GEN x, GEN pr, GEN *y = NULL}, which returns
+ \tet{LONG_MAX} if $x = 0$ and the valuation as a \kbd{long} integer.
diff --git a/src/functions/number_fields/nfgrunwaldwang b/src/functions/number_fields/nfgrunwaldwang
new file mode 100644
index 0000000..952a475
--- /dev/null
+++ b/src/functions/number_fields/nfgrunwaldwang
@@ -0,0 +1,42 @@
+Function: nfgrunwaldwang
+Section: number_fields
+C-Name: nfgrunwaldwang
+Prototype: GGGGDn
+Help: nfgrunwaldwang(nf,Lpr,Ld,pl,{v='x}): a polynomial in the variable v
+ defining a cyclic extension of nf (given in nf or bnf form) with local
+ behaviour prescribed by Lpr, Ld and pl: the extension has local degree a
+ multiple of Ld[i] at the prime Lpr[i], and the extension is complex at the
+ i-th real place of nf if pl[i]=-1 (no condition if pl[i]=0). The extension
+ has degree the LCM of the local degrees.
+Doc: Given \var{nf} a number field in \var{nf} or \var{bnf} format,
+ a \typ{VEC} \var{Lpr} of primes of \var{nf} and a \typ{VEC} \var{Ld} of
+ positive integers of the same length, a \typ{VECSMALL} \var{pl} of length
+ $r_1$ the number of real places of \var{nf}, computes a polynomial with
+ coefficients in \var{nf} defining a cyclic extension of \var{nf} of
+ minimal degree satisfying certain local conditions:
+
+ \item at the prime \kbd{Lpr[i]}, the extension has local degree a multiple of
+ \kbd{Ld[i]};
+
+ \item at the $i$-th real place of \var{nf}, it is complex if $pl[i]=-1$
+ (no condition if $pl[i]=0$).
+
+ The extension has degree the LCM of the local degrees. Currently, the degree
+ is restricted to be a prime power for the search, and to be prime for the
+ construction because of the \kbd{rnfkummer} restrictions.
+
+ When \var{nf} is $\Q$, prime integers are accepted instead of \var{prid}
+ structures. However, their primality is not checked and the behaviour is
+ undefined if you provide a composite number.
+
+ \misctitle{Warning} If the number field \var{nf} does not contain the $n$-th
+ roots of unity where $n$ is the degree of the extension to be computed,
+ triggers the computation of the \var{bnf} of $nf(\zeta_n)$, which may be
+ costly.
+
+ \bprog
+ ? nf = nfinit(y^2-5);
+ ? pr = idealprimedec(nf,13)[1];
+ ? pol = nfgrunwaldwang(nf, [pr], [2], [0,-1], 'x)
+ %3 = x^2 + Mod(3/2*y + 13/2, y^2 - 5)
+ @eprog
diff --git a/src/functions/number_fields/nfhnf b/src/functions/number_fields/nfhnf
index b92a451..545e94d 100644
--- a/src/functions/number_fields/nfhnf
+++ b/src/functions/number_fields/nfhnf
@@ -1,12 +1,19 @@
 Function: nfhnf
 Section: number_fields
-C-Name: nfhnf
-Prototype: GG
-Help: nfhnf(nf,x): if x=[A,I], gives a pseudo-basis of the module sum A_jI_j
+C-Name: nfhnf0
+Prototype: GGD0,L,
+Help: nfhnf(nf,x,{flag=0}): if x=[A,I], gives a pseudo-basis [B,J] of the module
+ sum A_jI_j. If flag is non-zero, return [[B,J], U], where U is the
+ transformation matrix such that AU = [0|B]
 Doc: given a pseudo-matrix $(A,I)$, finds a
- pseudo-basis in \idx{Hermite normal form} of the module it generates.
+ pseudo-basis $(B,J)$ in \idx{Hermite normal form} of the module it generates.
+ If $\fl$ is non-zero, also return the transfomation matrix $U$ such that
+ $AU = [0|B]$.
+
 Variant: Also available:
 
+ \fun{GEN}{nfhnf}{GEN nf, GEN x} ($\fl = 0$).
+
  \fun{GEN}{rnfsimplifybasis}{GEN bnf, GEN x} simplifies the pseudo-basis
  given by $x = (A,I)$. The ideals in the list $I$ are integral, primitive and
  either trivial (equal to the full ring of integer) or non-principal.
diff --git a/src/functions/number_fields/nfinit b/src/functions/number_fields/nfinit
index b510c7a..73fb65d 100644
--- a/src/functions/number_fields/nfinit
+++ b/src/functions/number_fields/nfinit
@@ -88,8 +88,10 @@ Doc: \var{pol} being a non-constant,
 
  If a non monic polynomial is input, \kbd{nfinit} will transform it into a
  monic one, then reduce it (see $\fl=3$). It is allowed, though not very
- useful given the existence of \tet{nfnewprec}, to input a \kbd{nf} or a
- \kbd{bnf} instead of a polynomial.
+ useful given the existence of \tet{nfnewprec}, to input a \var{nf} or a
+ \var{bnf} instead of a polynomial. It is also allowed to
+ input a \var{rnf}, in which case an \var{nf} structure associated to the
+ absolute defining polynomial \kbd{polabs} is returned (\fl is then ignored).
 
  \bprog
  ? nf = nfinit(x^3 - 12); \\ initialize number field Q[X] / (X^3 - 12)
diff --git a/src/functions/number_fields/nfsnf b/src/functions/number_fields/nfsnf
index 46dfc6f..3027b5a 100644
--- a/src/functions/number_fields/nfsnf
+++ b/src/functions/number_fields/nfsnf
@@ -1,12 +1,15 @@
 Function: nfsnf
 Section: number_fields
-C-Name: nfsnf
-Prototype: GG
-Help: nfsnf(nf,x): if x=[A,I,J], outputs [c_1,...c_n] Smith normal form of x.
-Doc: given a $\Z_K$-module $x$ associated to the integral pseudo-matrix
- $(A,I,J)$, returns an ideal list $d_1,\dots,d_n$ which is the \idx{Smith
- normal form} of $x$. In other words, $x$ is isomorphic to
- $\Z_K/d_1\oplus\cdots\oplus\Z_K/d_n$ and $d_i$ divides $d_{i-1}$ for $i\ge2$.
+C-Name: nfsnf0
+Prototype: GGD0,L,
+Help: nfsnf(nf,x,{flag=0}): if x=[A,I,J], outputs D=[d_1,...d_n] Smith normal
+ form of x. If flag is non-zero return [D,U,V], where UAV = Id.
+Doc: given a torsion $\Z_K$-module $x$ associated to the square integral
+ invertible pseudo-matrix $(A,I,J)$, returns an ideal list
+ $D=[d_1,\dots,d_n]$ which is the \idx{Smith normal form} of $x$. In other
+ words, $x$ is isomorphic to $\Z_K/d_1\oplus\cdots\oplus\Z_K/d_n$ and $d_i$
+ divides $d_{i-1}$ for $i\ge2$. If $\fl$ is non-zero return $[D,U,V]$, where
+ $UAV$ is the identity.
 
  See \secref{se:ZKmodules} for the definition of integral pseudo-matrix;
  briefly, it is input as a 3-component row vector $[A,I,J]$ where
@@ -21,3 +24,6 @@ Doc: given a $\Z_K$-module $x$ associated to the integral pseudo-matrix
  finitely generated torsion module is isomorphic to a module of this form and
  even with $b_i=Z_K$ for all $i$.
 
+Variant: Also available:
+
+ \fun{GEN}{nfsnf}{GEN nf, GEN x} ($\fl = 0$).
diff --git a/src/functions/number_fields/nfsplitting b/src/functions/number_fields/nfsplitting
new file mode 100644
index 0000000..670b1a0
--- /dev/null
+++ b/src/functions/number_fields/nfsplitting
@@ -0,0 +1,26 @@
+Function: nfsplitting
+Section: number_fields
+C-Name: nfsplitting
+Prototype: GDG
+Help: nfsplitting(nf,{d}): defining polynomial for the splitting field of
+ the number field nf; if d is given, it must be the degree of the splitting
+ field
+Doc: defining polynomial for the splitting field of \var{nf};
+ if $d$ is given, it must be the degree of the splitting field. It
+ is possible to input a defining polynomial $T$ instead but this is in
+ general less efficient.
+ \bprog
+ ? K = nfinit(x^3-2);
+ ? nfsplitting(K)
+ %2 = x^6 + 108
+ ?  nfsplitting(x^8-2)
+ %3 = x^16 + 272*x^8 + 64
+ @eprog\noindent
+ The complexity of the algorithm is polynomial in the degree $d$ of the
+ splitting field and the bitsize of $T$; if $d$ is large the result will
+ likely be unusable, e.g. \kbd{nfinit} will not be an option:
+ \bprog
+ ? nfsplitting(x^6-x-1)
+ [... degree 720 polynomial deleted ...]
+ time = 11,020 ms.
+ @eprog
diff --git a/src/functions/number_fields/polcompositum b/src/functions/number_fields/polcompositum
index e239d63..f471556 100644
--- a/src/functions/number_fields/polcompositum
+++ b/src/functions/number_fields/polcompositum
@@ -3,11 +3,13 @@ Section: number_fields
 C-Name: polcompositum0
 Prototype: GGD0,L,
 Help: polcompositum(P,Q,{flag=0}): vector of all possible compositums
- of the number fields defined by the polynomials P and Q. If (optional)
- flag is set (i.e non-null), output for each compositum, not only the
- compositum polynomial pol, but a vector [R,a,b,k] where a (resp. b) is a root
- of P (resp. Q) expressed as a polynomial modulo R,
- and a small integer k such that al2+k*al1 is the chosen root of R.
+ of the number fields defined by the polynomials P and Q; flag is
+ optional, whose binary digits mean 1: output for each compositum, not only
+ the compositum polynomial pol, but a vector [R,a,b,k] where a (resp. b) is a
+ root of P (resp. Q) expressed as a polynomial modulo R, and a small integer k
+ such that al2+k*al1 is the chosen root of R; 2: assume that the number
+ fields defined by P and Q are linearly disjoint.
+
 Doc: \sidx{compositum} $P$ and $Q$
  being squarefree polynomials in $\Z[X]$ in the same variable, outputs
  the simple factors of the \'etale $\Q$-algebra $A = \Q(X, Y) / (P(X), Q(Y))$.
@@ -20,7 +22,8 @@ Doc: \sidx{compositum} $P$ and $Q$
  irreducible first. The routine will not perform this for you, since it may be
  expensive, and the inputs are irreducible in most applications anyway. In
  this case, there will be a single factor $R$ if and only if the number
- fields defined by $P$ and $Q$ are disjoint.
+ fields defined by $P$ and $Q$ are linearly disjoint (their intersection is
+ $\Q$).
 
  Assuming $P$ is irreducible (of smaller degree than $Q$ for efficiency), it
  is in general much faster to proceed as follows
@@ -32,12 +35,20 @@ Doc: \sidx{compositum} $P$ and $Q$
  simple factors, the \kbd{rnfequation} instruction can be replaced by a
  trivial \kbd{poldegree(P) * poldegree(L[i])}.
 
- If $\fl=1$, outputs a vector of 4-component vectors $[R,a,b,k]$, where $R$
+ The binary digits of $\fl$ mean
+
+ 1: outputs a vector of 4-component vectors $[R,a,b,k]$, where $R$
  ranges through the list of all possible compositums as above, and $a$
  (resp. $b$) expresses the root of $P$ (resp. $Q$) as an element of
  $\Q(X)/(R)$. Finally, $k$ is a small integer such that $b + ka = X$ modulo
  $R$.
 
+ 2: assume that $P$ and $Q$ define number fields which are linearly disjoint:
+ both polynomials are irreducible and the corresponding number fields
+ have no common subfield besides $\Q$. This allows to save a costly
+ factorization over $\Q$. In this case return the single simple factor
+ instead of a vector with one element.
+
  A compositum is often defined by a complicated polynomial, which it is
  advisable to reduce before further work. Here is an example involving
  the field $\Q(\zeta_5, 5^{1/5})$:
@@ -61,6 +72,11 @@ Doc: \sidx{compositum} $P$ and $Q$
  %8 = Mod(1/11*x^14 + 29/11*x^4, x^20 + 25*x^10 + 5)
  ? a^5 - 5
  %9 = 0
+ @eprog\noindent In the above example, $x^5-5$ and the $5$-th cyclotomic
+ polynomial are irreducible over $\Q$; they have coprime degrees so
+ define linearly disjoint extensions and we could have started by
+ \bprog
+ ? [R,a] = polcompositum(x^5 - 5, polcyclo(5), 3); \\@com $[R,a,b,k]$
  @eprog
 Variant: Also available are
  \fun{GEN}{compositum}{GEN P, GEN Q} ($\fl = 0$) and
diff --git a/src/functions/number_fields/rnfidealabstorel b/src/functions/number_fields/rnfidealabstorel
index 6c46d1d..0d83ace 100644
--- a/src/functions/number_fields/rnfidealabstorel
+++ b/src/functions/number_fields/rnfidealabstorel
@@ -20,7 +20,7 @@ Doc: let $\var{rnf}$ be a relative
    rnfidealabstorel(rnf, Labs.zk * m)
  @eprog\noindent converts $m$ to a relative ideal.
  \bprog
- ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); Labs = nfinit(L.pol);
+ ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); Labs = nfinit(L);
  ? m = idealhnf(Labs, 17, x^3+2);
  ? B = rnfidealabstorel(L, Labs.zk * m)
  %3 = [[1, 8; 0, 1], [[17, 4; 0, 1], 1]]  \\ pseudo-basis for m as Z_K-module
diff --git a/src/functions/number_fields/rnfinit b/src/functions/number_fields/rnfinit
index b4acb03..e05db81 100644
--- a/src/functions/number_fields/rnfinit
+++ b/src/functions/number_fields/rnfinit
@@ -21,6 +21,14 @@ Doc: $\var{nf}$ being a number field in \kbd{nfinit}
  information via \emph{member functions} is preferred since the specific
  data organization specified below will change in the future.
 
+ Note that a subsequent \kbd{nfinit}$(\var{rnf})$ will explicitly add an
+ \var{nf} structure associated to $L$ to \var{rnf} (and return it as well).
+ This is likely to be very expensive if the absolute degree $mn$ is large,
+ but fixes an integer basis for $\Z_L$ as a $\Z$-module and allows to input
+ and output elements of $L$ in absolute form: as \typ{COL} for elements,
+ as \typ{MAT} in HNF for ideals, as \kbd{prid} for prime ideals. Without such
+ a call, elements of $L$ are represented as \typ{POLMOD}, etc.
+
  $\var{rnf}[1]$(\kbd{rnf.pol}) contains the relative polynomial \var{pol}.
 
  $\var{rnf}[2]$ contains the integer basis $[A,d]$ of $K$, as
@@ -53,8 +61,9 @@ Doc: $\var{nf}$ being a number field in \kbd{nfinit}
 
  $\var{rnf}[10]$ (\kbd{rnf.nf}) is $\var{nf}$.
 
- $\var{rnf}[11]$ is the output of \kbd{rnfequation(K, pol, 1)}. Namely, a
- vector $[P, a, k]$ describing the \emph{absolute} extension
+ $\var{rnf}[11]$ is an extension of \kbd{rnfequation(K, pol, 1)}. Namely, a
+ vector $[P, a, k, \kbd{K.pol}, \kbd{pol}]$ describing the \emph{absolute}
+ extension
  $L/\Q$: $P$ is an absolute equation, more conveniently obtained
  as \kbd{rnf.polabs}; $a$ expresses the generator $\alpha = y \mod \kbd{K.pol}$
  of the number field $K$ as an element of $L$, i.e.~a polynomial modulo the
@@ -63,7 +72,7 @@ Doc: $\var{nf}$ being a number field in \kbd{nfinit}
  $k$ is a small integer such that, if $\beta$ is an abstract root of \var{pol}
  and $\alpha$ the generator of $K$ given above, then $P(\beta + k\alpha) = 0$.
 
- \misctitle{Caveat.} Be careful if $k\neq0$ when dealing simultaneously with
+ \misctitle{Caveat} Be careful if $k\neq0$ when dealing simultaneously with
  absolute and relative quantities since $L = \Q(\beta + k\alpha) =
  K(\alpha)$, and the generator chosen for the absolute extension is not the
  same as for the relative one. If this happens, one can of course go on
diff --git a/src/functions/number_fields/rnfnormgroup b/src/functions/number_fields/rnfnormgroup
index 2ea3fda..3606664 100644
--- a/src/functions/number_fields/rnfnormgroup
+++ b/src/functions/number_fields/rnfnormgroup
@@ -18,4 +18,6 @@ Doc:
  bnr). The result is the HNF defining the norm group on the given generators
  of \kbd{bnr.gen}. Note that neither the fact that \var{pol} defines an
  Abelian extension nor the fact that the module is a multiple of the conductor
- is checked. The result is undefined if the assumption is not correct.
+ is checked. The result is undefined if the assumption is not correct,
+ but the function will return the empty matrix \kbd{[;]} if it detects a
+ problem; it may also not detect the problem and return a wrong result.
diff --git a/src/functions/number_theoretical/content b/src/functions/number_theoretical/content
index a7e1e44..7812d16 100644
--- a/src/functions/number_theoretical/content
+++ b/src/functions/number_theoretical/content
@@ -24,4 +24,5 @@ Doc: computes the gcd of all the coefficients of $x$,
  \bprog
  ? content([ [2], 4*matid(3) ])
  %1 = 2
- @eprog
+ @eprog\noindent The content of a \typ{VECSMALL} is computed assuming the
+ entries are signed integers in $[-2^{BIL-1}, 2^{BIL-1}[$.
diff --git a/src/functions/number_theoretical/ffgen b/src/functions/number_theoretical/ffgen
index ff58509..68d1094 100644
--- a/src/functions/number_theoretical/ffgen
+++ b/src/functions/number_theoretical/ffgen
@@ -27,8 +27,16 @@ Doc: return a \typ{FFELT} generator for the finite field with $q$ elements;
   ***   at top-level: ffgen(6)
   ***                 ^--------
   *** ffgen: not a prime number in ffgen: 6.
- @eprog\noindent Alternative syntax: instead of a prime power $q$, one may
- input directly the polynomial $P$ (monic, irreducible, with \typ{INTMOD}
+ @eprog\noindent Alternative syntax: instead of a prime power $q=p^f$, one may
+ input the pair $[p,f]$:
+ \bprog
+ ? g = ffgen([2,4], 't);
+ ? g.p
+ %2 = 2
+ ? g.mod
+ %3 = t^4 + t^3 + t^2 + t + 1
+ @eprog\noindent Finally, one may input
+ directly the polynomial $P$ (monic, irreducible, with \typ{INTMOD}
  coefficients), and the function returns the generator $g = X \pmod{P(X)}$,
  inferring $p$ from the coefficients of $P$. If \kbd{v} is given, the
  variable name is used to display $g$, else the variable of the polynomial
diff --git a/src/functions/number_theoretical/ispower b/src/functions/number_theoretical/ispower
index de363bd..9eb1a2a 100644
--- a/src/functions/number_theoretical/ispower
+++ b/src/functions/number_theoretical/ispower
@@ -24,7 +24,7 @@ Doc: if $k$ is given, returns true (1) if $x$ is a $k$-th power, false
  \noindent For a \typ{FFELT} \kbd{x}, instead of omitting \kbd{k} (which is
  not allowed for this type), it may be natural to set
  \bprog
- k = (x.p ^ poldegree(x.pol) - 1) / fforder(x)
+ k = (x.p ^ x.f - 1) / fforder(x)
  @eprog
 Variant: Also available is
  \fun{long}{gisanypower}{GEN x, GEN *pty} ($k$ omitted).
diff --git a/src/functions/number_theoretical/ispowerful b/src/functions/number_theoretical/ispowerful
index 39e056a..e8c1799 100644
--- a/src/functions/number_theoretical/ispowerful
+++ b/src/functions/number_theoretical/ispowerful
@@ -3,10 +3,10 @@ Section: number_theoretical
 C-Name: ispowerful
 Prototype: lG
 Help: ispowerful(x): true(1) if x is a powerful integer (valuation at all
- primes is greater than 1), false(0) if not.
+ primes dividing x is greater than 1), false(0) if not.
 Doc: true (1) if $x$ is a powerful integer, false (0) if not;
- an integer is powerful if and only if its valuation at all primes is
- greater than 1.
+ an integer is powerful if and only if its valuation at all primes dividing
+ $x$ is greater than 1.
  \bprog
  ? ispowerful(50)
  %1 = 0
diff --git a/src/functions/number_theoretical/ispseudoprime b/src/functions/number_theoretical/ispseudoprime
index 0f26792..f2c2626 100644
--- a/src/functions/number_theoretical/ispseudoprime
+++ b/src/functions/number_theoretical/ispseudoprime
@@ -9,7 +9,7 @@ Description:
  (int,?0):bool      BPSW_psp($1)
  (int,#small):bool  millerrabin($1,$2)
  (int,small):bool   ispseudoprime($1, $2)
- (gen,?small):bool  gispseudoprime($1, $2)
+ (gen,?small):gen   gispseudoprime($1, $2)
 Doc: true (1) if $x$ is a strong pseudo
  prime (see below), false (0) otherwise. If this function returns false, $x$
  is not prime; if, on the other hand it returns true, it is only highly likely
@@ -26,7 +26,7 @@ Doc: true (1) if $x$ is a strong pseudo
  There are no known composite numbers passing this test, although it is
  expected that infinitely many such numbers exist. In particular, all
  composites $\leq 2^{64}$ are correctly detected (checked using
- \kbd{http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html}).
+ \url{http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html}).
 
  If $\fl > 0$, checks whether $x$ is a strong Miller-Rabin pseudo prime  for
  $\fl$ randomly chosen bases (with end-matching to catch square roots of $-1$).
diff --git a/src/functions/number_theoretical/ispseudoprimepower b/src/functions/number_theoretical/ispseudoprimepower
new file mode 100644
index 0000000..7f9dab8
--- /dev/null
+++ b/src/functions/number_theoretical/ispseudoprimepower
@@ -0,0 +1,18 @@
+Function: ispseudoprimepower
+Section: number_theoretical
+C-Name: ispseudoprimepower
+Prototype: lGD&
+Help: ispseudoprimepower(x,{&n}): if x = p^k is a pseudo-prime power (p
+ pseudo-prime, k > 0),
+ return k, else return 0. If n is present, and the function returns a non-zero
+ result, set n to p, the k-th root of x.
+Doc: if $x = p^k$ is a pseudo-prime power ($p$ pseudo-prime as per
+ \tet{ispseudoprime}, $k > 0$), return $k$, else
+ return 0. If a second argument $\&n$ is given and $x$ is indeed
+ the $k$-th power of a prime $p$, sets $n$ to $p$.
+
+ More precisely, $k$ is always the largest integer such that $x = n^k$ for
+ some integer $n$ and, when $n \leq  2^{64}$ the function returns $k > 0$ if and
+ only if $n$ is indeed prime. When $n > 2^{64}$ is larger than the threshold,
+ the function may return $1$ even though $n$ is composite: it only passed
+ an \kbd{ispseudoprime(n)} test.
diff --git a/src/functions/number_theoretical/lcm b/src/functions/number_theoretical/lcm
index eab7e1d..a0b1e23 100644
--- a/src/functions/number_theoretical/lcm
+++ b/src/functions/number_theoretical/lcm
@@ -2,14 +2,16 @@ Function: lcm
 Section: number_theoretical
 C-Name: glcm0
 Prototype: GDG
-Help: lcm(x,{y}): least common multiple of x and y, i.e. x*y / gcd(x,y).
+Help: lcm(x,{y}): least common multiple of x and y, i.e. x*y / gcd(x,y)
+ up to units.
 Description:
  (int, int):int lcmii($1, $2)
  (gen):gen      glcm0($1, NULL)
  (gen, gen):gen glcm($1, $2)
 Doc: least common multiple of $x$ and $y$, i.e.~such
- that $\lcm(x,y)*\gcd(x,y) = \text{abs}(x*y)$. If $y$ is omitted and $x$
+ that $\lcm(x,y)*\gcd(x,y) = x*y$, up to units. If $y$ is omitted and $x$
  is a vector, returns the $\text{lcm}$ of all components of $x$.
+ For integer arguments, return the non-negative \text{lcm}.
 
  When $x$ and $y$ are both given and one of them is a vector/matrix type,
  the LCM is again taken recursively on each component, but in a different way.
@@ -28,9 +30,9 @@ Doc: least common multiple of $x$ and $y$, i.e.~such
  and should be much more efficient, especially when using the GMP
  multiprecision kernel (and more subquadratic algorithms become available):
  \bprog
- ? v = vector(10^4, i, random);
+ ? v = vector(10^5, i, random);
  ? lcm(v);
- time = 323 ms.
+ time = 546 ms.
  ? l = v[1]; for (i = 1, #v, l = lcm(l, v[i]))
- time = 833 ms.
+ time = 4,561 ms.
  @eprog
diff --git a/src/functions/number_theoretical/qfbclassno b/src/functions/number_theoretical/qfbclassno
index c3df308..b09690d 100644
--- a/src/functions/number_theoretical/qfbclassno
+++ b/src/functions/number_theoretical/qfbclassno
@@ -4,23 +4,27 @@ C-Name: qfbclassno0
 Prototype: GD0,L,
 Help: qfbclassno(D,{flag=0}): class number of discriminant D using Shanks's
  method by default. If (optional) flag is set to 1, use Euler products.
-Doc: ordinary class number of the quadratic
- order of discriminant $D$. In the present version \vers, a $O(D^{1/2})$
- algorithm is used for $D > 0$ (using Euler product and the functional
- equation) so $D$ should not be too large, say $D < 10^8$, for the time to be
- reasonable. On the other hand, for $D < 0$ one can reasonably compute
- \kbd{qfbclassno($D$)} for $|D|<10^{25}$, since the routine uses
- \idx{Shanks}'s method which is in $O(|D|^{1/4})$. For larger values of $|D|$,
- see \kbd{quadclassunit}.
-
- If $\fl=1$, compute the class number using \idx{Euler product}s and the
- functional equation. However, it is in $O(|D|^{1/2})$.
-
- \misctitle{Important warning} For $D < 0$, this function may give incorrect
- results when the class group has many cyclic factors,
- because implementing \idx{Shanks}'s method in full generality slows it down
- immensely. It is therefore strongly recommended to double-check results using
- either the version with $\fl = 1$ or the function \kbd{quadclassunit}.
+Doc: ordinary class number of the quadratic order of discriminant $D$, for
+ ``small'' values of $D$.
+
+ \item if  $D > 0$ or $\fl = 1$, use a $O(|D|^{1/2})$
+ algorithm (compute $L(1,\chi_D)$ with the approximate functional equation).
+ This is slower than \tet{quadclassunit} as soon as $|D| \approx 10^2$ or
+ so and is not meant to be used for large $D$.
+
+ \item if $D < 0$ and $\fl = 0$ (or omitted), use a $O(|D|^{1/4})$
+ algorithm (Shanks's baby-step/giant-step method). It should
+ be faster than \tet{quadclassunit} for small values of $D$, say
+ $|D| < 10^{18}$.
+
+ \misctitle{Important warning} In the latter case, this function only
+ implements part of \idx{Shanks}'s method (which allows to speed it up
+ considerably). It gives unconditionnally correct results for $|D| < 2\cdot
+ 10^{10}$, but may give incorrect results for larger values if the class
+ group has many cyclic factors. We thus recommend to double-check results
+ using the function \kbd{quadclassunit}, which is about 2 to 3 times slower in
+ the above range, assuming GRH. We currently have no counter-examples but
+ they should exist: we'd appreciate a bug report if you find one.
 
  \misctitle{Warning} Contrary to what its name implies, this routine does not
  compute the number of classes of binary primitive forms of discriminant $D$,
diff --git a/src/functions/number_theoretical/qfbredsl2 b/src/functions/number_theoretical/qfbredsl2
new file mode 100644
index 0000000..1bc9c6b
--- /dev/null
+++ b/src/functions/number_theoretical/qfbredsl2
@@ -0,0 +1,15 @@
+Function: qfbredsl2
+Section: number_theoretical
+C-Name: qfbredsl2
+Prototype: GDG
+Help: qfbredsl2(x,{data}): reduction of the binary quadratic form x, return
+ [y,g] where y is reduced and g in Sl(2,Z) is such that g.x = y; data, if
+ present, must be equal to [D, sqrtint(D)], where D > 0 is the discriminant
+ of x.
+Doc:
+ reduction of the (real or imaginary) binary quadratic form $x$, return
+ $[y,g]$ where $y$ is reduced and $g$ in $\text{SL}(2,\Z)$ is such that
+  $g \cdot x = y$; \var{data}, if
+ present, must be equal to $[D, \kbd{sqrtint}(D)]$, where $D > 0$ is the
+ discriminant of $x$. In case $x$ is \typ{QFR}, the distance component is
+ unaffected.
diff --git a/src/functions/number_theoretical/quaddisc b/src/functions/number_theoretical/quaddisc
index 7b776ff..3149c90 100644
--- a/src/functions/number_theoretical/quaddisc
+++ b/src/functions/number_theoretical/quaddisc
@@ -3,4 +3,14 @@ Section: number_theoretical
 C-Name: quaddisc
 Prototype: G
 Help: quaddisc(x): discriminant of the quadratic field Q(sqrt(x)).
-Doc: discriminant of the quadratic field $\Q(\sqrt{x})$, where $x\in\Q$.
+Doc: discriminant of the \'etale algebra $\Q(\sqrt{x})$, where $x\in\Q^*$.
+ This is the same as \kbd{coredisc}$(d)$ where $d$ is the integer square-free
+ part of $x$, so x=$d f^2$ with $f\in \Q^*$ and $d\in\Z$.
+ This returns $0$ for $x = 0$, $1$ for $x$ square and the discriminant of the
+ quadratic field $\Q(\sqrt{x})$ otherwise.
+ \bprog
+ ? quaddisc(7)
+ %1 = 28
+ ? quaddisc(-7)
+ %2 = -7
+ @eprog
diff --git a/src/functions/number_theoretical/stirling b/src/functions/number_theoretical/stirling
index 6f1792e..4e23974 100644
--- a/src/functions/number_theoretical/stirling
+++ b/src/functions/number_theoretical/stirling
@@ -24,7 +24,7 @@ Doc: \idx{Stirling number} of the first kind $s(n,k)$ ($\fl=1$, default) or
  /* list of S(n,k), k = 1..n */
  vecstirling2(n) =
  { my(Q = x^(n-1), t);
-   vector(n, i, t = divrem(Q, x-i); Q=t[1]; t[2]);
+   vector(n, i, t = divrem(Q, x-i); Q=t[1]; simplify(t[2]));
  }
  @eprog
 Variant: Also available are \fun{GEN}{stirling1}{ulong n, ulong k}
diff --git a/src/functions/number_theoretical/sumdigits b/src/functions/number_theoretical/sumdigits
index c9257de..9ea9d5b 100644
--- a/src/functions/number_theoretical/sumdigits
+++ b/src/functions/number_theoretical/sumdigits
@@ -1,11 +1,17 @@
 Function: sumdigits
 Section: number_theoretical
-C-Name: sumdigits
-Prototype: G
-Help: sumdigits(n): sum of (decimal) digits in the integer n.
-Doc: sum of (decimal) digits in the integer $n$.
+C-Name: sumdigits0
+Prototype: GDG
+Help: sumdigits(n,{B=10}): sum of digits in the integer n, when written in
+ base B.
+Doc: sum of digits in the integer $n$, when written in base $B > 1$.
  \bprog
  ? sumdigits(123456789)
  %1 = 45
- @eprog\noindent Other bases that 10 are not supported. Note that the sum of
- bits in $n$ is returned by \tet{hammingweight}.
+ ? sumdigits(123456789, 2)
+ %1 = 16
+ @eprog\noindent Note that the sum of bits in $n$ is also returned by
+ \tet{hammingweight}. This function is much faster than
+ \kbd{vecsum(digits(n,B))} when $B$ is $10$ or a power of $2$, and only
+ slightly faster in other cases.
+Variant: Also available is \fun{GEN}{sumdigits}{GEN n}, for $B = 10$.
diff --git a/src/functions/number_theoretical/zncoppersmith b/src/functions/number_theoretical/zncoppersmith
index 8be0865..b24f6c4 100644
--- a/src/functions/number_theoretical/zncoppersmith
+++ b/src/functions/number_theoretical/zncoppersmith
@@ -23,14 +23,15 @@ Doc: $N$ being an integer and $P\in \Z[X]$, finds all integers $x$ with
  non-trivial divisor of $N$.
  \bprog
  setrand(1); \\ to make the example reproducible
- p = nextprime(random(10^30));
- q = nextprime(random(10^30)); N = p*q;
+ interval = [10^30, 10^31];
+ p = randomprime(interval);
+ q = randomprime(interval); N = p*q;
  p0 = p % 10^20; \\ assume we know 1) p > 10^29, 2) the last 19 digits of p
- p1 = zncoppersmith(10^19*x + p0, N, 10^12, 10^29)
+ L = zncoppersmith(10^19*x + p0, N, 10^12, 10^29)
 
  \\ result in 10ms.
- %1 = [35023733690]
- ? gcd(p1[1] * 10^19 + p0, N) == p
+ %6 = [738281386540]
+ ? gcd(L[1] * 10^19 + p0, N) == p
  %2 = 1
  @eprog\noindent and we recovered $p$, faster than by trying all
  possibilities $ < 10^{12}$.
@@ -48,7 +49,8 @@ Doc: $N$ being an integer and $P\in \Z[X]$, finds all integers $x$ with
  zncoppersmith((P + x)^3 - C, N, X)
 
  \\ result in 244ms.
- %3 = [265174753892462432]
+ %14 = [2679982004001230401]
+
  ? %[1] == x0
  %4 = 1
  @eprog\noindent
diff --git a/src/functions/operators/powers b/src/functions/operators/powers
new file mode 100644
index 0000000..c73e3ea
--- /dev/null
+++ b/src/functions/operators/powers
@@ -0,0 +1,8 @@
+Function: powers
+Section: operators
+C-Name: gpowers
+Prototype: GL
+Description:
+ (gen, small):vec  gpowers($1, $2)
+Help: powers(x,n): return the vector [1,x,...,x^n]
+Doc: return the vector $[1,x,\dots,x^n]$.
diff --git a/src/functions/polynomials/bezoutres b/src/functions/polynomials/bezoutres
index 79b467e..118b9d7 100644
--- a/src/functions/polynomials/bezoutres
+++ b/src/functions/polynomials/bezoutres
@@ -2,5 +2,5 @@ Function: bezoutres
 Section: polynomials
 C-Name: polresultantext0
 Prototype: GGDn
-Help: bezoutre(A,B,{v}): deprecated alias for polresultantext
+Help: bezoutres(A,B,{v}): deprecated alias for polresultantext
 Doc: deprecated alias for \kbd{polresultantext}
diff --git a/src/functions/polynomials/eval b/src/functions/polynomials/eval
index 609f25a..5767a70 100644
--- a/src/functions/polynomials/eval
+++ b/src/functions/polynomials/eval
@@ -36,8 +36,8 @@ Doc: replaces in $x$ the formal variables by the values that
  exception, which can be trapped as usual:
  \bprog
  ? 1a
-  ***   unused characters: 1a
-  ***                       ^-
+  ***   syntax error, unexpected variable name, expecting $end or ';': 1a
+  ***                                                                   ^-
  ? E(expr) =
    {
      iferr(eval(expr),
diff --git a/src/functions/polynomials/factorpadic b/src/functions/polynomials/factorpadic
index d7429e8..cac091f 100644
--- a/src/functions/polynomials/factorpadic
+++ b/src/functions/polynomials/factorpadic
@@ -1,7 +1,7 @@
 Function: factorpadic
 Section: polynomials
-C-Name: factorpadic0
-Prototype: GGLD0,L,
+C-Name: factorpadic
+Prototype: GGL
 Help: factorpadic(pol,p,r): p-adic factorization of the polynomial pol
  to precision r.
 Doc: $p$-adic factorization
diff --git a/src/functions/polynomials/polclass b/src/functions/polynomials/polclass
new file mode 100644
index 0000000..4a66caf
--- /dev/null
+++ b/src/functions/polynomials/polclass
@@ -0,0 +1,14 @@
+Function: polclass
+Section: polynomials
+C-Name: polclass
+Prototype: GDn
+Help: polclass(D, {x = 'x}): return the Hilbert class polynomial for the disciminant D.
+Doc:
+ Return the Hilbert class polynomial for the $j$ function for the imaginary quadratic
+ discriminant $D$ in the variable $x$.
+ \bprog
+ ? polclass(-163)
+ %1 = x + 262537412640768000
+ ? polclass(-51, 'z)
+ %2 = z^2 + 5541101568*z + 6262062317568
+ @eprog
diff --git a/src/functions/polynomials/polcoeff b/src/functions/polynomials/polcoeff
index 28fdd5f..ad9f4cf 100644
--- a/src/functions/polynomials/polcoeff
+++ b/src/functions/polynomials/polcoeff
@@ -7,7 +7,10 @@ Help: polcoeff(x,n,{v}): coefficient of degree n of x, or the n-th component
  to the main variable if v is omitted, with respect to the variable v
  otherwise.
 Description:
- (pol, 0):gen:copy      constant_term($1)
+ (pol, 0):gen:copy       constant_term($1)
+ (pol, 0,):gen:copy      constant_term($1)
+ (pol, small):gen:copy   RgX_coeff($1, $2)
+ (pol, small,):gen:copy  RgX_coeff($1, $2)
  (gen, small, ?var):gen polcoeff0($1, $2, $3)
 Doc: coefficient of degree $n$ of the polynomial $x$, with respect to the
  main variable if $v$ is omitted, with respect to $v$ otherwise.  If $n$
diff --git a/src/functions/polynomials/poldegree b/src/functions/polynomials/poldegree
index 7b1101a..43cdebf 100644
--- a/src/functions/polynomials/poldegree
+++ b/src/functions/polynomials/poldegree
@@ -1,18 +1,16 @@
 Function: poldegree
 Section: polynomials
-C-Name: poldegree
-Prototype: lGDn
+C-Name: gppoldegree
+Prototype: GDn
 Help: poldegree(x,{v}): degree of the polynomial or rational function x with
  respect to main variable if v is omitted, with respect to v otherwise.
- For scalar x, return 0 is x is non-zero and a negative number otherwise.
-Description:
- (pol):small                degpol($1)
- (gen):small                degree($1)
- (gen, var):small           poldegree($1, $2)
+ For scalar x, return 0 is x is non-zero and -oo otherwise.
 Doc: degree of the polynomial $x$ in the main variable if $v$ is omitted, in
  the variable $v$ otherwise.
 
- The degree of $0$ is a fixed negative number, whose exact value should not
- be used. The degree of a non-zero scalar is $0$. Finally, when $x$ is a
- non-zero polynomial or rational function, returns the ordinary degree of
- $x$. Raise an error otherwise.
+ The degree of $0$ is \kbd{-oo}. The degree of a non-zero scalar is $0$.
+ Finally, when $x$ is a non-zero polynomial or rational function, returns the
+ ordinary degree of $x$. Raise an error otherwise.
+Variant: Also available is
+ \fun{long}{poldegree}{GEN x, long v}, which returns \tet{-LONG_MAX} if $x = 0$
+ and the degree as a \kbd{long} integer.
diff --git a/src/functions/polynomials/polmodular b/src/functions/polynomials/polmodular
new file mode 100644
index 0000000..d2a9c89
--- /dev/null
+++ b/src/functions/polynomials/polmodular
@@ -0,0 +1,29 @@
+Function: polmodular
+Section: polynomials
+C-Name: polmodular
+Prototype: LDGDnD0,L,
+Help: polmodular(L, {x = 'x}, {y = 'y}, {compute_derivs = 0}): return the
+ modular polynomial of level L.
+Doc:
+ Return the modular polynomial of level $L$ in variables $x$ and $y$ for the
+ $j$ function.  If $x$ is given as \kbd{Mod(j, p)} or an element $j$ of a prime
+ finite field, then return the modular polynomial of level $L$ evaluated at $j$
+ modulo $p$.  If $j$ is from a finite field and \var{compute\_derivs} is
+ non-zero, then return a triple where the last two elements are the first and
+ second derivatives of the modular polynomial evaluated at $j$.
+ \bprog
+ ? polmodular(3)
+ %1 = x^4 + (-y^3 + 2232*y^2 - 1069956*y + 36864000)*x^3 + [...]
+ @eprog
+Variant: Also available are
+
+ \fun{GEN}{modpoly_ZXX}{long L, long xvar, long yvar} which returns a
+ bivariate polynomial in variables \kbd{xvar} and \kbd{yvar},
+
+ \fun{GEN}{modpoly_ZM}{long L} which returns a matrix of coefficients, and
+
+ \fun{GEN}{Fp_modpoly_evalx}{long L, GEN J, GEN P, long v, int
+ compute_derivs} which returns the modular polynomial evaluated at $J$ modulo
+ $P$ in the variable $v$ (if \kbd{compute\_derivs} is non-zero, returns a
+ vector containing the modular polynomial and its first and second
+ derivatives, all evaluted at $J$ modulo $P$).
diff --git a/src/functions/polynomials/polrootsreal b/src/functions/polynomials/polrootsreal
new file mode 100644
index 0000000..d5c1a90
--- /dev/null
+++ b/src/functions/polynomials/polrootsreal
@@ -0,0 +1,36 @@
+Function: polrootsreal
+Section: polynomials
+C-Name: realroots
+Prototype: GDGp
+Help: polrootsreal(T, {ab}): real roots of the polynomial T with rational
+ coefficients, using Uspensky's method. In interval ab = [a,b] if present.
+Doc: real roots of the polynomial $T$ with rational coefficients, multiple
+ roots being included according to their multiplicity. The roots are given
+ to a relative accuracy of \kbd{realprecision}. If argument \var{ab} is
+ present, it must be a vector $[a,b]$ with two components (of type
+ \typ{INT}, \typ{FRAC} or \typ{INFINITY}) and we restrict to roots belonging
+ to that closed interval.
+ \bprog
+ ? \p9
+ ? polrootsreal(x^2-2)
+ %1 = [-1.41421356, 1.41421356]~
+ ? polrootsreal(x^2-2, [1,+oo])
+ %2 = [1.41421356]~
+ ? polrootsreal(x^2-2, [2,3])
+ %3 = []~
+ ? polrootsreal((x-1)*(x-2), [2,3])
+ %4 = [2.00000000]~
+ @eprog\noindent
+ The algorithm used is a modification of Uspensky's method (relying on
+ Descartes's rule of sign), following Rouillier and Zimmerman ``Efficient
+ isolation of a polynomial real roots''
+ (\url{http://hal.inria.fr/inria-00072518/}. Barring bugs, it is guaranteed
+ to converge and to give the roots to the required accuracy.
+
+ \misctitle{Remark} If the polynomial $T$ is of the
+ form $Q(x^h)$ for some $h\geq 2$ and \var{ab} is omitted, the routine will
+ apply the algorithm to $Q$ (restricting to non-negative roots when $h$ is
+ even), then take $h$-th roots. On the other hand, if you want to specify
+ \var{ab}, you should apply the routine to $Q$ yourself and a suitable
+ interval $[a',b']$ using approximate $h$-th roots adapted to your problem:
+ the function will not perform this change of variables if \var{ab} is present.
diff --git a/src/functions/polynomials/polsturm b/src/functions/polynomials/polsturm
index 6c2a598..ead0128 100644
--- a/src/functions/polynomials/polsturm
+++ b/src/functions/polynomials/polsturm
@@ -2,11 +2,31 @@ Function: polsturm
 Section: polynomials
 C-Name: sturmpart
 Prototype: lGDGDG
-Help: polsturm(pol,{a},{b}): number of real roots of the squarefree polynomial
- pol in the interval ]a,b] (which are respectively taken to be -oo or +oo when
- omitted).
-Doc: number of real roots of the real squarefree polynomial \var{pol} in the
- interval $]a,b]$, using Sturm's algorithm. $a$ (resp.~$b$) is taken to be
- $-\infty$ (resp.~$+\infty$) if omitted.
-Variant: Also available is \fun{long}{sturm}{GEN pol} (total number of real
- roots).
+Help: polsturm(T,{ab}): number of real roots of the squarefree polynomial
+ T (in the interval ab = [a,b] if present).
+Doc: number of real roots of the real squarefree polynomial \var{T}. If
+ the argument \var{ab} is present, it must be a vector $[a,b]$ with
+ two real components (of type \typ{INT}, \typ{REAL}, \typ{FRAC}
+ or  \typ{INFINITY}) and we count roots belonging to that closed interval.
+
+ If possible, you should stick to exact inputs, that is avoid \typ{REAL}s in
+ $T$ and the bounds $a,b$: the result is then guaranteed and we use a fast
+ algorithm (Uspensky's method, relying on Descartes's rule of sign, see
+ \tet{polrootsreal}); otherwise, we use Sturm's algorithm and the result
+ may be wrong due to round-off errors.
+ \bprog
+ ? T = (x-1)*(x-2)*(x-3);
+ ? polsturm(T)
+ %2 = 3
+ ? polsturm(T, [-oo,2])
+ %3 = 2
+ ? polsturm(T, [1/2,+oo])
+ %4 = 3
+ ? polsturm(T, [1, Pi])  \\ Pi inexact: not recommended !
+ %5 = 3
+ @eprog
+ %\syn{NO}
+
+ The library syntax is \fun{long}{RgX_sturmpart}{GEN T, GEN ab} or
+ \fun{long}{sturm}{GEN T} (for the case \kbd{ab = NULL}). The function
+ \fun{long}{sturmpart}{GEN T, GEN a, GEN b} is obsolete and deprecated.
diff --git a/src/functions/polynomials/polzagier b/src/functions/polynomials/polzagier
index 503f45c..2f97fe2 100644
--- a/src/functions/polynomials/polzagier
+++ b/src/functions/polynomials/polzagier
@@ -4,9 +4,16 @@ C-Name: polzag
 Prototype: LL
 Help: polzagier(n,m): Zagier's polynomials of index n,m.
 Doc: creates Zagier's polynomial $P_n^{(m)}$ used in
- the functions \kbd{sumalt} and \kbd{sumpos} (with $\fl=1$). One must have $m\le
- n$. The exact definition can be found in ``Convergence acceleration of
- alternating series'', Cohen et al., Experiment.~Math., vol.~9, 2000, pp.~3--12.
+ the functions \kbd{sumalt} and \kbd{sumpos} (with $\fl=1$), see
+ ``Convergence acceleration of alternating series'', Cohen et al.,
+ \emph{Experiment.~Math.}, vol.~9, 2000, pp.~3--12.
+
+ If $m < 0$ or $m \ge n$, $P_n^{(m)} = 0$.
+ We have
+ $P_n := P_n^{(0)}$ is $T_n(2x-1)$, where $T_n$ is the Legendre polynomial of
+ the second kind. For $n > m > 0$, $P_n^{(m)}$ is the $m$-th difference with
+ step $2$ of the sequence $n^{m+1}P_n$; in this case, it satisfies
+ $$2 P_n^{(m)}(sin^2 t) = \dfrac{d^{m+1}}{dt^{m+1}}(\sin(2t)^m \sin(2(n-m)t)).$$
 
  %@article {MR2001m:11222,
  %    AUTHOR = {Cohen, Henri and Rodriguez Villegas, Fernando and Zagier, Don},
diff --git a/src/functions/polynomials/serlaplace b/src/functions/polynomials/serlaplace
index 6a983b0..af89934 100644
--- a/src/functions/polynomials/serlaplace
+++ b/src/functions/polynomials/serlaplace
@@ -5,4 +5,5 @@ Prototype: G
 Help: serlaplace(x): replaces the power series sum of a_n*x^n/n! by sum of
  a_n*x^n. For the reverse operation, use serconvol(x,exp(X)).
 Doc: $x$ must be a power series with non-negative
- exponents. If $x=\sum (a_k/k!)*X^k$ then the result is $\sum a_k*X^k$.
+ exponents or a polynomial. If $x=\sum (a_k/k!)*X^k$ then the result is $\sum
+ a_k*X^k$.
diff --git a/src/functions/polynomials/thue b/src/functions/polynomials/thue
index 9c0a106..a3a7249 100644
--- a/src/functions/polynomials/thue
+++ b/src/functions/polynomials/thue
@@ -12,7 +12,7 @@ Doc: returns all solutions of the equation
  $\kbd{thueinit}(P)$. If present, \var{sol} must contain the solutions of
  $\Norm(x)=a$ modulo units of positive norm in the number field
  defined by $P$ (as computed by \kbd{bnfisintnorm}). If there are infinitely
- many solutions, an error will be issued.
+ many solutions, an error is issued.
 
  It is allowed to input directly the polynomial $P$ instead of a \var{tnf},
  in which case, the function first performs \kbd{thueinit(P,0)}. This is
diff --git a/src/functions/polynomials/thueinit b/src/functions/polynomials/thueinit
index 1835e9b..c6bc4fa 100644
--- a/src/functions/polynomials/thueinit
+++ b/src/functions/polynomials/thueinit
@@ -6,14 +6,56 @@ Help: thueinit(P,{flag=0}): initialize the tnf corresponding to P, that will
  be used to solve Thue equations P(x,y) = some-integer. If flag is non-zero,
  certify the result unconditionaly. Otherwise, assume GRH (much faster of
  course).
-Doc: initializes the \var{tnf} corresponding to $P$, a univariate polynomial
- with integer coefficients. The result is meant to be used in conjunction with
- \tet{thue} to solve Thue equations $P(X / Y)Y^{\deg P} = a$, where $a$ is an
- integer.
+Doc: initializes the \var{tnf} corresponding to $P$, a non-constant
+ univariate polynomial with integer coefficients.
+ The result is meant to be used in conjunction with \tet{thue} to solve Thue
+ equations $P(X / Y)Y^{\deg P} = a$, where $a$ is an integer. Accordingly,
+ $P$ must either have at least two distinct irreducible factors over $\Q$,
+ or have one irreducible factor $T$ with degree $>2$ or two conjugate
+ complex roots: under these (necessary and sufficient) conditions, the
+ equation has finitely many integer solutions.
+ \bprog
+ ? S = thueinit(t^2+1);
+ ? thue(S, 5)
+ %2 = [[-2, -1], [-2, 1], [-1, -2], [-1, 2], [1, -2], [1, 2], [2, -1], [2, 1]]
+ ? S = thueinit(t+1);
+  ***   at top-level: thueinit(t+1)
+  ***                 ^-------------
+  *** thueinit: domain error in thueinit: P = t + 1
+ @eprog\noindent The hardest case is when $\deg P > 2$ and $P$ is irreducible
+ with at least one real root. The routine then uses Bilu-Hanrot's algorithm.
 
  If $\fl$ is non-zero, certify results unconditionally. Otherwise, assume
  \idx{GRH}, this being much faster of course. In the latter case, the result
  may still be unconditionally correct, see \tet{thue}. For instance in most
  cases where $P$ is reducible (not a pure power of an irreducible), \emph{or}
  conditional computed class groups are trivial \emph{or} the right hand side
- is $\pm1$, then results are always unconditional.
+ is $\pm1$, then results are unconditional.
+
+ \misctitle{Note} The general philosophy is to disprove the existence of large
+ solutions then to enumerate bounded solutions naively. The implementation
+ will overflow when there exist huge solutions and the equation has degree
+ $> 2$ (the quadratic imaginary case is special, since we can use
+ \kbd{bnfisintnorm}):
+ \bprog
+ ? thue(t^3+2, 10^30)
+  ***   at top-level: L=thue(t^3+2,10^30)
+  ***                   ^-----------------
+  *** thue: overflow in thue (SmallSols): y <= 80665203789619036028928.
+ ? thue(x^2+2, 10^30)  \\ quadratic case much easier
+ %1 = [[-1000000000000000, 0], [1000000000000000, 0]]
+ @eprog
+
+ \misctitle{Note} It is sometimes possible to circumvent the above, and in any
+ case obtain an important speed-up, if you can write $P = Q(x^d)$ for some $d >
+ 1$ and $Q$ still satisfying the \kbd{thueinit} hypotheses. You can then solve
+ the equation associated to $Q$ then eliminate all solutions $(x,y)$ such that
+ either $x$ or $y$ is not a $d$-th power.
+ \bprog
+ ? thue(x^4+1, 10^40); \\ stopped after 10 hours
+ ? filter(L,d) =
+     my(x,y); [[x,y] | v<-L, ispower(v[1],d,&x)&&ispower(v[2],d,&y)];
+ ? L = thue(x^2+1, 10^40);
+ ? filter(L, 2)
+ %4 = [[0, 10000000000], [10000000000, 0]]
+ @eprog\noindent The last 2 commands use less than 20ms.
diff --git a/src/functions/programming/alarm b/src/functions/programming/alarm
index f9172da..59ecbc8 100644
--- a/src/functions/programming/alarm
+++ b/src/functions/programming/alarm
@@ -1,5 +1,4 @@
 Function: alarm
-Class: gp
 Section: programming/specific
 C-Name: gp_alarm
 Prototype: D0,L,DE
diff --git a/src/functions/programming/allocatemem b/src/functions/programming/allocatemem
index fb3cc1e..b1eb932 100644
--- a/src/functions/programming/allocatemem
+++ b/src/functions/programming/allocatemem
@@ -1,7 +1,6 @@
 Function: allocatemem
-Class: gp
 Section: programming/specific
-C-Name: allocatemem0
+C-Name: gp_allocatemem
 Prototype: vDG
 Help: allocatemem({s=0}): allocates a new stack of s bytes. doubles the
  stack if s is omitted.
@@ -11,12 +10,64 @@ Doc: this special operation changes the stack size \emph{after}
  $x$ is way too small, or for alignment reasons: the current formula is
  $\max(16*\ceil{x/16}, 500032)$ bytes.
 
- If $x=0$, the size of the new stack is twice the size of the old one. The
- old stack is discarded.
+ If $x=0$, the size of the new stack is twice the size of the old one.
 
- \misctitle{Warning} This function should be typed at the \kbd{gp} prompt in
+ This command is much more useful if \tet{parisizemax} is non-zero, and we
+ describe this case first. With \kbd{parisizemax} enabled, there are three
+ sizes of interest:
+
+ \item a virtual stack size, \tet{parisizemax}, which is an absolute upper
+ limit for the stack size; this is set by \kbd{default(parisizemax, ...)}.
+
+ \item the desired typical stack size, \tet{parisize}, that will grow as
+ needed, up to \tet{parisizemax}; this is set by \kbd{default(parisize, ...)}.
+
+ \item the current stack size, which is less that \kbd{parisizemax},
+ typically equal to \kbd{parisize} but possibly larger and increasing
+ dynamically as needed; \kbd{allocatemem} allows to change that one
+ explicitly.
+
+ The \kbd{allocatemem} command forces stack
+ usage to increase temporarily (up to \kbd{parisizemax} of course); for
+ instance if you notice using \kbd{\bs gm2} that we seem to collect garbage a
+ lot, e.g.
+ \bprog
+ ? \gm2
+   debugmem = 2
+ ? default(parisize,"32M")
+  ***   Warning: new stack size = 32000000 (30.518 Mbytes).
+ ? bnfinit('x^2+10^30-1)
+  *** bnfinit: collecting garbage in hnffinal, i = 1.
+  *** bnfinit: collecting garbage in hnffinal, i = 2.
+  *** bnfinit: collecting garbage in hnffinal, i = 3.
+ @eprog\noindent and so on for hundred of lines. Then, provided the
+ \tet{breakloop} default is set, you can interrupt the computation, type
+ \kbd{allocatemem(100*10\pow6)} at the break loop prompt, then let the
+ computation go on by typing \kbd{<Enter>}. Back at the \kbd{gp} prompt,
+ the desired stack size of \kbd{parisize} is restored. Note that changing either
+ \kbd{parisize} or \kbd{parisizemax} at the break loop prompt would interrupt
+ the computation, contrary to the above.
+
+ In most cases, \kbd{parisize} will increase automatically (up to
+ \kbd{parisizemax}) and there is no need to perform the above maneuvers.
+ But that the garbage collector is sufficiently efficient that
+ a given computation can still run without increasing the stack size,
+ albeit very slowly due to the frequent garbage collections.
+
+ \misctitle{Deprecated: when \kbd{parisizemax} is unset}
+ This is currently still the default behavior in order not to break backward
+ compatibility. The rest of this section documents the
+ behavior of \kbd{allocatemem} in that (deprecated) situation: it becomes a
+ synonym for \kbd{default(parisize,...)}. In that case, there is no
+ notion of a virtual stack, and the stack size is always equal to
+ \kbd{parisize}. If more memory is needed, the PARI stack overflows, aborting
+ the computation.
+
+ Thus, increasing \kbd{parisize} via \kbd{allocatemem} or
+ \kbd{default(parisize,...)} before a big computation is important.
+ Unfortunately, either must be typed at the \kbd{gp} prompt in
  interactive usage, or left by itself at the start of batch files.
- It cannot be used meaningfully in loop-like constructs, or as part of a
+ They cannot be used meaningfully in loop-like constructs, or as part of a
  larger expression sequence, e.g
  \bprog
     allocatemem(); x = 1;   \\@com This will not set \kbd{x}!
@@ -24,7 +75,7 @@ Doc: this special operation changes the stack size \emph{after}
  In fact, all loops are immediately exited, user functions terminated, and
  the rest of the sequence following \kbd{allocatemem()} is silently
  discarded, as well as all pending sequences of instructions. We just go on
- reading the next instruction sequence from the file we're in (or from the
+ reading the next instruction sequence from the file we are in (or from the
  user). In particular, we have the following possibly unexpected behavior: in
  \bprog
     read("file.gp"); x = 1
@@ -32,18 +83,9 @@ Doc: this special operation changes the stack size \emph{after}
  the \kbd{x = 1} is never executed, since all pending instructions in the
  current sequence are discarded.
 
- The technical reason is that this routine moves the stack, so temporary
- objects created during the current expression evaluation are not correct
- anymore. (In particular byte-compiled expressions, which are allocated on
- the stack.) To avoid accessing obsolete pointers to the old stack, this
- routine ends by a \kbd{longjmp}.
-
- \misctitle{Remark} If the operating system cannot allocate the desired
- $x$ bytes, a loop halves the allocation size until it succeeds:
- \bprog
- ? allocatemem(5*10^10)
-  ***   Warning: not enough memory, new stack 50000000000.
-  ***   Warning: not enough memory, new stack 25000000000.
-  ***   Warning: not enough memory, new stack 12500000000.
-  ***   Warning: new stack size = 6250000000 (5960.464 Mbytes).
- @eprog
+ The reason for these unfortunate side-effects is that, with
+ \kbd{parisizemax} disabled, increasing the stack size physically
+ moves the stack, so temporary objects created during the current expression
+ evaluation are not correct anymore. (In particular byte-compiled expressions,
+ which are allocated on the stack.) To avoid accessing obsolete pointers to
+ the old stack, this routine ends by a \kbd{longjmp}.
diff --git a/src/functions/programming/extern b/src/functions/programming/extern
index 5bbd46e..94976d4 100644
--- a/src/functions/programming/extern
+++ b/src/functions/programming/extern
@@ -1,7 +1,6 @@
 Function: extern
-Class: gp
 Section: programming/specific
-C-Name: extern0
+C-Name: gpextern
 Prototype: s
 Help: extern(str): execute shell command str, and feeds the result to GP (as
  if loading from file).
diff --git a/src/functions/programming/externstr b/src/functions/programming/externstr
index 3fcf10c..b0fed58 100644
--- a/src/functions/programming/externstr
+++ b/src/functions/programming/externstr
@@ -1,5 +1,4 @@
 Function: externstr
-Class: gp
 Section: programming/specific
 C-Name: externstr
 Prototype: s
diff --git a/src/functions/programming/fold b/src/functions/programming/fold
new file mode 100644
index 0000000..4ffa44b
--- /dev/null
+++ b/src/functions/programming/fold
@@ -0,0 +1,23 @@
+Function: fold
+Section: programming/specific
+C-Name: fold0
+Prototype: GG
+Help: fold(f, A): return f(...f(f(A[1],A[2]),A[3]),...,A[#A])
+Wrapper: (GG)
+Description:
+  (closure,gen):gen    genfold(${1 cookie}, ${1 wrapper}, $2)
+Doc: Apply the \typ{CLOSURE} \kbd{f} of arity $2$ to the entries of \kbd{A}
+ to return \kbd{f(\dots f(f(A[1],A[2]),A[3])\dots ,A[\#A])}.
+ \bprog
+ ? fold((x,y)->x*y, [1,2,3,4])
+ %1 = 24
+ ? fold((x,y)->[x,y], [1,2,3,4])
+ %2 = [[[1, 2], 3], 4]
+ ? fold((x,f)->f(x), [2,sqr,sqr,sqr])
+ %3 = 256
+ ? fold((x,y)->(x+y)/(1-x*y),[1..5])
+ %4 = -9/19
+ ? bestappr(tan(sum(i=1,5,atan(i))))
+ %5 = -9/19
+ @eprog
+ \synt{genfold}{void *E, GEN (*fun)(void*,GEN, GEN), GEN A}.
diff --git a/src/functions/programming/getabstime b/src/functions/programming/getabstime
index 15d800f..914e177 100644
--- a/src/functions/programming/getabstime
+++ b/src/functions/programming/getabstime
@@ -3,10 +3,11 @@ Section: programming/specific
 C-Name: getabstime
 Prototype: l
 Help: getabstime(): time (in milliseconds) since startup.
-Doc: returns the time (in milliseconds) elapsed since \kbd{gp} startup. This
- provides a reentrant version of \kbd{gettime}:
+Doc: returns the CPU time (in milliseconds) elapsed since \kbd{gp} startup.
+ This provides a reentrant version of \kbd{gettime}:
  \bprog
  my (t = getabstime());
  ...
  print("Time: ", getabstime() - t);
  @eprog
+ For a version giving wall-clock time, see \tet{getwalltime}.
diff --git a/src/functions/programming/getheap b/src/functions/programming/getheap
index a83ea59..c5d9ce6 100644
--- a/src/functions/programming/getheap
+++ b/src/functions/programming/getheap
@@ -3,7 +3,7 @@ Section: programming/specific
 C-Name: getheap
 Prototype:
 Help: getheap(): 2-component vector giving the current number of objects in
- the heap and the space they occupy.
+ the heap and the space they occupy (in long words).
 Doc: returns a two-component row vector giving the
  number of objects on the heap and the amount of memory they occupy in long
  words. Useful mainly for debugging purposes.
diff --git a/src/functions/programming/gettime b/src/functions/programming/gettime
index a1b79f6..c6582d6 100644
--- a/src/functions/programming/gettime
+++ b/src/functions/programming/gettime
@@ -3,8 +3,10 @@ Section: programming/specific
 C-Name: gettime
 Prototype: l
 Help: gettime(): time (in milliseconds) since last call to gettime.
-Doc: returns the time (in milliseconds) elapsed since either the last call to
+Doc: returns the CPU time (in milliseconds) used since either the last call to
  \kbd{gettime}, or to the beginning of the containing GP instruction (if
  inside \kbd{gp}), whichever came last.
 
  For a reentrant version, see \tet{getabstime}.
+
+ For a version giving wall-clock time, see \tet{getwalltime}.
diff --git a/src/functions/programming/getwalltime b/src/functions/programming/getwalltime
new file mode 100644
index 0000000..309e79a
--- /dev/null
+++ b/src/functions/programming/getwalltime
@@ -0,0 +1,12 @@
+Function: getwalltime
+Section: programming/specific
+C-Name: getwalltime
+Prototype:
+Help: getwalltime(): time (in milliseconds) since the UNIX Epoch.
+Doc: returns the time (in milliseconds) elapsed since the UNIX Epoch
+ (1970-01-01 00:00:00 (UTC)).
+ \bprog
+ my (t = getwalltime());
+ ...
+ print("Time: ", getwalltime() - t);
+ @eprog
diff --git a/src/functions/programming/iferr b/src/functions/programming/iferr
index e8d8058..70956c4 100644
--- a/src/functions/programming/iferr
+++ b/src/functions/programming/iferr
@@ -216,10 +216,6 @@ Doc: evaluates the expression sequence \var{seq1}. If an error occurs,
   \var{E} has three component, 1 (\typ{STR}): the function $s$,
   2: the argument $x$, 3: the argument $x$.
 
-  \item \kbd{"e\_NEGVAL"}. An argument of function $s$ is a power series with
-  negative valuation, which does not make sense. (As in \kbd{cos(1/x)}.)
-  \var{E} has one component, 1 (\typ{STR}): the function name $s$.
-
   \item \kbd{"e\_PRIME"}. Function $s$ expected a prime number,
   and did receive $p$, which was not. (As in \kbd{idealprimedec(nf, 4)}.)
   \var{E} has two component, 1 (\typ{STR}): the function name $s$,
diff --git a/src/functions/programming/input b/src/functions/programming/input
index 67df986..c240d20 100644
--- a/src/functions/programming/input
+++ b/src/functions/programming/input
@@ -1,7 +1,6 @@
 Function: input
-Class: gp
 Section: programming/specific
-C-Name: input0
+C-Name: gp_input
 Prototype:
 Help: input(): read an expression from the input file or standard input.
 Doc: reads a string, interpreted as a GP expression,
diff --git a/src/functions/programming/localprec b/src/functions/programming/localprec
new file mode 100644
index 0000000..cd0a091
--- /dev/null
+++ b/src/functions/programming/localprec
@@ -0,0 +1,51 @@
+Function: localprec
+Section: programming/specific
+C-Name: localprec
+Prototype: vL
+Help: localprec(p): set the real precision to p in the dynamic scope.
+Doc: set the real precision to $p$ in the dynamic scope. All computations
+ are performed as if \tet{realprecision} was $p$:
+ transcendental constants (e.g.~\kbd{Pi}) and
+ conversions from exact to floating point inexact data use $p$ decimal
+ digits, as well as iterative routines implicitly using a floating point
+ accuracy as a termination criterion (e.g.~\tet{solve} or \tet{intnum}).
+ But \kbd{realprecision} itself is unaffected
+ and is ``unmasked'' when we exit the dynamic (\emph{not} lexical) scope.
+ In effect, this is similar to
+ \bprog
+ my(prec = default(realprecision));
+ default(realprecision,p);
+ ...
+ default(realprecision, prec);
+ @eprog\noindent but is both less cumbersome, cleaner (no need to manipulate
+ a global variable, which in fact never changes and is only temporarily masked)
+ and more robust: if the above computation is interrupted or an exception
+ occurs, \kbd{realprecision} will not be restored as intended.
+
+ Such \kbd{localprec} statements can be nested, the innermost one taking
+ precedence as expected. Beware that \kbd{localprec} follows the semantic of
+ \tet{local}, not \tet{my}: a subroutine called from \kbd{localprec} scope
+ uses the local accuracy:
+ \bprog
+ ? f()=precision(1.);
+ ? f()
+ %2 = 38
+ ? localprec(19); f()
+ %3 = 19
+ @eprog\noindent
+ \misctitle{Warning} Changing \kbd{realprecision} itself in programs is
+ now deprecated in favor of \kbd{localprec}. Think about the
+ \kbd{realprecision} default as an interactive command for the \kbd{gp}
+ interpreter, best left out of GP programs. Indeed, the above rules
+ imply that mixing both constructs yields surprising results:
+ \bprog
+ ? \p38
+ ? localprec(19); default(realprecision,100);  Pi
+ %1 = 3.141592653589793239
+ ? \p
+     realprecision = 115 significant digits (100 digits displayed)
+ @eprog\noindent Indeed, \kbd{realprecision} itself is ignored within
+ \kbd{localprec} scope, so \kbd{Pi} is computed to a low accuracy. And when
+ we leave \kbd{localprec} scope, \kbd{realprecision} only regains precedence,
+ it is not ``restored'' to the original value.
+ %\syn{NO}
diff --git a/src/functions/programming/parfor b/src/functions/programming/parfor
index 856ebb5..9fb25f2 100644
--- a/src/functions/programming/parfor
+++ b/src/functions/programming/parfor
@@ -1,7 +1,9 @@
 Function: parfor
 Section: programming/parallel
-C-Name: parfor
+C-Name: parfor0
 Prototype: vV=GDGJDVDI
+Description:
+ (gen,gen,closure):void parfor($1, $2, $3, NULL, NULL)
 Help: parfor(i=a,{b},expr1,{j},{expr2}): evaluates the sequence expr2
  (dependent on i and j) for i between a and b, in random order, computed
  in parallel. Substitute for j the value of expr1 (dependent on i).
diff --git a/src/functions/programming/parforprime b/src/functions/programming/parforprime
index 82d2e61..10b71eb 100644
--- a/src/functions/programming/parforprime
+++ b/src/functions/programming/parforprime
@@ -1,10 +1,12 @@
 Function: parforprime
 Section: programming/parallel
-C-Name: parforprime
+C-Name: parforprime0
 Prototype: vV=GDGJDVDI
+Description:
+ (gen,gen,closure):void parforprime($1, $2, $3, NULL, NULL)
 Help: parforprime(p=a,{b},expr1,{j},{expr2}): evaluates the sequence expr2
  (dependent on p and j) for p prime between a and b, in random order,
- computed in parallel. Substitute for j the value of expr1 (dependent on i).
+ computed in parallel. Substitute for j the value of expr1 (dependent on p).
  If b is omitted, the loop will not stop.
 Doc: evaluates the sequence \kbd{expr2} (dependent on $p$ and $j$) for $p$
  prime between $a$ and $b$, in random order, computed in parallel. Substitute
diff --git a/src/functions/programming/read b/src/functions/programming/read
index 63ef580..8e35ab9 100644
--- a/src/functions/programming/read
+++ b/src/functions/programming/read
@@ -1,7 +1,6 @@
 Function: read
-Class: gp
 Section: programming/specific
-C-Name: read0
+C-Name: gp_read_file
 Prototype: D"",s,
 Help: read({filename}): read from the input file filename. If filename is
  omitted, reread last input file, be it from read() or \r.
diff --git a/src/functions/programming/readstr b/src/functions/programming/readstr
index c96d393..92583a3 100644
--- a/src/functions/programming/readstr
+++ b/src/functions/programming/readstr
@@ -1,5 +1,4 @@
 Function: readstr
-Class: gp
 Section: programming/specific
 C-Name: readstr
 Prototype: D"",s,
diff --git a/src/functions/programming/self b/src/functions/programming/self
new file mode 100644
index 0000000..1f0fa6a
--- /dev/null
+++ b/src/functions/programming/self
@@ -0,0 +1,12 @@
+Function: self
+Section: programming/control
+C-Name: pari_self
+Prototype: m
+Help: self(): return the calling function or closure. Useful for defining
+ anonymous recursive functions.
+Doc: return the calling function or closure as a \typ{CLOSURE} object.
+ This is useful for defining anonymous recursive functions.
+ \bprog
+ ? (n->if(n==0,1,n*self()(n-1)))(5)
+ %1 = 120
+ @eprog
diff --git a/src/functions/programming/system b/src/functions/programming/system
index a80e820..e93c1e0 100644
--- a/src/functions/programming/system
+++ b/src/functions/programming/system
@@ -1,10 +1,7 @@
 Function: system
-Class: gp
 Section: programming/specific
-C-Name: system0
+C-Name: gpsystem
 Prototype: vs
-Description:
- (str):void   system($1)
 Help: system(str): str being a string, execute the system command str.
 Doc: \var{str} is a string representing a system command. This command is
  executed, its output written to the standard output (this won't get into your
diff --git a/src/functions/sums/intmellininvshort b/src/functions/sums/intmellininvshort
index 6083611..0065456 100644
--- a/src/functions/sums/intmellininvshort
+++ b/src/functions/sums/intmellininvshort
@@ -8,7 +8,7 @@ Help: intmellininvshort(sig,z,tab): numerical integration on the
  by default assume s(X) decreases like exp(-X). Or sig = [sigR, al], sigR is
  the abscissa of integration, and al = 0 for slowly decreasing functions, or
  al > 0 if s(X) decreases like exp(-al*X). Compulsory table tab has been
- precomputed using the command intfuncinit(t=[[-1],sig[2]],[[1],sig[2]],s)
+ precomputed using the command intfuncinit(t=[-oo,sig[2]],[oo,sig[2]],s)
  (with possibly its two optional additional parameters), where sig[2] = 1
  if not given. Orders of magnitude faster than intmellininv.
 Doc: numerical integration
@@ -17,14 +17,13 @@ Doc: numerical integration
  Here $s(X)$ is implicitly contained in \var{tab} in \kbd{intfuncinit} format,
  typically
  \bprog
- tab = intfuncinit(T = [-1], [1], s(sig + I*T))
+ tab = intfuncinit(T = -oo, oo, s(sig + I*T))
  @eprog\noindent
  or similar commands. Take the example of the inverse Mellin transform of
  $\Gamma(s)^3$ given in \kbd{intmellininv}:
 
  \bprog
  ? \p 105
- ? oo = [1]; \\@com for clarity
  ? A = intmellininv(s=2,4, gamma(s)^3);
  time = 2,500 ms. \\@com not too fast because of $\Gamma(s)^3$.
  \\ @com function of real type, decreasing as $\exp(-3\pi/2\cdot |t|)$
diff --git a/src/functions/sums/intnum b/src/functions/sums/intnum
index 5b89b99..4801db3 100644
--- a/src/functions/sums/intnum
+++ b/src/functions/sums/intnum
@@ -3,7 +3,7 @@ Section: sums
 C-Name: intnum0
 Prototype: V=GGEDGp
 Help: intnum(X=a,b,expr,{tab}): numerical integration of expr from a to b with
- respect to X. Plus/minus infinity is coded as [+1]/ [-1]. Finally tab is
+ respect to X. Plus/minus infinity is coded as +oo/-oo. Finally tab is
  either omitted (let the program choose the integration step), a positive
  integer m (choose integration step 1/2^m), or data precomputed with intnuminit.
 Wrapper: (,,G)
@@ -21,12 +21,8 @@ Doc: numerical integration
  ? intnum(x = 0,Pi/2, [cos(x), sin(x)])
  %2 = [1.000000000000000000000000000, 1.000000000000000000000000000]
  @eprog\noindent
- An endpoint equal to $\pm\infty$ is coded as the single-component vector
- $[\pm1]$. You are welcome to set, e.g \kbd{oo = [1]} or \kbd{INFINITY = [1]},
- then using \kbd{+oo}, \kbd{-oo}, \kbd{-INFINITY}, etc. will have the expected
- behavior.
+ An endpoint equal to $\pm\infty$ is coded as \kbd{+oo} or \kbd{-oo}.
  \bprog
- ? oo = [1];  \\@com for clarity
  ? intnum(x = 1,+oo, 1/x^2)
  %2 = 1.000000000000000000000000000
  @eprog\noindent
@@ -59,9 +55,9 @@ Doc: numerical integration
 
  \misctitle{Specifying the behavior at endpoints}
  This is done as follows. An endpoint $a$ is either given as such (a scalar,
- real or complex, or $[\pm1]$ for $\pm\infty$), or as a two component vector
- $[a,\alpha]$, to indicate the behavior of the integrand in a neighborhood
- of $a$.
+ real or complex, \kbd{oo} or \kbd{-oo} for $\pm\infty$), or as a two
+ component vector $[a,\alpha]$, to indicate the behavior of the integrand in a
+ neighborhood of $a$.
 
  If $a$ is finite, the code $[a,\alpha]$ means the function has a
  singularity of the form $(x-a)^{\alpha}$, up to logarithms. (If $\alpha \ge
@@ -77,18 +73,17 @@ Doc: numerical integration
  %3 = 1.999999999999999999999946438 \\@com using a wrong exponent is bad
  @eprog
 
- If $a$ is $\pm\infty$, which is coded as $[\pm 1]$, the situation is more
- complicated, and $[[\pm1],\alpha]$ means:
+ If $a$ is $\pm\infty$, which is coded as \kbd{+oo} or \kbd{-oo},
+ the situation is more complicated, and $[\pm\kbd{oo},\alpha]$ means:
 
- \item $\alpha=0$ (or no $\alpha$ at all, i.e. simply $[\pm1]$) assumes that the
- integrand tends to zero, but not exponentially fast, and not
- oscillating such as $\sin(x)/x$.
+ \item $\alpha=0$ (or no $\alpha$ at all, i.e. simply $\pm\kbd{oo}$)
+ assumes that the integrand tends to zero, but not exponentially fast, and
+ not oscillating such as $\sin(x)/x$.
 
  \item $\alpha>0$ assumes that the function tends to zero exponentially fast
  approximately as $\exp(-\alpha x)$. This includes oscillating but quickly
  decreasing functions such as $\exp(-x)\sin(x)$.
  \bprog
- ? oo = [1];
  ? intnum(x=0, +oo, exp(-2*x))
    ***   at top-level: intnum(x=0,+oo,exp(-
    ***                 ^--------------------
@@ -123,9 +118,11 @@ Doc: numerical integration
 
  \misctitle{Note} If $f(x)=\cos(kx)g(x)$ where $g(x)$ tends to zero
  exponentially fast as $\exp(-\alpha x)$, it is up to the user to choose
- between $[[\pm1],\alpha]$ and $[[\pm1],k* I]$, but a good rule of thumb is that
+ between $[\pm\kbd{oo},\alpha]$ and $[\pm\kbd{oo},k* I]$, but a good rule of
+ thumb is that
  if the oscillations are much weaker than the exponential decrease, choose
- $[[\pm1],\alpha]$, otherwise choose $[[\pm1],k* I]$, although the latter can
+ $[\pm\kbd{oo},\alpha]$, otherwise choose $[\pm\kbd{oo},k*I]$, although the
+ latter can
  reasonably be used in all cases, while the former cannot. To take a specific
  example, in the inverse Mellin transform, the integrand is almost always a
  product of an exponentially decreasing and an oscillating factor. If we
@@ -144,7 +141,6 @@ Doc: numerical integration
  decimal digits. We first type
  \bprog
  ? \p 105
- ? oo = [1]  \\@com for clarity
  @eprog
 
  \misctitle{Apparent singularities} Even if the function $f(x)$ represented
diff --git a/src/functions/sums/intnuminit b/src/functions/sums/intnuminit
index 57d734c..a832b51 100644
--- a/src/functions/sums/intnuminit
+++ b/src/functions/sums/intnuminit
@@ -11,8 +11,8 @@ Doc: initialize tables for integration from
  compactness, the possible existence of singularities, the speed of decrease
  or the oscillations at infinity are taken into account, and not the values.
  For instance {\tt intnuminit(-1,1)} is equivalent to {\tt intnuminit(0,Pi)},
- and {\tt intnuminit([0,-1/2],[1])} is equivalent to {\tt
- intnuminit([-1],[-1,-1/2])}. If $m$ is not given, it is computed according to
+ and {\tt intnuminit([0,-1/2],oo)} is equivalent to {\tt
+ intnuminit(-oo,[-1,-1/2])}. If $m$ is not given, it is computed according to
  the current precision. Otherwise the integration step is $1/2^m$. Reasonable
  values of $m$ are $m=6$ or $m=7$ for $100$ decimal digits, and $m=9$ for
  $1000$ decimal digits.
diff --git a/src/functions/sums/sumalt b/src/functions/sums/sumalt
index a1b876b..2de54be 100644
--- a/src/functions/sums/sumalt
+++ b/src/functions/sums/sumalt
@@ -10,19 +10,37 @@ Description:
   (gen,gen,?0):gen:prec sumalt(${2 cookie}, ${2 wrapper}, $1, prec)
   (gen,gen,1):gen:prec sumalt2(${2 cookie}, ${2 wrapper}, $1, prec)
 Doc: numerical summation of the series \var{expr}, which should be an
- \idx{alternating series}, the formal variable $X$ starting at $a$. Use an
- algorithm of Cohen, Villegas and Zagier (\emph{Experiment. Math.} {\bf 9}
- (2000), no.~1, 3--12).
+ \idx{alternating series} $(-1)^k a_k$, the formal variable $X$ starting at
+ $a$. Use an algorithm of Cohen, Villegas and Zagier (\emph{Experiment. Math.}
+ {\bf 9} (2000), no.~1, 3--12).
 
- If $\fl=1$, use a variant with slightly different polynomials. Sometimes
- faster.
+ If $\fl=0$, assuming that that the $a_k$ are the moments of a positive
+ measure on $[0,1]$, the relative error is $O(3+\sqrt8)^(-n)$ after using
+ $a_k$ for $k\leq n$. If \kbd{realprecision} is $p$, we thus set
+ $n = \log(10)p/\log(3+\sqrt8)\approx 1.3 p$; besides the time needed to
+ compute the $a_k$, $k\leq n$, the algorithm overhead is negligible: time
+ $O(p^2)$ and space $O(p)$.
 
- The routine is heuristic and a rigorous proof assumes that the values of
- \var{expr} are the moments of a positive measure on $[0,1]$. Divergent
- alternating series can sometimes be summed by this method, as well as series
- which are not exactly alternating (see for example
- \secref{se:user_defined}). It should be used to try and guess the value of
- an infinite sum. (However, see the example at the end of
+ If $\fl=1$, use a variant with more complicated polynomials, see
+ \tet{polzagier}. If the $a_k$ are the moments of $w(x)dx$ where $w$
+ (or only $xw(x^2)$) is a smooth function extending analytically to the whole
+ complex plane, convergence is in $O(14.4^(-n))$. If $xw(x^2)$ extends
+ analytically to a smaller region, we still have exponential convergence,
+ with worse constants. Usually faster when the computation of $a_k$ is
+ expensive. If \kbd{realprecision} is $p$, we thus set
+ $n = \log(10)p/\log(14.4)\approx 0.86 p$; besides the time needed to
+ compute the $a_k$, $k\leq n$, the algorithm overhead is \emph{not}
+ negligible: time $O(p^3)$ and space $O(p^2)$. Thus, even if the analytic
+ conditions for rigorous use are met, this variant is only worthwile if the
+ $a_k$ are hard to compute, at least $O(p^2)$ individually on average:
+ otherwise we gain a small constant factor (1.5, say) in the number of
+ needed $a_k$ at the expense of a large overhead.
+
+ The conditions for rigorous use are hard to check but the routine is best used
+ heuristically: even divergent alternating series can sometimes be summed by
+ this method, as well as series which are not exactly alternating (see for
+ example \secref{se:user_defined}). It should be used to try and guess the
+ value of an infinite sum. (However, see the example at the end of
  \secref{se:userfundef}.)
 
  If the series already converges geometrically,
diff --git a/src/functions/sums/sumpos b/src/functions/sums/sumpos
index 484d710..c025cf5 100644
--- a/src/functions/sums/sumpos
+++ b/src/functions/sums/sumpos
@@ -23,7 +23,19 @@ Doc: numerical summation of the series \var{expr}, which must be a series of
  have the same sign. As \tet{sumalt}, this function should be used to
  try and guess the value of an infinite sum.
 
- If $\fl=1$, use slightly different polynomials. Sometimes faster.
+ If $\fl=1$, use \kbd{sumalt}$(,1)$ instead of \kbd{sumalt}$(,0)$, see
+ \secref{se:sumalt}. Requiring more stringent analytic properties for
+ rigorous use, but allowing to compute fewer series terms.
+
+ To reach accuracy $10^{-p}$, both algorithms require $O(p^2)$ space;
+ furthermore, assuming the terms decrease polynomially (in $O(n^-C)$), both
+ need to compute $O(p^2)$ terms. The \kbd{sumpos}$(,1)$ variant has a smaller
+ implied constant (roughly 1.5 times smaller). Since the \kbd{sumalt}$(,1)$
+ overhead is now small compared to the time needed to compute series terms,
+ this last variant should be about 1.5 faster. On the other hand, the
+ achieved accuracy may be much worse: as for \tet{sumalt}, since
+ conditions for rigorous use are hard to check, the routine is best used
+ heuristically.
 
  \synt{sumpos}{void *E, GEN (*eval)(void*,GEN),GEN a,long prec}. Also
  available is \tet{sumpos2} with the same arguments ($\fl = 1$).
diff --git a/src/gp/highlvl.c b/src/gp/emacs.c
similarity index 86%
rename from src/gp/highlvl.c
rename to src/gp/emacs.c
index 8c6d1aa..7cf4bf8 100644
--- a/src/gp/highlvl.c
+++ b/src/gp/emacs.c
@@ -13,11 +13,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 
 /*******************************************************************/
 /*                                                                 */
-/*        SOME GP FUNCTION THAT MAY BE USEFUL OUTSIDE OF IT        */
+/*                           EMACS FRONTEND                        */
 /*                                                                 */
 /*******************************************************************/
 #include "pari.h"
 #include "paripriv.h"
 #include "gp.h"
-#include "../graph/rect.h"
-#include "highlvl.h"
+void
+init_emacs(void)
+{
+  GP_DATA->breakloop = 0;
+  disable_color = 1;
+}
diff --git a/src/gp/gp.c b/src/gp/gp.c
index c7af7e2..90d4964 100644
--- a/src/gp/gp.c
+++ b/src/gp/gp.c
@@ -20,343 +20,67 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 #include "paripriv.h"
 #include "gp.h"
 
-#ifdef _WIN32
-#  include <windows.h>
-#  include "../systems/mingw/mingw.h"
-#  ifndef WINCE
-#    include <process.h>
-#  endif
-#endif
-
-/********************************************************************/
-/**                                                                **/
-/**                            STRINGS                             **/
-/**                                                                **/
-/********************************************************************/
-
-static void
-skip_space(char **s) {
-  char *t = *s;
-  while (isspace((int)*t)) t++;
-  *s = t;
-}
-static void
-skip_alpha(char **s) {
-  char *t = *s;
-  while (isalpha((int)*t)) t++;
-  *s = t;
-}
-
-static char *
-translate(char **src, char *s, char *entry)
-{
-  char *t = *src;
-  while (*t)
-  {
-    while (*t == '\\')
-    {
-      switch(*++t)
-      {
-        case 'e':  *s='\033'; break; /* escape */
-        case 'n':  *s='\n'; break;
-        case 't':  *s='\t'; break;
-        default:   *s=*t;
-                   if (!*t) pari_err(e_SYNTAX,"unfinished string",s,entry);
-      }
-      t++; s++;
-    }
-    if (*t == '"')
-    {
-      if (t[1] != '"') break;
-      t += 2; continue;
-    }
-    *s++ = *t++;
-  }
-  *s=0; *src=t; return s;
-}
+static jmp_buf *env;
+static pari_stack s_env;
+void (*cb_gp_output)(GEN z) = NULL;
+void (*cb_pari_end_output)(void) = NULL;
 
 static void
-matchQ(char *s, char *entry)
-{
-  if (*s != '"')
-    pari_err(e_SYNTAX,"expected character: '\"' instead of",s,entry);
-}
-
-/*  Read a "string" from src. Format then copy it, starting at s. Return
- *  pointer to char following the end of the input string */
-static char *
-readstring(char *src, char *s, char *entry)
+gp_ask_confirm(const char *s)
 {
-  matchQ(src, entry); src++; s = translate(&src, s, entry);
-  matchQ(src, entry); return src+1;
+  err_printf(s);
+  err_printf(". OK ? (^C if not)\n");
+  pari_hit_return();
 }
-/*******************************************************************/
-/**                                                               **/
-/**                    TEXMACS-SPECIFIC STUFF                     **/
-/**                                                               **/
-/*******************************************************************/
-static int tm_is_waiting = 0, tm_did_complete = 0;
 
-/* tell TeXmacs GP will start outputing data */
+/* numerr < 0: from SIGINT */
 static void
-tm_start_output(void)
+gp_err_recover(long numerr)
 {
-  if (!tm_is_waiting) { printf("%cverbatim:",DATA_BEGIN); fflush(stdout); }
-  tm_is_waiting = 1;
+  longjmp(env[s_env.n-1], numerr);
 }
-/* tell TeXmacs GP is done and is waiting for new data */
+/* numerr < 0: from SIGINT */
 static void
-tm_end_output(void)
-{
-  if (tm_is_waiting) { printf("%c", DATA_END); fflush(stdout); }
-  tm_is_waiting = 0;
-}
-static char *
-fgets_texmacs(char *s, int n, FILE *f)
+gp_pre_recover(long numerr)
 {
-  if (!tm_did_complete)
+  if (numerr>=0)
   {
-    tm_start_output(); tm_end_output(); /* tell TeXmacs we need input */
+    out_puts(pariErr, "\n"); pariErr->flush();
   }
-  return fgets(s,n,f);
+  longjmp(env[s_env.n-1], numerr);
 }
 
-#ifdef READLINE
-typedef struct {
-  char *cmd;
-  long n; /* number of args */
-  char **v; /* args */
-} tm_cmd;
-
 static void
-parse_texmacs_command(tm_cmd *c, const char *ch)
+reset_ctrlc(void)
 {
-  long l = strlen(ch);
-  char *t, *s = (char*)ch, *send = s+l-1;
-  char **A;
-  pari_stack s_A;
-
-  if (*s != DATA_BEGIN || *send-- != DATA_END)
-    pari_err(e_MISC, "missing DATA_[BEGIN | END] in TeXmacs command");
-  s++;
-  if (strncmp(s, "special:", 8)) pari_err(e_MISC, "unrecognized TeXmacs command");
-  s += 8;
-  if (*s != '(' || *send-- != ')')
-    pari_err(e_MISC, "missing enclosing parentheses for TeXmacs command");
-  s++; t = s;
-  skip_alpha(&s);
-  c->cmd = pari_strndup(t, s - t);
-  pari_stack_init(&s_A,sizeof(*A),(void**)&A);
-  for (c->n = 0; s <= send; c->n++)
-  {
-    char *u = (char*)pari_malloc(strlen(s) + 1);
-    skip_space(&s);
-    if (*s == '"') s = readstring(s, u, t);
-    else
-    { /* read integer */
-      t = s;
-      while (isdigit((int)*s)) s++;
-      strncpy(u, t, s - t); u[s-t] = 0;
-    }
-    pari_stack_pushp(&s_A, u);
-  }
-  c->v = A;
+#if defined(_WIN32) || defined(__CYGWIN32__)
+  win32ctrlc = 0;
+#endif
 }
 
-static void
-free_cmd(tm_cmd *c)
-{
-  while (c->n--) pari_free((void*)c->v[c->n]);
-  pari_free((void*)c->v);
-}
+static int
+is_silent(char *s) { return s[strlen(s) - 1] == ';'; }
 
-static void
-handle_texmacs_command(const char *s)
-{
-  tm_cmd c;
-  parse_texmacs_command(&c, s);
-  if (strcmp(c.cmd, "complete"))
-    pari_err(e_MISC,"Texmacs_stdin command %s not implemented", c.cmd);
-  if (c.n != 2)
-    pari_err(e_MISC,"was expecting 2 arguments for Texmacs_stdin command");
-  texmacs_completion(c.v[0], atol(c.v[1]));
-  free_cmd(&c);
-  tm_did_complete = 1;
-}
-#else
-static void
-handle_texmacs_command(const char *s)
-{ (void)s;pari_err(e_MISC, "readline not available"); }
-#endif
+static int stdin_isatty = 0;
+static int
+is_interactive(void)
+{ return pari_infile == stdin && stdin_isatty; }
 
 /*******************************************************************/
 /**                                                               **/
-/**                          BUFFERS                              **/
+/**                        INITIALIZATION                         **/
 /**                                                               **/
 /*******************************************************************/
-static Buffer **bufstack;
-static pari_stack s_bufstack;
-
-static void
-pop_buffer(void)
-{
-  if (s_bufstack.n)
-    delete_buffer( bufstack[ --s_bufstack.n ] );
-}
-
-/* kill all buffers until B is met or nothing is left */
-static void
-kill_buffers_upto(Buffer *B)
-{
-  while (s_bufstack.n) {
-    if (bufstack[ s_bufstack.n-1 ] == B) break;
-    pop_buffer();
-  }
-}
-static void
-kill_buffers_upto_including(Buffer *B)
-{
-  while (s_bufstack.n) {
-    if (bufstack[ s_bufstack.n-1 ] == B) { pop_buffer(); break; }
-    pop_buffer();
-  }
-}
-
-/********************************************************************/
-/**                                                                **/
-/**                             HELP                               **/
-/**                                                                **/
-/********************************************************************/
-static int disable_exception_handler = 0;
-#define BLOCK_EH_START                \
-{                                     \
-  int block=disable_exception_handler;\
-  disable_exception_handler = 1;
-
-#define BLOCK_EH_END                \
-  disable_exception_handler = block;\
-}
-static char *Help;
-
-static char *
-init_help(void)
-{
-  char *h = os_getenv("GPHELP");
-# ifdef GPHELP
-  if (!h) h = (char*)GPHELP;
-# endif
-#ifdef _WIN32
-  win32_set_pdf_viewer();
-#endif
-  if (h) h = pari_strdup(h);
-  return h;
-}
-
-static void
-hit_return(void)
-{
-  int c;
-  if (GP_DATA->flags & (gpd_EMACS|gpd_TEXMACS)) return;
-  BLOCK_EH_START
-  pari_puts("/*-- (type RETURN to continue) --*/");
-  pari_flush();
-  /* if called from a readline callback, may be in a funny TTY mode */
-  do c = fgetc(stdin); while (c >= 0 && c != '\n' && c != '\r');
-  pari_putc('\n');
-  BLOCK_EH_END
-}
-static void
-gp_ask_confirm(const char *s)
-{
-  err_printf(s);
-  err_printf(". OK ? (^C if not)\n");
-  hit_return();
-}
-
-static int
-has_ext_help(void) { return (Help && *Help); }
-
-static int
-compare_str(char **s1, char **s2) { return strcmp(*s1, *s2); }
-
-/* Print all elements of list in columns, pausing every nbli lines
- * if nbli is non-zero.
- * list is a NULL terminated list of function names
- */
-void
-print_fun_list(char **list, long nbli)
-{
-  long i=0, j=0, maxlen=0, nbcol,len, w = term_width();
-  char **l;
-
-  while (list[i]) i++;
-  qsort (list, i, sizeof(char *), (QSCOMP)compare_str);
-
-  for (l=list; *l; l++)
-  {
-    len = strlen(*l);
-    if (len > maxlen) maxlen=len;
-  }
-  maxlen++; nbcol= w / maxlen;
-  if (nbcol * maxlen == w) nbcol--;
-  if (!nbcol) nbcol = 1;
-
-  pari_putc('\n'); i=0;
-  for (l=list; *l; l++)
-  {
-    pari_puts(*l); i++;
-    if (i >= nbcol)
-    {
-      i=0; pari_putc('\n');
-      if (nbli && j++ > nbli) { j = 0; hit_return(); }
-      continue;
-    }
-    len = maxlen - strlen(*l);
-    while (len--) pari_putc(' ');
-  }
-  if (i) pari_putc('\n');
-}
-
-static void
-commands(long n)
-{
-  long i;
-  entree *ep;
-  char **t_L;
-  pari_stack s_L;
-
-  pari_stack_init(&s_L, sizeof(*t_L), (void**)&t_L);
-  for (i = 0; i < functions_tblsz; i++)
-    for (ep = functions_hash[i]; ep; ep = ep->next)
-    {
-      long m;
-      switch (EpVALENCE(ep))
-      {
-        case EpVAR:
-          if (typ((GEN)ep->value) == t_CLOSURE) break;
-          /* fall through */
-        case EpNEW: continue;
-      }
-      m = ep->menu;
-      if ((n < 0 && m && m < 13) || m == n) pari_stack_pushp(&s_L, (void*)ep->name);
-    }
-  pari_stack_pushp(&s_L, NULL);
-  print_fun_list(t_L, term_height()-4);
-  pari_stack_delete(&s_L);
-}
-
 static void
-center(const char *s)
+print_shortversion(void)
 {
-  long i, l = strlen(s), pad = term_width() - l;
-  char *buf, *u;
+  const ulong mask = (1UL<<PARI_VERSION_SHIFT) - 1;
+  ulong n = paricfg_version_code, major, minor, patch;
 
-  if (pad<0) pad=0; else pad >>= 1;
-  u = buf = (char*)pari_malloc(l + pad + 2);
-  for (i=0; i<pad; i++) *u++ = ' ';
-  while (*s) *u++ = *s++;
-  *u++ = '\n'; *u = 0;
-  pari_puts(buf); pari_free(buf);
+  patch = n & mask; n >>= PARI_VERSION_SHIFT;
+  minor = n & mask; n >>= PARI_VERSION_SHIFT;
+  major = n;
+  printf("%lu.%lu.%lu\n", major,minor,patch); exit(0);
 }
 
 static void
@@ -378,1255 +102,262 @@ usage(char *s)
 }
 
 static void
-community(void)
-{
-  print_text("The PARI/GP distribution includes a reference manual, a \
-tutorial, a reference card and quite a few examples. They have been installed \
-in the directory ");
-  pari_puts("  ");
-  pari_puts(pari_datadir);
-  pari_puts("\nYou can also download them from http://pari.math.u-bordeaux.fr/.\
-\n\nThree mailing lists are devoted to PARI:\n\
-  - pari-announce (moderated) to announce major version changes.\n\
-  - pari-dev for everything related to the development of PARI, including\n\
-    suggestions, technical questions, bug reports and patch submissions.\n\
-  - pari-users for everything else!\n\
-To subscribe, send an empty message to\n\
-  <pari_list_name>-request at pari.math.u-bordeaux.fr\n\
-with a Subject: field containing the word 'subscribe'.\n\n");
-  print_text("An archive is kept at the WWW site mentioned above. You can also \
-reach the authors at pari at math.u-bordeaux.fr (answer not guaranteed)."); }
-
-static void
-gentypes(void)
-{
-  pari_puts("List of the PARI types:\n\
-  t_INT    : long integers     [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ]\n\
-  t_REAL   : long real numbers [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ]\n\
-  t_INTMOD : integermods       [ code ] [ mod  ] [ integer ]\n\
-  t_FRAC   : irred. rationals  [ code ] [ num. ] [ den. ]\n\
-  t_FFELT  : finite field elt. [ code ] [ cod2 ] [ elt ] [ mod ] [ p ]\n\
-  t_COMPLEX: complex numbers   [ code ] [ real ] [ imag ]\n\
-  t_PADIC  : p-adic numbers    [ cod1 ] [ cod2 ] [ p ] [ p^r ] [ int ]\n\
-  t_QUAD   : quadratic numbers [ cod1 ] [ mod  ] [ real ] [ imag ]\n\
-  t_POLMOD : poly mod          [ code ] [ mod  ] [ polynomial ]\n\
-  -------------------------------------------------------------\n\
-  t_POL    : polynomials       [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ]\n\
-  t_SER    : power series      [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ]\n\
-  t_RFRAC  : irred. rat. func. [ code ] [ num. ] [ den. ]\n\
-  t_QFR    : real qfb          [ code ] [ a ] [ b ] [ c ] [ del ]\n\
-  t_QFI    : imaginary qfb     [ code ] [ a ] [ b ] [ c ]\n\
-  t_VEC    : row vector        [ code ] [  x_1  ] ... [  x_k  ]\n\
-  t_COL    : column vector     [ code ] [  x_1  ] ... [  x_k  ]\n\
-  t_MAT    : matrix            [ code ] [ col_1 ] ... [ col_k ]\n\
-  t_LIST   : list              [ code ] [ n ] [ nmax ][ vec ]\n\
-  t_STR    : string            [ code ] [ man_1 ] ... [ man_k ]\n\
-  t_VECSMALL: vec. small ints  [ code ] [ x_1 ] ... [ x_k ]\n\
-  t_CLOSURE: functions [ code ] [ arity ] [ code ] [ operand ] [ data ] [ text ]\n\
-  t_ERROR  : error context     [ code ] [ errnum ] [ dat_1 ] ... [ dat_k ]\n\
-\n");
-}
-
-static void
-menu_commands(void)
-{
-  pari_puts("Help topics: for a list of relevant subtopics, type ?n for n in\n\
-  0: user-defined functions (aliases, installed and user functions)\n\
-  1: Standard monadic or dyadic OPERATORS\n\
-  2: CONVERSIONS and similar elementary functions\n\
-  3: TRANSCENDENTAL functions\n\
-  4: NUMBER THEORETICAL functions\n\
-  5: Functions related to ELLIPTIC CURVES\n\
-  6: Functions related to general NUMBER FIELDS\n\
-  7: POLYNOMIALS and power series\n\
-  8: Vectors, matrices, LINEAR ALGEBRA and sets\n\
-  9: SUMS, products, integrals and similar functions\n\
- 10: GRAPHIC functions\n\
- 11: PROGRAMMING under GP\n\
- 12: The PARI community\n\
-\n\
-Also:\n\
-  ? functionname (short on-line help)\n\
-  ?\\             (keyboard shortcuts)\n\
-  ?.             (member functions)\n");
-  if (has_ext_help()) pari_puts("\
-Extended help (if available):\n\
-  ??             (opens the full user's manual in a dvi previewer)\n\
-  ??  tutorial / refcard / libpari (tutorial/reference card/libpari manual)\n\
-  ??  keyword    (long help text about \"keyword\" from the user's manual)\n\
-  ??? keyword    (a propos: list of related functions).");
-}
-
-static void
-slash_commands(void)
-{
-  pari_puts("#       : enable/disable timer\n\
-##      : print time for last result\n\
-\\\\      : comment up to end of line\n\
-\\a {n}  : print result in raw format (readable by PARI)\n\
-\\B {n}  : print result in beautified format\n\
-\\c      : list all commands (same effect as ?*)\n\
-\\d      : print all defaults\n\
-\\e {n}  : enable/disable echo (set echo=n)\n\
-\\g {n}  : set debugging level\n\
-\\gf{n}  : set file debugging level\n\
-\\gm{n}  : set memory debugging level\n\
-\\h {m-n}: hashtable information\n\
-\\l {f}  : enable/disable logfile (set logfile=f)\n\
-\\m {n}  : print result in prettymatrix format\n\
-\\o {n}  : set output method (0=raw, 1=prettymatrix, 2=prettyprint, 3=2-dim)\n\
-\\p {n}  : change real precision\n\
-\\ps{n}  : change series precision\n\
-\\q      : quit completely this GP session\n\
-\\r {f}  : read in a file\n\
-\\s      : print stack information\n\
-\\t      : print the list of PARI types\n\
-\\u      : print the list of user-defined functions\n\
-\\um     : print the list of user-defined member functions\n\
-\\v      : print current version of GP\n\
-\\w {nf} : write to a file\n\
-\\x {n}  : print complete inner structure of result\n\
-\\y {n}  : disable/enable automatic simplification (set simplify=n)\n\
-\n\
-{f}=optional filename. {n}=optional integer\n");
-}
-
-static void
-member_commands(void)
+gp_head(void)
 {
-  pari_puts("\
-Member functions, followed by relevant objects\n\n\
-a1-a6, b2-b8, c4-c6 : coeff. of the curve.         ell\n\
-area : area                                        ell\n\
-bid  : big ideal                     bid,                     bnr\n\
-bnf  : big number field                                   bnf,bnr\n\
-clgp : class group                   bid,                 bnf,bnr\n\
-cyc  : cyclic decomposition (SNF)    bid,     clgp,ell,   bnf,bnr\n\
-diff, codiff: different and codifferent                nf,bnf,bnr\n\
-disc : discriminant                                ell,nf,bnf,bnr,rnf\n\
-e, f : inertia/residue  degree           prid\n\
-fu   : fundamental units                                  bnf,bnr\n\
-gen  : generators                    bid,prid,clgp,ell,   bnf,bnr,    gal\n\
-group: group                                       ell,          ,rnf,gal\n\
-index: index                                           nf,bnf,bnr\n\
-j    : j-invariant                                 ell\n");
-/* split: some compilers can't handle long constant strings */
-  pari_puts("\
-mod  : modulus                       bid,                     bnr,    gal\n\
-nf   : number field                                    nf,bnf,bnr,rnf\n\
-no   : number of elements            bid,     clgp,ell,   bnf,bnr\n\
-omega, eta: [w1,w2] and [eta1, eta2]               ell\n\
-orders: relative orders of generators                                 gal\n\
-p    : rational prime                    prid,     ell,           rnf,gal\n\
-pol  : defining polynomial                             nf,bnf,bnr,    gal\n\
-polabs: defining polynomial over Q                                rnf\n\
-reg  : regulator                                          bnf,bnr\n\
-roots: roots                                       ell,nf,bnf,bnr,    gal\n\
-sign,r1,r2 : signature                                 nf,bnf,bnr\n\
-t2   : t2 matrix                                       nf,bnf,bnr\n\
-tate : Tate's [u^2, u, q, [a,b]]                   ell\n\
-tu   : torsion unit and its order                         bnf,bnr\n\
-zk   : integral basis                                  nf,bnf,bnr,rnf\n\
-zkst : structure of (Z_K/m)*         bid,                     bnr\n");
+  pari_print_version();
+  pari_putc('\n');
+  pari_center("Copyright (C) 2000-2015 The PARI Group");
+  pari_putc('\n');
+  print_text("PARI/GP is free software, covered by the GNU General Public \
+License, and comes WITHOUT ANY WARRANTY WHATSOEVER.");
+  pari_puts("\nType ? for help, \\q to quit.\n");
+  print_text("Type ?14 for how to get moral (and possibly technical) support.");
+  if (pari_mainstack->vsize)
+    pari_printf("\nparisizemax = %lu, primelimit = %lu",
+                pari_mainstack->vsize,GP_DATA->primelimit);
+  else
+    pari_printf("\nparisize = %lu, primelimit = %lu",
+                pari_mainstack->rsize,GP_DATA->primelimit);
+  if (pari_mt_nbthreads > 1)
+    pari_printf(", nbthreads = %lu", pari_mt_nbthreads);
+  pari_putc('\n');
 }
 
-#define QUOTE "_QUOTE"
-#define DOUBQUOTE "_DOUBQUOTE"
-#define BACKQUOTE "_BACKQUOTE"
-
 static char *
-_cat(char *s, const char *t)
+read_arg(long *nread, char *t, long argc, char **argv)
 {
-  *s = 0; strcat(s,t); return s + strlen(t);
+  long i = *nread;
+  if (isdigit((int)*t)) return t;
+  if (*t || i==argc) usage(argv[0]);
+  *nread = i+1; return argv[i];
 }
 
 static char *
-filter_quotes(const char *s)
-{
-  int i, l = strlen(s);
-  int quote = 0;
-  int backquote = 0;
-  int doubquote = 0;
-  char *str, *t;
-
-  for (i=0; i < l; i++)
-    switch(s[i])
-    {
-      case '\'': quote++; break;
-      case '`' : backquote++; break;
-      case '"' : doubquote++;
-    }
-  str = (char*)pari_malloc(l + quote * (strlen(QUOTE)-1)
-                          + doubquote * (strlen(DOUBQUOTE)-1)
-                          + backquote * (strlen(BACKQUOTE)-1) + 1);
-  t = str;
-  for (i=0; i < l; i++)
-    switch(s[i])
-    {
-      case '\'': t = _cat(t, QUOTE); break;
-      case '`' : t = _cat(t, BACKQUOTE); break;
-      case '"' : t = _cat(t, DOUBQUOTE); break;
-      default: *t++ = s[i];
-    }
-  *t = 0; return str;
-}
-
-static int
-nl_read(char *s) { size_t l = strlen(s); return s[l-1] == '\n'; }
-
-#define nbof(a) sizeof(a) / sizeof(a[0])
-/* query external help program for s. num < 0 [keyword] or chapter number */
-static void
-external_help(const char *s, int num)
-{
-  long nbli = term_height()-3, li = 0;
-  char buf[256], *str;
-  const char *opt = "", *ar = "", *cdir = "";
-  char *t, *help = Help;
-  pariFILE *z;
-  FILE *f;
-
-  if (!has_ext_help()) pari_err(e_MISC,"no external help program");
-  t = filter_quotes(s);
-  if (num < 0)
-    opt = "-k";
-  else if (t[strlen(t)-1] != '@')
-    ar = stack_sprintf("@%d",num);
-#ifdef _WIN32
-  if (*help=='@')
-  {
-    const char *basedir = win32_basedir();
-    help++;
-    cdir = stack_sprintf("%c:& cd %s & ", *basedir, basedir);
-  }
-#endif
-  str=stack_sprintf("%s%s -fromgp %s %c%s%s%c",cdir,help,opt,
-                                               SHELL_Q,t,ar,SHELL_Q);
-  z = try_pipe(str,0); f = z->file;
-  pari_free(t);
-  while (fgets(buf, nbof(buf), f))
-  {
-    if (!strncmp("ugly_kludge_done",buf,16)) break;
-    pari_puts(buf);
-    if (nl_read(buf) && ++li > nbli) { hit_return(); li = 0; }
-  }
-  pari_fclose(z);
-}
-
-const char *keyword_list[]={
-  "operator",
-  "libpari",
-  "member",
-  "integer",
-  "real",
-  "readline",
-  "refcard",
-  "tutorial",
-  "nf",
-  "bnf",
-  "bnr",
-  "ell",
-  "rnf",
-  "bid",
-  "modulus",
-  "prototype",
-  NULL
-};
-
-static int
-ok_external_help(char **s)
+read_arg_equal(long *nread, char *t, long argc, char **argv)
 {
-  long n;
-  if (!**s) return 1;
-  if (!isalpha((int)**s)) return 3; /* operator or section number */
-  if (!strncmp(*s,"t_",2)) { *s += 2; return 2; } /* type name */
-
-  for (n=0; keyword_list[n]; n++)
-    if (!strcmp(*s,keyword_list[n])) return 3;
-  return 0;
+  long i = *nread;
+  if (*t=='=' && isdigit((int)t[1])) return t+1;
+  if (*t || i==argc) usage(argv[0]);
+  *nread = i+1; return argv[i];
 }
 
 static void
-cut_trailing_garbage(char *s)
+init_trivial_stack(void)
 {
-  char c;
-  while ( (c = *s++) )
-  {
-    if (c == '\\' && ! *s++) return; /* gobble next char, return if none. */
-    if (!is_keyword_char(c) && c != '@') { s[-1] = 0; return; }
-  }
+  const size_t s = 2048;
+  pari_mainstack->size = s;
+  pari_mainstack->bot = (pari_sp)pari_malloc(s);
+  avma = pari_mainstack->top = pari_mainstack->bot + s;
 }
 
 static void
-digit_help(char *s, long flag)
+free_trivial_stack(void)
 {
-  long n = atoi(s);
-  if (n < 0 || n > 15) pari_err(e_SYNTAX,"no such section in help: ?",s,s);
-  if (n == 12)
-    community();
-  else if (flag & h_LONG)
-    external_help(s,3);
-  else
-    commands(n);
-  return;
+  free((void*)pari_mainstack->bot);
 }
 
+typedef struct { char *key, *val; } pair_t;
+/* If ab of the form key=val, record pair in new stack entry
+ * P[n].key must be freed by caller to avoid memory leak */
 static void
-simple_help(const char *s1, const char *s2) { pari_printf("%s: %s\n", s1, s2); }
-
-static void
-default_help(char *s, long flag)
+record_default(pari_stack *s_P, char *ab)
 {
-  if (flag & h_LONG)
-    external_help(stack_strcat("se:def,",s),3);
-  else
-    simple_help(s,"default");
+  pair_t *P = (pair_t*)*pari_stack_base(s_P);
+  char *k, *v;
+  long n;
+  ab = pari_strdup(ab);
+  parse_key_val(ab, &k, &v);
+  n = pari_stack_new(s_P);
+  P[n].key = k;
+  P[n].val = v;
 }
-
 static void
-aide0(const char *s0, int flag)
+read_opt(pari_stack *p_A, long argc, char **argv)
 {
-  const long long_help = flag & h_LONG;
-  long n;
-  entree *ep;
-  char *s = get_sep(s0);
-
-  if (isdigit((int)*s)) { digit_help(s,flag); return; }
-  if (flag & h_APROPOS) { external_help(s,-1); return; }
-  /* Get meaningful answer on '\ps 5' (e.g. from <F1>) */
-  if (*s == '\\') { char *t = s+1; skip_alpha(&t); *t = '\0'; }
-  if (isalpha((int)*s))
-  {
-    if (!strncmp(s, "default", 7))
-    { /* special-case ?default(dft_name), e.g. default(log) */
-      char *t = s+7;
-      skip_space(&t);
-      if (*t == '(')
-      {
-        t++; skip_space(&t);
-        cut_trailing_garbage(t);
-        if (pari_is_default(t)) { default_help(t,flag); return; }
-      }
-    }
-    cut_trailing_garbage(s);
-  }
-
-  if (long_help && (n = ok_external_help(&s))) { external_help(s,n); return; }
-  switch (*s)
-  {
-    case '*' : commands(-1); return;
-    case '\0': menu_commands(); return;
-    case '\\': slash_commands(); return;
-    case '.' : member_commands(); return;
-  }
-  ep = is_entry(s);
-  if (!ep)
-  {
-    if (pari_is_default(s))
-      default_help(s,flag);
-    else if (long_help)
-      external_help(s,3);
-    else if (!cb_pari_whatnow(pariOut, s,1))
-      simple_help(s,"unknown identifier");
-    return;
-  }
-
-  if (EpVALENCE(ep) == EpALIAS)
-  {
-    pari_printf("%s is aliased to:\n\n",s);
-    ep = do_alias(ep);
-  }
-  switch(EpVALENCE(ep))
-  {
-    case EpVAR:
-      if (!ep->help)
-      {
-        if (typ((GEN)ep->value)!=t_CLOSURE)
-          simple_help(s, "user defined variable");
-        else
-        {
-          GEN str = closure_get_text((GEN)ep->value);
-          if (typ(str) == t_VEC)
-            pari_printf("%s =\n  %Ps\n", ep->name, ep->value);
-        }
-        return;
-      }
-      break;
-
-    case EpINSTALL:
-      if (!ep->help) { simple_help(s, "installed function"); return; }
-      break;
-
-    case EpNEW:
-      if (!ep->help) { simple_help(s, "new identifier"); return; };
-      break;
+  pair_t *P;
+  pari_stack s_P; /* key / value to record default() settings */
+  char *b = NULL, *p = NULL, *s = NULL;
+  ulong f = GP_DATA->flags;
+  long i = 1, initrc = 1;
 
-    default: /* built-in function */
-      if (!ep->help) pari_err_BUG("aide (no help found)"); /*paranoia*/
-      if (long_help) { external_help(ep->name,3); return; }
-  }
-  print_text(ep->help);
-}
+  (void)&p; (void)&b; (void)&s; /* -Wall gcc-2.95 */
 
-void
-aide(const char *s, long flag)
-{
-  pari_sp av = avma;
-  if ((flag & h_RL) == 0)
+  pari_stack_init(&s_P,sizeof(*P),(void**)&P);
+  pari_stack_alloc(&s_P, 64);
+  pari_outfile = stderr;
+  while (i < argc)
   {
-    if (*s == '?') { flag |= h_LONG; s++; }
-    if (*s == '?') { flag |= h_APROPOS; s++; }
-  }
-  term_color(c_HELP); aide0(s,flag); term_color(c_NONE);
-  if ((flag & h_RL) == 0) pari_putc('\n');
-  avma = av;
-}
+    char *t = argv[i];
 
-/********************************************************************/
-/**                                                                **/
-/**                         GP HEADER                              **/
-/**                                                                **/
-/********************************************************************/
-static char *
-what_readline(void)
-{
-#ifdef READLINE
-  const char *v = READLINE;
-  char *s = stack_malloc(3 + strlen(v) + 8);
-  (void)sprintf(s, "v%s %s", v, GP_DATA->use_readline? "enabled": "disabled");
-  return s;
-#else
-  return (char*)"not compiled in";
-#endif
-}
-
-static void
-print_shortversion(void)
-{
-  const ulong mask = (1UL<<PARI_VERSION_SHIFT) - 1;
-  ulong n = paricfg_version_code, major, minor, patch;
-
-  patch = n & mask; n >>= PARI_VERSION_SHIFT;
-  minor = n & mask; n >>= PARI_VERSION_SHIFT;
-  major = n;
-  printf("%lu.%lu.%lu\n", major,minor,patch); exit(0);
-}
-
-static char *
-what_cc(void)
-{
-  char *s;
-#ifdef GCC_VERSION
-#  ifdef __cplusplus
-#    define Format "(C++) %s"
-#  else
-#    define Format "%s"
-#  endif
-  s = stack_malloc(6 + strlen(GCC_VERSION) + 1);
-  (void)sprintf(s, Format, GCC_VERSION);
-#else
-#  ifdef _MSC_VER
-  s = stack_malloc(32);
-  (void)sprintf(s, "MSVC-%i", _MSC_VER);
-#  else
-  s = NULL;
-#  endif
-#endif
-  return s;
-}
-
-static void
-print_version(void)
-{
-  pari_sp av = avma;
-  char *buf, *ver = what_cc();
-  const char *date = paricfg_compiledate;
-
-  center(paricfg_version);
-  center(paricfg_buildinfo);
-  buf = stack_malloc(strlen(date) +  32 + (ver? strlen(ver): 0));
-  if (ver) (void)sprintf(buf, "compiled: %s, %s", date, ver);
-  else     (void)sprintf(buf, "compiled: %s", date);
-  center(buf);
-  sprintf(buf, "threading engine: %s",paricfg_mt_engine);
-  center(buf);
-  ver = what_readline();
-  buf = stack_malloc(strlen(ver) + 64);
-  (void)sprintf(buf, "(readline %s, extended help%s enabled)", ver,
-                has_ext_help()? "": " not");
-  center(buf); avma = av;
-}
-
-static void
-gp_head(void)
-{
-#ifdef READLINE
-  if (GP_DATA->flags & gpd_TEXMACS)
-    printf("%ccommand:(cas-supports-completions-set! \"pari\")%c\n",
-           DATA_BEGIN, DATA_END);
-#endif
-  print_version();
-  pari_putc('\n');
-  center("Copyright (C) 2000-2014 The PARI Group");
-  pari_putc('\n');
-  print_text("PARI/GP is free software, covered by the GNU General Public \
-License, and comes WITHOUT ANY WARRANTY WHATSOEVER.");
-  pari_puts("\nType ? for help, \\q to quit.\n");
-  print_text("Type ?12 for how to get moral (and possibly technical) support.");
-  pari_printf("\nparisize = %lu, primelimit = %lu\n",
-              top - bot, GP_DATA->primelimit);
-}
-
-/********************************************************************/
-/**                                                                **/
-/**                         METACOMMANDS                           **/
-/**                                                                **/
-/********************************************************************/
-#define pariputs_opt(s) if (!(GP_DATA->flags & gpd_QUIET)) pari_puts(s)
-
-void
-gp_quit(long exitcode)
-{
-  if (Help) pari_free((void*)Help);
-  free_graph();
-  pari_close();
-  kill_buffers_upto(NULL);
-  pariputs_opt("Goodbye!\n");
-  if (GP_DATA->flags & gpd_TEXMACS) tm_end_output();
-  exit(exitcode);
-}
-
-static GEN
-gpreadbin(const char *s, int *vector)
-{
-  GEN x = readbin(s,pari_infile, vector);
-  popinfile();
-  if (!x) pari_err_FILE("input file",s);
-  return x;
-}
-
-static void
-escape(char *tch, int ismain)
-{
-  const char *s;
-  char c;
-
-  if (compatible != NONE)
-  {
-    s = tch;
-    while (*s)
-      if (*s++ == '=')
-      {
-        GEN (*f)(const char *v, long flag) = NULL;
-        long len = (s-tch) - 1;
-        if      (!strncmp(tch,"precision",len))    f = sd_realprecision;
-        else if (!strncmp(tch,"serieslength",len)) f = sd_seriesprecision;
-        else if (!strncmp(tch,"format",len))       f = sd_format;
-        else if (!strncmp(tch,"prompt",len))       f = sd_prompt;
-        if (f) { (void)f(s, d_ACKNOWLEDGE); return; }
+    if (*t++ != '-') break;
+    i++;
+START:
+    switch(*t++)
+    {
+      case 'p': p = read_arg(&i,t,argc,argv); break;
+      case 's': s = read_arg(&i,t,argc,argv); break;
+      case 'e':
+        f |= gpd_EMACS; if (*t) goto START;
         break;
-      }
-  }
-  s = tch;
-  switch ((c = *s++))
-  {
-    case 'w': case 'x': case 'a': case 'b': case 'B': case 'm':
-    { /* history things */
-      long d;
-      GEN x;
-      if (c != 'w' && c != 'x') d = get_int(s,0);
-      else
-      {
-        d = atol(s); if (*s == '-') s++;
-        while (isdigit((int)*s)) s++;
-      }
-      x = gp_history(GP_DATA->hist, d, tch+1,tch-1);
-      switch (c)
-      {
-        case 'B':
-        { /* prettyprinter */
-          gp_data G = *GP_DATA; /* copy */
-          gp_hist   h = *(G.hist); /* copy */
-          pariout_t f = *(G.fmt);  /* copy */
-
-          G.hist = &h; h.total = 0; /* no hist number */
-          G.fmt  = &f; f.prettyp = f_PRETTY;
-          G.flags &= ~(gpd_TEST|gpd_TEXMACS);
-          G.lim_lines = 0;
-          gp_output(x, &G); break;
+      case 'q':
+        f |= gpd_QUIET; if (*t) goto START;
+        break;
+      case 't':
+        f |= gpd_TEST; if (*t) goto START;
+        break;
+      case 'f':
+        initrc = 0; if (*t) goto START;
+        break;
+      case 'D':
+        if (*t || i == argc) usage(argv[0]);
+        record_default(&s_P, argv[i++]);
+        break;
+      case '-':
+        if (strcmp(t, "version-short") == 0) { print_shortversion(); exit(0); }
+        if (strcmp(t, "version") == 0) {
+          init_trivial_stack(); pari_print_version();
+          free_trivial_stack(); exit(0);
         }
-        case 'a': brute   (x, GP_DATA->fmt->format, -1); break;
-        case 'b': /* fall through */
-        case 'm': matbrute(x, GP_DATA->fmt->format, -1); break;
-        case 'x': dbgGEN(x, get_int(s, -1)); break;
-        case 'w':
-          s = get_sep(s); if (!*s) s = current_logfile;
-          write0(s, mkvec(x)); return;
-      }
-      pari_putc('\n'); return;
-    }
-
-    case 'c': commands(-1); break;
-    case 'd': (void)setdefault(NULL,NULL,d_SILENT); break;
-    case 'e':
-      s = get_sep(s);
-      if (!*s) s = (GP_DATA->echo)? "0": "1";
-      (void)sd_echo(s,d_ACKNOWLEDGE); break;
-    case 'g':
-      switch (*s)
-      {
-        case 'm': s++; (void)sd_debugmem(*s? s: NULL,d_ACKNOWLEDGE); break;
-        case 'f': s++; (void)sd_debugfiles(*s? s: NULL,d_ACKNOWLEDGE); break;
-        default : (void)sd_debug(*s? s: NULL,d_ACKNOWLEDGE); break;
-      }
-      break;
-    case 'h': print_functions_hash(s); break;
-    case 'l':
-      s = get_sep(s);
-      if (*s)
-      {
-        (void)sd_logfile(s,d_ACKNOWLEDGE);
-        if (pari_logfile) break;
-      }
-      (void)sd_log(pari_logfile?"0":"1",d_ACKNOWLEDGE);
-      break;
-    case 'o': (void)sd_output(*s? s: NULL,d_ACKNOWLEDGE); break;
-    case 'p':
-      switch (*s)
-      {
-        case 's': s++;
-          (void)sd_seriesprecision(*s? s: NULL,d_ACKNOWLEDGE); break;
-        default :
-          (void)sd_realprecision(*s? s: NULL,d_ACKNOWLEDGE); break;
-      }
-      break;
-    case 'q': gp_quit(0); break;
-    case 'r':
-      s = get_sep(s);
-      if (!ismain) { read0(s); break; }
-      switchin(s);
-      if (file_is_binary(pari_infile))
-      {
-        int vector;
-        GEN x = gpreadbin(s, &vector);
-        if (vector) /* many BIN_GEN */
-        {
-          long i, l = lg(x);
-          pari_warn(warner,"setting %ld history entries", l-1);
-          for (i=1; i<l; i++) pari_add_hist(gel(x,i), 0);
+        if (strcmp(t, "default") == 0) {
+          if (i == argc) usage(argv[0]);
+          record_default(&s_P, argv[i++]);
+          break;
         }
-      }
-      break;
-    case 's': dbg_pari_heap(); break;
-    case 't': gentypes(); break;
-    case 'u':
-      print_all_user_fun((*s == 'm')? 1: 0);
-      break;
-    case 'v': print_version(); break;
-    case 'y':
-      s = get_sep(s);
-      if (!*s) s = (GP_DATA->simplify)? "0": "1";
-      (void)sd_simplify(s,d_ACKNOWLEDGE); break;
-    default: pari_err(e_SYNTAX,"unexpected character", tch,tch-1);
-  }
-}
-
-static void
-convert_time(char *s, long delay)
-{
-  if (delay >= 3600000)
-  {
-    sprintf(s, "%ldh, ", delay / 3600000); s+=strlen(s);
-    delay %= 3600000;
-  }
-  if (delay >= 60000)
-  {
-    sprintf(s, "%ldmin, ", delay / 60000); s+=strlen(s);
-    delay %= 60000;
-  }
-  if (delay >= 1000)
-  {
-    sprintf(s, "%ld,", delay / 1000); s+=strlen(s);
-    delay %= 1000;
-    if (delay < 100)
-    {
-      sprintf(s, "%s", (delay<10)? "00": "0");
-      s+=strlen(s);
-    }
-  }
-  sprintf(s, "%ld ms", delay); s+=strlen(s);
-}
-
-/* Format a time of 'delay' ms */
-static char *
-gp_format_time(long delay)
-{
-  static char buf[64];
-  char *s = buf;
-
-  term_get_color(s, c_TIME);
-  convert_time(s + strlen(s), delay);
-  s+=strlen(s);
-  term_get_color(s, c_NONE);
-  s+=strlen(s);
-  s[0] = '.';
-  s[1] = '\n';
-  s[2] = 0; return buf;
-}
-
-static int
-chron(char *s)
-{
-  if (*s)
-  { /* if "#" or "##" timer metacommand. Otherwise let the parser get it */
-    char *t;
-    if (*s == '#') s++;
-    if (*s) return 0;
-    t = gp_format_time(pari_get_histtime(0));
-    pari_printf("  ***   last result computed in %s", t);
-  }
-  else { GP_DATA->chrono ^= 1; (void)sd_timer(NULL,d_ACKNOWLEDGE); }
-  return 1;
-}
-
-/* return 0: can't interpret *buf as a metacommand
- *        1: did interpret *buf as a metacommand or empty command */
-static int
-check_meta(char *buf, int ismain)
-{
-  switch(*buf++)
-  {
-    case '?': aide(buf, h_REGULAR); break;
-    case '#': return chron(buf);
-    case '\\': escape(buf, ismain); break;
-    case '\0': break;
-    default: return 0;
-  }
-  return 1;
-}
-
-/********************************************************************/
-/*                                                                  */
-/*                              GPRC                                */
-/*                                                                  */
-/********************************************************************/
-/* LOCATE GPRC */
-
-static int get_line_from_file(const char *prompt, filtre_t *F, FILE *file);
-static void
-err_gprc(const char *s, char *t, char *u)
-{
-  err_printf("\n");
-  pari_err(e_SYNTAX,s,t,u);
-}
-
-/* return $HOME or the closest we can find */
-static const char *
-get_home(int *free_it)
-{
-  char *drv, *pth = os_getenv("HOME");
-  if (pth) return pth;
-  if ((drv = os_getenv("HOMEDRIVE"))
-   && (pth = os_getenv("HOMEPATH")))
-  { /* looks like WinNT */
-    char *buf = (char*)pari_malloc(strlen(pth) + strlen(drv) + 1);
-    sprintf(buf, "%s%s",drv,pth);
-    *free_it = 1; return buf;
-  }
-  pth = pari_get_homedir("");
-  return pth? pth: ".";
-}
-
-static FILE *
-gprc_chk(const char *s)
-{
-  FILE *f = fopen(s, "r");
-  if (f && !(GP_DATA->flags & gpd_QUIET)) err_printf("Reading GPRC: %s ...", s);
-  return f;
-}
-
-/* Look for [._]gprc: $GPRC, then in $HOME, ., /etc, pari_datadir */
-static FILE *
-gprc_get(void)
-{
-  FILE *f = NULL;
-  const char *gprc = os_getenv("GPRC");
-  if (gprc) f = gprc_chk(gprc);
-  if (!f)
-  {
-    int free_it = 0;
-    const char *home = get_home(&free_it);
-    char *str, *s, c;
-    long l;
-    l = strlen(home); c = home[l-1];
-    /* + "/gprc.txt" + \0*/
-    str = strcpy((char*)pari_malloc(l+10), home);
-    if (free_it) pari_free((void*)home);
-    s = str + l;
-    if (c != '/' && c != '\\') *s++ = '/';
-#ifndef _WIN32
-    strcpy(s, ".gprc");
-#else
-    strcpy(s, "gprc.txt");
-#endif
-    f = gprc_chk(str); /* in $HOME */
-    if (!f) f = gprc_chk(s); /* in . */
-#ifndef _WIN32
-    if (!f) f = gprc_chk("/etc/gprc");
-#else
-    if (!f)  /* in basedir */
-    {
-      const char *basedir = win32_basedir();
-      char *t = (char *) pari_malloc(strlen(basedir)+strlen(s)+2);
-      sprintf(t, "%s/%s", basedir, s);
-      f = gprc_chk(t); free(t);
-    }
-#endif
-    pari_free(str);
-  }
-  return f;
-}
-
-/* PREPROCESSOR */
-
-static ulong
-read_uint(char **s)
-{
-  long v = atol(*s);
-  if (!isdigit((int)**s)) err_gprc("not an integer", *s, *s);
-  while (isdigit((int)**s)) (*s)++;
-  return v;
-}
-static ulong
-read_dot_uint(char **s)
-{
-  if (**s != '.') return 0;
-  (*s)++; return read_uint(s);
-}
-/* read a.b.c */
-static long
-read_version(char **s)
-{
-  long a, b, c;
-  a = read_uint(s);
-  b = read_dot_uint(s);
-  c = read_dot_uint(s);
-  return PARI_VERSION(a,b,c);
-}
-
-static int
-get_preproc_value(char **s)
-{
-  if (!strncmp(*s,"EMACS",5)) {
-    *s += 5;
-    return GP_DATA->flags & (gpd_EMACS|gpd_TEXMACS);
-  }
-  if (!strncmp(*s,"READL",5)) {
-    *s += 5;
-    return GP_DATA->use_readline;
-  }
-  if (!strncmp(*s,"VERSION",7)) {
-    int less = 0, orequal = 0;
-    long d;
-    *s += 7;
-    switch(**s)
-    {
-      case '<': (*s)++; less = 1; break;
-      case '>': (*s)++; less = 0; break;
-      default: return -1;
-    }
-    if (**s == '=') { (*s)++; orequal = 1; }
-    d = paricfg_version_code - read_version(s);
-    if (!d) return orequal;
-    return less? (d < 0): (d > 0);
-  }
-  return -1;
-}
-
-/* PARSE GPRC */
-
-/* 1) replace next separator by '\0' (t must be writable)
- * 2) return the next expression ("" if none)
- * see get_sep() */
-static char *
-next_expr(char *t)
-{
-  int outer = 1;
-  char *s = t;
-
-  for(;;)
-  {
-    char c;
-    switch ((c = *s++))
-    {
-      case '"':
-        if (outer || (s >= t+2 && s[-2] != '\\')) outer = !outer;
-        break;
-      case '\0':
-        return (char*)"";
+        if (strcmp(t, "texmacs") == 0) { f |= gpd_TEXMACS; break; }
+        if (strcmp(t, "emacs") == 0) { f |= gpd_EMACS; break; }
+        if (strcmp(t, "test") == 0) { f |= gpd_TEST; initrc = 0; break; }
+        if (strcmp(t, "quiet") == 0) { f |= gpd_QUIET; break; }
+        if (strcmp(t, "fast") == 0) { initrc = 0; break; }
+        if (strncmp(t, "primelimit",10) == 0) {p = read_arg_equal(&i,t+10,argc,argv); break; }
+        if (strncmp(t, "stacksize",9) == 0) {s = read_arg_equal(&i,t+9,argc,argv); break; }
+       /* fall through */
       default:
-        if (outer && c == ';') { s[-1] = 0; return s; }
-    }
-  }
-}
-
-static Buffer *
-filtered_buffer(filtre_t *F)
-{
-  Buffer *b = new_buffer();
-  init_filtre(F, b);
-  pari_stack_pushp(&s_bufstack, (void*)b);
-  return b;
-}
-
-static jmp_buf *env;
-static pari_stack s_env;
-/* parse src of the form s=t (or s="t"), set *ps to s, and *pt to t.
- * modifies src (replaces = by \0) */
-static void
-parse_key_val(char *src, char **ps, char **pt)
-{
-  char *s_end, *t;
-  t = src; while (*t && *t != '=') t++;
-  if (*t != '=') err_gprc("missing '='",t,src);
-  s_end = t;
-  t++;
-  if (*t == '"') (void)readstring(t, t, src);
-  *s_end = 0; *ps = src; *pt = t;
-}
-
-static void
-gp_initrc(pari_stack *p_A)
-{
-  FILE *file = gprc_get();
-  Buffer *b;
-  filtre_t F;
-  VOLATILE long c = 0;
-
-  if (!file) return;
-  b = filtered_buffer(&F);
-  (void)pari_stack_new(&s_env);
-  for(;;)
-  {
-    char *nexts, *s, *t;
-    if (setjmp(env[s_env.n-1])) err_printf("...skipping line %ld.\n", c);
-    c++;
-    if (!get_line_from_file(NULL,&F,file)) break;
-    s = b->buf;
-    if (*s == '#')
-    { /* preprocessor directive */
-      int z, NOT = 0;
-      s++;
-      if (strncmp(s,"if",2)) err_gprc("unknown directive",s,b->buf);
-      s += 2;
-      if (!strncmp(s,"not",3)) { NOT = !NOT; s += 3; }
-      if (*s == '!')           { NOT = !NOT; s++; }
-      t = s;
-      z = get_preproc_value(&s);
-      if (z < 0) err_gprc("unknown preprocessor variable",t,b->buf);
-      if (NOT) z = !z;
-      if (!*s)
-      { /* make sure at least an expr follows the directive */
-        if (!get_line_from_file(NULL,&F,file)) break;
-        s = b->buf;
-      }
-      if (!z) continue; /* dump current line */
-    }
-    /* parse line */
-    for ( ; *s; s = nexts)
-    {
-      nexts = next_expr(s);
-      if (!strncmp(s,"read",4) && (s[4] == ' ' || s[4] == '\t' || s[4] == '"'))
-      { /* read file */
-        s += 4;
-        t = (char*)pari_malloc(strlen(s) + 1);
-        if (*s == '"') (void)readstring(s, t, s-4); else strcpy(t,s);
-        pari_stack_pushp(p_A,t);
-      }
-      else
-      { /* set default */
-        parse_key_val(s, &s,&t);
-        (void)setdefault(s,t,d_INITRC);
-      }
+        usage(argv[0]);
     }
   }
-  s_env.n--;
-  pop_buffer();
-  if (!(GP_DATA->flags & gpd_QUIET)) err_printf("Done.\n\n");
-  fclose(file);
-}
-
-/********************************************************************/
-/*                                                                  */
-/*                             PROMPTS                              */
-/*                                                                  */
-/********************************************************************/
-static int gp_is_interactive = 0;
-static const char *DFT_PROMPT = "? ";
-static const char *CONTPROMPT = "";
-static const char *COMMENTPROMPT = "comment> ";
-static const char *DFT_INPROMPT = "";
-
-static char Prompt[MAX_PROMPT_LEN], Prompt_cont[MAX_PROMPT_LEN];
-
-#ifndef _WIN32
-/* if prompt is coloured, we must tell readline to ignore the
- * corresponding ANSI escape sequences */
-static void
-brace_color(char *s, int c, int force)
-{
-  if (disable_color || (gp_colors[c] == c_NONE && !force)) return;
+  GP_DATA->flags = f;
 #ifdef READLINE
-  if (GP_DATA->use_readline)
-    readline_prompt_color(s, c);
-  else
+  GP_DATA->use_readline = stdin_isatty;
 #endif
-    term_get_color(s, c);
-}
-
-static void
-color_prompt(char *buf, const char *prompt)
-{
-  char *s = buf;
-  *s = 0;
-  /* escape sequences bug readline, so use special bracing (if available) */
-  brace_color(s, c_PROMPT, 0);
-  s += strlen(s); strcpy(s, prompt);
-  s += strlen(s);
-  brace_color(s, c_INPUT, 1);
-}
-#else
-static void
-color_prompt(char *buf, const char *prompt) { strcpy(buf,prompt); }
-#endif
-
-static const char *
-expand_prompt(char *buf, const char *prompt, filtre_t *F)
-{
-  if (F && F->in_comment) return COMMENTPROMPT;
-  strftime_expand(prompt, buf, MAX_PROMPT_LEN-1);
-  return buf;
-}
+  if (!is_interactive()) GP_DATA->breakloop = 0;
+  if (initrc) gp_initrc(p_A);
+  for ( ; i < argc; i++) pari_stack_pushp(p_A, pari_strdup(argv[i]));
 
-const char *
-do_prompt(char *buf, const char *prompt, filtre_t *F)
-{
-  if (GP_DATA->flags & gpd_TEST)
-    strcpy(buf, prompt);
-  else
-  {
-    char b[MAX_PROMPT_LEN];
-    const char *s = expand_prompt(b, prompt, F);
-    color_prompt(buf, s);
+  /* override the values from gprc */
+  if (p) (void)sd_primelimit(p, d_INITRC);
+  if (s) (void)sd_parisize(s, d_INITRC);
+  for (i = 0; i < s_P.n; i++) {
+    setdefault(P[i].key, P[i].val, d_INITRC);
+    free((void*)P[i].key);
   }
-  return buf;
+  pari_stack_delete(&s_P);
+  pari_outfile = stdout;
 }
 
-/********************************************************************/
-/*                                                                  */
-/*                           GP MAIN LOOP                           */
-/*                                                                  */
-/********************************************************************/
+/*******************************************************************/
+/**                                                               **/
+/**                            TEST MODE                          **/
+/**                                                               **/
+/*******************************************************************/
 static int
-is_interactive(void)
-{
-  ulong f = GP_DATA->flags&(gpd_TEXMACS|gpd_TEST);
-  return pari_infile == stdin && !f && gp_is_interactive;
-}
+test_is_interactive(void) { return 0; }
 
-static const char esc = (0x1f & '['); /* C-[ = escape */
-static char *
-strip_prompt(const char *s)
-{
-  long l = strlen(s);
-  char *t, *t0 = stack_malloc(l+1);
-  t = t0;
-  for (; *s; s++)
-  {
-    /* RL_PROMPT_START_IGNORE / RL_PROMPT_END_IGNORE */
-    if (*s == 1 || *s == 2) continue;
-    if (*s == esc) /* skip ANSI color escape sequence */
-    {
-      while (*++s != 'm')
-        if (!*s) goto end;
-      continue;
-    }
-    *t = *s; t++;
-  }
-end:
-  *t = 0; return t0;
-}
 static void
-update_logfile(const char *prompt, const char *s)
+test_output(GEN z)
 {
-  pari_sp av;
-  const char *p;
-  if (!pari_logfile) return;
-  if (!is_interactive() && !GP_DATA->echo) return;
-  av = avma;
-  p = strip_prompt(prompt); /* raw prompt */
-
-  switch (logstyle) {
-    case logstyle_TeX:
-      fprintf(pari_logfile,
-              "\\PARIpromptSTART|%s\\PARIpromptEND|%s\\PARIinputEND|%%\n",
-              p, s);
-    break;
-    case logstyle_plain:
-      fprintf(pari_logfile,"%s%s\n",p, s);
-    break;
-    case logstyle_color:
-      fprintf(pari_logfile,"%s%s%s%s%s\n",term_get_color(NULL,c_PROMPT), p,
-                                          term_get_color(NULL,c_INPUT), s,
-                                          term_get_color(NULL,c_NONE));
-      break;
-  }
-  avma = av;
+  init_linewrap(76);
+  gen_output(z, GP_DATA->fmt);
+  pari_putc('\n');
+  pari_flush();
 }
-
 void
-echo_and_log(const char *prompt, const char *s)
+init_test(void)
 {
-  if (GP_DATA->echo && !is_interactive()) {
-    /* not pari_puts(): would duplicate in logfile */
-    fputs(prompt, pari_outfile);
-    fputs(s,      pari_outfile);
-    fputc('\n',   pari_outfile);
-    pari_set_last_newline(1);
-  }
-  update_logfile(prompt, s);
-  pari_flush();
+  disable_color = 1;
+  init_linewrap(76);
+  cb_gp_output = test_output;
+  cb_pari_is_interactive = test_is_interactive;
 }
 
-/* prompt = NULL --> from gprc. Return 1 if new input, and 0 if EOF */
-static int
-get_line_from_file(const char *prompt, filtre_t *F, FILE *file)
+/*******************************************************************/
+/**                                                               **/
+/**                   FORMAT GP OUTPUT                            **/
+/**                                                               **/
+/*******************************************************************/
+    /* REGULAR */
+static void
+normal_output(GEN z, long n)
 {
-  const int Texmacs_stdin = ((GP_DATA->flags & gpd_TEXMACS) && file == stdin);
+  long l = 0;
   char *s;
-  input_method IM;
-
-  IM.file = file;
-  IM.fgets= Texmacs_stdin? &fgets_texmacs: &fgets;
-  IM.getline = &file_input;
-  IM.free = 0;
-  if (! input_loop(F,&IM))
-  {
-    if (Texmacs_stdin) tm_start_output();
-    return 0;
-  }
-
-  s = ((Buffer*)F->buf)->buf;
-  /* don't log if from gprc or empty input */
-  if (*s && prompt) echo_and_log(prompt, s);
-  if (GP_DATA->flags & gpd_TEXMACS)
-  {
-    tm_did_complete = 0;
-    if (Texmacs_stdin && *s == DATA_BEGIN)
-    { handle_texmacs_command(s); *s = 0; }
-    else
-      tm_start_output();
-  }
-  return 1;
-}
-
-/* return 0 if no line could be read (EOF). If PROMPT = NULL, expand and
- * color default prompt; otherwise, use PROMPT as-is. */
-static int
-gp_read_line(filtre_t *F, const char *PROMPT)
-{
-  Buffer *b = (Buffer*)F->buf;
-  char buf[MAX_PROMPT_LEN + 24];
-  const char *p;
-  int res, interactive;
-  F->downcase = (compatible == OLDALL);
-  if (b->len > 100000) fix_buffer(b, 100000);
-  interactive = is_interactive();
-  if (interactive || pari_logfile || GP_DATA->echo)
-    p = PROMPT? PROMPT: do_prompt(buf, Prompt, F);
-  else
-    p = DFT_PROMPT;
-
-  if (interactive)
+  /* history number */
+  if (n)
   {
-    BLOCK_EH_START
-#ifdef READLINE
-    if (GP_DATA->use_readline)
-      res = get_line_from_readline(p, Prompt_cont, F);
-    else
-#endif
+    char buf[64];
+    if (!(GP_DATA->flags & gpd_QUIET))
     {
-      pari_puts(p); pari_flush();
-      res = get_line_from_file(p, F, pari_infile);
+      term_color(c_HIST);
+      sprintf(buf, "%%%ld = ", n);
+      pari_puts(buf);
+      l = strlen(buf);
     }
-    BLOCK_EH_END
   }
+  /* output */
+  term_color(c_OUTPUT);
+  s = GENtostr(z);
+  if (GP_DATA->lim_lines)
+    lim_lines_output(s, l, GP_DATA->lim_lines);
   else
-    res = get_line_from_file(p, F, pari_infile);
-
-  if (!disable_color && p != DFT_PROMPT &&
-      (gp_colors[c_PROMPT] != c_NONE || gp_colors[c_INPUT] != c_NONE))
-  {
-    term_color(c_NONE); pari_flush();
-  }
-  return res;
+    pari_puts(s);
+  pari_free(s);
+  term_color(c_NONE); pari_putc('\n');
 }
 
-static int
-is_silent(char *s) { return s[strlen(s) - 1] == ';'; }
-
 static void
-reset_ctrlc(void)
+gp_output(GEN z)
 {
-#if defined(_WIN32) || defined(__CYGWIN32__)
-  win32ctrlc = 0;
-#endif
+  if (cb_gp_output) { cb_gp_output(z); return; }
+  if (GP_DATA->fmt->prettyp == f_PRETTY)
+  { if (tex2mail_output(z, GP_DATA->hist->total)) return; }
+  normal_output(z, GP_DATA->hist->total);
+  pari_flush();
 }
 
-enum { gp_ISMAIN = 1, gp_RECOVER = 2 };
-
 static GEN
-gp_main_loop(long flag)
+gp_main_loop(long ismain)
 {
-  VOLATILE const long dorecover = flag & gp_RECOVER;
-  VOLATILE const long ismain    = flag & gp_ISMAIN;
   VOLATILE GEN z = gnil;
   VOLATILE long t = 0;
   VOLATILE pari_sp av = avma;
   filtre_t F;
   Buffer *b = filtered_buffer(&F);
   struct gp_context rec;
-
-  if (dorecover) /* set recovery point */
-  {
-    long er;
-    if ((er = setjmp(env[s_env.n-1])))
-    { /* recover: jump from error [ > 0 ] or allocatemem [ -1 ] */
-      if (er > 0) { /* true error */
-        if (!(GP_DATA->recover)) exit(1);
-        gp_context_restore(&rec);
-        /* true error not from main instance, let caller sort it out */
-        if (!ismain) { kill_buffers_upto_including(b); return NULL; }
-      } else { /* allocatemem */
-        filestate_restore(rec.file);
-        gp_context_save(&rec);
-      }
-      avma = av = top;
-      kill_buffers_upto(b);
-      alarm0(0);
+  long er;
+  if ((er = setjmp(env[s_env.n-1])))
+  { /* recover: jump from error [ > 0 ] or allocatemem [ -1 ] */
+    if (er > 0) { /* true error */
+      if (!(GP_DATA->recover)) exit(1);
+      gp_context_restore(&rec);
+      /* true error not from main instance, let caller sort it out */
+      if (!ismain) { kill_buffers_upto_including(b); return NULL; }
+    } else { /* allocatemem */
+      filestate_restore(rec.file);
+      gp_context_save(&rec);
     }
+    avma = av = pari_mainstack->top;
+    parivstack_reset();
+    kill_buffers_upto(b);
+    pari_alarm(0);
   }
   for(;;)
   {
-    if (dorecover) gp_context_save(&rec);
+    gp_context_save(&rec);
     if (! gp_read_line(&F, NULL))
     {
       if (popinfile()) gp_quit(0);
       if (ismain) continue;
       pop_buffer(); return z;
     }
-    if (check_meta(b->buf, ismain)) continue;
-
     avma = av;
     if (ismain)
     {
@@ -1634,9 +365,11 @@ gp_main_loop(long flag)
       timer_start(GP_DATA->T);
       pari_set_last_newline(1);
     }
-    z = closure_evalres(pari_compile_str(b->buf, GP_DATA->strictmatch));
-    if (! ismain) continue;
-    alarm0(0);
+    if (gp_meta(b->buf,ismain)) continue;
+    z = pari_compile_str(b->buf);
+    z = closure_evalres(z);
+    if (!ismain) continue;
+    pari_alarm(0);
 
     if (!pari_last_was_newline()) pari_putc('\n');
 
@@ -1648,45 +381,28 @@ gp_main_loop(long flag)
     }
     if (GP_DATA->simplify) z = simplify_shallow(z);
     pari_add_hist(z, t);
-    if (z != gnil && ! is_silent(b->buf) ) gp_output(z, GP_DATA);
+    if (z != gnil && ! is_silent(b->buf) ) gp_output(z);
+    parivstack_reset();
   }
 }
 
-/********************************************************************/
-/*                                                                  */
-/*                      EXCEPTION HANDLER                           */
-/*                                                                  */
-/********************************************************************/
+/* as gp_read_file, before running the main gp instance */
 static void
-gp_sigint_fun(void) {
-  char buf[64];
-  if (GP_DATA->flags & gpd_TEXMACS) tm_start_output();
-  convert_time(buf, timer_get(GP_DATA->T));
-  pari_sigint(buf);
-}
-
-#if defined(SIGALRM) || defined(HAS_ALARM)
-static THREAD pari_timer ti_alarm;
-#endif
-#ifdef SIGALRM
-static void
-gp_alarm_fun(void) {
-  char buf[64];
-  if (GP_DATA->flags & gpd_TEXMACS) tm_start_output();
-  convert_time(buf, timer_get(&ti_alarm));
-  pari_err(e_ALARM, buf);
-}
-#endif /* SIGALRM */
-
-static const char *
-break_loop_prompt(char *buf, long n)
+read_main(const char *s)
 {
-  char s[128];
-  if (n == 1)
-    strcpy(s, "break> ");
-  else
-    sprintf(s, "break[%ld]> ", n);
-  return do_prompt(buf, s, NULL);
+  GEN z;
+  if (setjmp(env[s_env.n-1]))
+    z = NULL;
+  else {
+    FILE *f = switchin(s);
+    if (file_is_binary(f)) {
+      z = readbin(s,f, NULL);
+      popinfile();
+    }
+    else z = gp_main_loop(0);
+  }
+  if (!z) err_printf("... skipping file '%s'\n", s);
+  avma = pari_mainstack->top;
 }
 
 static long frame_level=0, dbg_level = 0;
@@ -1699,15 +415,15 @@ break_loop(int numerr)
   int sigint = numerr<0, go_on = sigint;
   struct gp_context rec;
   const char *prompt, *msg;
-  char promptbuf[MAX_PROMPT_LEN + 24];
   long nenv, oldframe_level = frame_level;
   pari_sp av;
 
   if (numerr == e_SYNTAX) return 0;
-  if (numerr == e_STACK) { evalstate_clone(); avma = top; }
+  if (numerr == e_STACK) { evalstate_clone(); avma = pari_mainstack->top; }
 
   b = filtered_buffer(&F);
   nenv=pari_stack_new(&s_env);
+  prompt = break_loop_prompt(s_env.n-1);
   gp_context_save(&rec);
   iferr_env = NULL;
   dbg_level = 0;
@@ -1720,421 +436,60 @@ break_loop(int numerr)
     msg = "Break loop: type 'break' to go back to GP prompt";
   print_errcontext(pariOut, msg, NULL, NULL);
   term_color(c_NONE);
-  prompt = break_loop_prompt(promptbuf, s_env.n-1);
   av = avma;
   for(;;)
   {
     GEN x;
     long er, br_status;
-    avma = av;
-    if ((er=setjmp(env[nenv])))
-    {
-      if (er < 0)
-      {
-        s_env.n = 1;
-        frame_level = oldframe_level;
-        longjmp(env[s_env.n-1], er);
-      }
-      gp_context_restore(&rec);
-      iferr_env = NULL;
-      closure_err(dbg_level);
-      (void) closure_context(oldframe_level, dbg_level);
-      pari_infile = newfile(stdin, "stdin", mf_IN)->file;
-    }
-    term_color(c_NONE);
-    if (!gp_read_line(&F, prompt))
-      br_status = br_BREAK; /* EOF */
-    else
-    {
-      /* Empty input ? Continue if entry on sigint (exit debugger frame) */
-      if (! *(b->buf) && sigint) break;
-      reset_ctrlc();
-      if (check_meta(b->buf, 0)) continue;
-      x = closure_evalbrk(pari_compile_str(b->buf,0), &br_status);
-    }
-    switch (br_status)
-    {
-      case br_NEXT: case br_MULTINEXT:
-        popinfile(); /* exit frame. Don't exit debugger if s_env.n > 2 */
-        go_on = 0; goto BR_EXIT;
-      case br_BREAK: case br_RETURN:
-        killallfiles(); /* completely exit the debugger */
-        go_on = 0; goto BR_EXIT;
-    }
-
-    if (x != gnil && !is_silent(b->buf))
-    {
-      term_color(c_OUTPUT);
-      gen_output(x, GP_DATA->fmt);
-      pari_putc('\n');
-    }
-  }
-BR_EXIT:
-  s_env.n=nenv;
-  frame_level = oldframe_level;
-  gp_context_restore(&rec);
-  pop_buffer(); return go_on;
-}
-
-/* numerr < 0: from SIGINT */
-static void
-gp_pre_recover(long numerr)
-{
-  if (numerr>=0)
-  {
-    out_puts(pariErr, "\n"); pariErr->flush();
-  }
-  longjmp(env[s_env.n-1], numerr);
-}
-
-/* numerr < 0: from SIGINT */
-static void
-gp_err_recover(long numerr)
-{
-  longjmp(env[s_env.n-1], numerr);
-}
-
-void
-dbg_up(long k)
-{
-  if (k<0) k=0;
-  dbg_level += k;
-  if (dbg_level>frame_level) dbg_level=frame_level;
-  gp_err_recover(e_NONE);
-}
-
-void
-dbg_down(long k)
-{
-  if (k<0) k=0;
-  dbg_level -= k;
-  if (dbg_level<0) dbg_level=0;
-  gp_err_recover(e_NONE);
-}
-
-GEN
-dbg_err(void) { GEN E = pari_err_last(); return E? gcopy(E):gnil; }
-
-void
-pari_breakpoint(void)
-{
-  if (!pari_last_was_newline()) pari_putc('\n');
-  closure_err(0);
-  if (break_loop(-1)) return;
-  gp_err_recover(e_MISC);
-}
-
-/* numerr < 0: from SIGINT */
-static int
-gp_handle_exception(long numerr)
-{
-  if (disable_exception_handler) disable_exception_handler = 0;
-  else if ((GP_DATA->breakloop) && break_loop(numerr)) return 1;
-  return 0;
-}
-
-#ifdef SIGALRM
-static void
-gp_alarm_handler(int sig)
-{
-#ifndef HAS_SIGACTION
-  /*SYSV reset the signal handler in the handler*/
-  (void)os_signal(sig,gp_alarm_handler);
-#endif
-  if (PARI_SIGINT_block) PARI_SIGINT_pending=sig;
-  else gp_alarm_fun();
-  return;
-}
-#endif /* SIGALRM */
-
-/********************************************************************/
-/*                                                                  */
-/*                      GP-SPECIFIC ROUTINES                        */
-/*                                                                  */
-/********************************************************************/
-static void
-check_secure(const char *s)
-{
-  if (GP_DATA->secure)
-    pari_err(e_MISC, "[secure mode]: system commands not allowed\nTried to run '%s'",s);
-}
-
-GEN
-read0(const char *s)
-{
-  switchin(s);
-  if (file_is_binary(pari_infile)) return gpreadbin(s, NULL);
-  return gp_main_loop(0);
-}
-/* as read0 but without a main instance of gp running */
-static void
-read_main(const char *s)
-{
-  GEN z;
-  if (setjmp(env[s_env.n-1]))
-    z = NULL;
-  else {
-    switchin(s);
-    if (file_is_binary(pari_infile)) {
-      z = readbin(s,pari_infile, NULL);
-      popinfile();
-    }
-    else z = gp_main_loop(gp_RECOVER);
-  }
-  if (!z) err_printf("... skipping file '%s'\n", s);
-  avma = top;
-}
-
-static GEN
-get_lines(FILE *F)
-{
-  pari_sp av = avma;
-  long i, nz = 16;
-  GEN z = cgetg(nz + 1, t_VEC);
-  Buffer *b = new_buffer();
-  input_method IM;
-  IM.fgets = &fgets;
-  IM.file = F;
-  for(i = 1;;)
-  {
-    char *s = b->buf, *e;
-    if (!file_getline(b, &s, &IM)) break;
-    if (i > nz) { nz <<= 1; z = vec_lengthen(z, nz); }
-    e = s + strlen(s)-1;
-    if (*e == '\n') *e = 0;
-    gel(z,i++) = strtoGENstr(s);
-  }
-  delete_buffer(b); setlg(z, i);
-  return gerepilecopy(av, z);
-}
-
-GEN
-externstr(const char *s)
-{
-  pariFILE *F;
-  GEN z;
-  check_secure(s);
-  F = try_pipe(s, mf_IN);
-  z = get_lines(F->file);
-  pari_fclose(F); return z;
-}
-GEN
-readstr(const char *s)
-{
-  GEN z = get_lines(switchin(s));
-  popinfile(); return z;
-}
-
-GEN
-extern0(const char *s)
-{
-  check_secure(s);
-  pari_infile = try_pipe(s, mf_IN)->file;
-  return gp_main_loop(0);
-}
-
-GEN
-input0(void)
-{
-  filtre_t F;
-  Buffer *b = filtered_buffer(&F);
-  GEN x;
-
-  while (! get_line_from_file(DFT_INPROMPT,&F,pari_infile))
-    if (popinfile()) { err_printf("no input ???"); gp_quit(1); }
-  x = readseq(b->buf);
-  pop_buffer(); return x;
-}
-
-void
-system0(const char *s)
-{
-/*FIXME: HAS_SYSTEM */
-#if defined(UNIX) || defined(__EMX__) || defined(_WIN32)
-  check_secure(s);
-  if (system(s) < 0)
-    pari_err(e_MISC, "system(\"%s\") failed", s);
-#else
-  pari_err(e_ARCH,"system");
-#endif
-}
-
-static GEN
-closure_alarmer(GEN C, long s)
-{
-  struct pari_evalstate state;
-  VOLATILE GEN x;
-  if (!s) { alarm0(0); return closure_evalgen(C); }
-  evalstate_save(&state);
-#ifndef HAS_ALARM
-  pari_err(e_ARCH,"alarm");
-#endif
-  pari_CATCH(CATCH_ALL) /* We need to stop the timer after any error */
-  {
-    GEN E = pari_err_last();
-    if (err_get_num(E) != e_ALARM) { alarm0(0); pari_err(0, E); }
-    x = evalstate_restore_err(&state);
-  }
-  pari_TRY { alarm0(s); x = closure_evalgen(C); alarm0(0); } pari_ENDCATCH;
-  return x;
-}
-
-void
-alarm0(long s)
-{
-  if (s < 0) pari_err_DOMAIN("alarm","delay","<",gen_0,stoi(s));
-#ifdef HAS_ALARM
-  if (s) timer_start(&ti_alarm);
-  alarm(s);
-#else
-  if (s) pari_err(e_ARCH,"alarm");
-#endif
-}
-
-GEN
-gp_alarm(long s, GEN code)
-{
-  if (!code) { alarm0(s); return gnil; }
-  return closure_alarmer(code,s);
-}
-
-/*******************************************************************/
-/**                                                               **/
-/**                        INITIALIZATION                         **/
-/**                                                               **/
-/*******************************************************************/
-static char *
-read_arg(long *nread, char *t, long argc, char **argv)
-{
-  long i = *nread;
-  if (isdigit((int)*t)) return t;
-  if (*t || i==argc) usage(argv[0]);
-  *nread = i+1; return argv[i];
-}
-
-static char *
-read_arg_equal(long *nread, char *t, long argc, char **argv)
-{
-  long i = *nread;
-  if (*t=='=' && isdigit((int)t[1])) return t+1;
-  if (*t || i==argc) usage(argv[0]);
-  *nread = i+1; return argv[i];
-}
-
-static void
-init_trivial_stack(void)
-{
-  const size_t s = 2048;
-  bot = (pari_sp)pari_malloc(s);
-  avma = top = bot + s;
-}
-
-typedef struct { char *key, *val; } pair_t;
-/* If ab of the form key=val, record pair in new stack entry
- * P[n].key must be freed by caller to avoid memory leak */
-static void
-record_default(pari_stack *s_P, char *ab)
-{
-  pair_t *P = (pair_t*)*pari_stack_base(s_P);
-  char *k, *v;
-  long n;
-  ab = pari_strdup(ab);
-  parse_key_val(ab, &k, &v);
-  n = pari_stack_new(s_P);
-  P[n].key = k;
-  P[n].val = v;
-}
-static void
-read_opt(pari_stack *p_A, long argc, char **argv)
-{
-  pair_t *P;
-  pari_stack s_P; /* key / value to record default() settings */
-  char *b = NULL, *p = NULL, *s = NULL;
-  ulong f = GP_DATA->flags;
-  long i = 1, initrc = 1;
-
-  (void)&p; (void)&b; (void)&s; /* -Wall gcc-2.95 */
-
-  pari_stack_init(&s_P,sizeof(*P),(void**)&P);
-  pari_stack_alloc(&s_P, 64);
-  pari_outfile = stderr;
-  while (i < argc)
-  {
-    char *t = argv[i];
-
-    if (*t++ != '-') break;
-    i++;
-START:
-    switch(*t++)
+    avma = av;
+    if ((er=setjmp(env[nenv])))
     {
-      case 'p': p = read_arg(&i,t,argc,argv); break;
-      case 's': s = read_arg(&i,t,argc,argv); break;
-      case 'e':
-        f |= gpd_EMACS; if (*t) goto START;
-        break;
-      case 'q':
-        f |= gpd_QUIET; if (*t) goto START;
-        break;
-      case 't':
-        f |= gpd_TEST; if (*t) goto START;
-        break;
-      case 'f':
-        initrc = 0; if (*t) goto START;
-        break;
-      case 'D':
-        if (*t || i == argc) usage(argv[0]);
-        record_default(&s_P, argv[i++]);
-        break;
-      case '-':
-        if (strcmp(t, "version-short") == 0) { print_shortversion(); exit(0); }
-        if (strcmp(t, "version") == 0) {
-          init_trivial_stack(); print_version();
-          pari_free((void*)bot); exit(0);
-        }
-        if (strcmp(t, "default") == 0) {
-          if (i == argc) usage(argv[0]);
-          record_default(&s_P, argv[i++]);
-          break;
-        }
-        if (strcmp(t, "texmacs") == 0) { f |= gpd_TEXMACS; break; }
-        if (strcmp(t, "emacs") == 0) { f |= gpd_EMACS; break; }
-        if (strcmp(t, "test") == 0) { f |= gpd_TEST; break; }
-        if (strcmp(t, "quiet") == 0) { f |= gpd_QUIET; break; }
-        if (strcmp(t, "fast") == 0) { initrc = 0; break; }
-        if (strncmp(t, "primelimit",10) == 0) {p = read_arg_equal(&i,t+10,argc,argv); break; }
-        if (strncmp(t, "stacksize",9) == 0) {s = read_arg_equal(&i,t+9,argc,argv); break; }
-       /* fall through */
-      default:
-        usage(argv[0]);
+      if (er < 0)
+      {
+        s_env.n = 1;
+        frame_level = oldframe_level;
+        longjmp(env[s_env.n-1], er);
+      }
+      gp_context_restore(&rec);
+      iferr_env = NULL;
+      closure_err(dbg_level);
+      (void) closure_context(oldframe_level, dbg_level);
+      pari_infile = newfile(stdin, "stdin", mf_IN)->file;
+    }
+    term_color(c_NONE);
+    if (!gp_read_line(&F, prompt))
+      br_status = br_BREAK; /* EOF */
+    else
+    {
+      /* Empty input ? Continue if entry on sigint (exit debugger frame) */
+      if (! *(b->buf) && sigint) break;
+      reset_ctrlc();
+      if (gp_meta(b->buf,0)) continue;
+      x = pari_compile_str(b->buf);
+      x = closure_evalbrk(x, &br_status);
+    }
+    switch (br_status)
+    {
+      case br_NEXT: case br_MULTINEXT:
+        popinfile(); /* exit frame. Don't exit debugger if s_env.n > 2 */
+        go_on = 0; goto BR_EXIT;
+      case br_BREAK: case br_RETURN:
+        killallfiles(); /* completely exit the debugger */
+        go_on = 0; goto BR_EXIT;
     }
-  }
-#ifdef READLINE
-  GP_DATA->use_readline = gp_is_interactive;
-#else
-  GP_DATA->use_readline = 0;
-#endif
-  if (!gp_is_interactive && !(GP_DATA->flags & gpd_EMACS))
-    GP_DATA->breakloop = 0;
-  if (f & gpd_TEXMACS) tm_start_output();
-  GP_DATA->flags = f;
-  if (f & gpd_TEST) {
-    GP_DATA->breakloop = 0;
-    init_linewrap(76);
-  } else if (initrc)
-    gp_initrc(p_A);
-  for ( ; i < argc; i++) pari_stack_pushp(p_A, pari_strdup(argv[i]));
 
-  /* override the values from gprc */
-  if (p) (void)sd_primelimit(p, d_INITRC);
-  if (s) (void)sd_parisize(s, d_INITRC);
-  for (i = 0; i < s_P.n; i++) {
-    setdefault(P[i].key, P[i].val, d_INITRC);
-    free((void*)P[i].key);
+    if (x != gnil && !is_silent(b->buf))
+    {
+      term_color(c_OUTPUT);
+      gen_output(x, GP_DATA->fmt);
+      pari_putc('\n');
+    }
   }
-  pari_stack_delete(&s_P);
-
-  if (GP_DATA->flags & (gpd_EMACS|gpd_TEXMACS|gpd_TEST)) disable_color = 1;
-  pari_outfile = stdout;
+BR_EXIT:
+  s_env.n=nenv;
+  frame_level = oldframe_level;
+  gp_context_restore(&rec);
+  pop_buffer(); return go_on;
 }
 
 #ifdef __CYGWIN32__
@@ -2186,7 +541,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
   char **argv = NULL;
   int argc = 1;
 #endif
-  void **A;
+  char **A;
   pari_stack s_A;
 
   GP_DATA = default_gp_data();
@@ -2201,20 +556,15 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 #ifdef __CYGWIN32__
   cyg_environment(argc, argv);
 #endif
-  gp_is_interactive = pari_stdin_isatty();
+  stdin_isatty = pari_stdin_isatty();
   pari_init_defaults();
   pari_library_path = DL_DFLT_NAME;
   pari_stack_init(&s_A,sizeof(*A),(void**)&A);
-  pari_stack_init(&s_bufstack, sizeof(Buffer*), (void**)&bufstack);
+  pari_init_opts(1000000 * sizeof(long), 0, INIT_SIGm | INIT_noPRIMEm | INIT_noIMTm);
   cb_pari_err_recover = gp_err_recover;
-  pari_init_opts(1000000 * sizeof(long), 0, INIT_SIGm | INIT_noPRIMEm);
   cb_pari_pre_recover = gp_pre_recover;
-  pari_add_defaults_module(functions_gp_default);
-  (void)sd_graphcolormap("[\"white\",\"black\",\"blue\",\"violetred\",\"red\",\"green\",\"grey\",\"gainsboro\"]", d_SILENT);
-  (void)sd_graphcolors("[4, 5]", d_SILENT);
-  strcpy(Prompt,      DFT_PROMPT);
-  strcpy(Prompt_cont, CONTPROMPT);
-  Help = init_help();
+  cb_pari_break_loop = break_loop;
+  cb_pari_is_interactive = is_interactive;
 
   read_opt(&s_A, argc,argv);
   initprimetable(GP_DATA->primelimit);
@@ -2223,405 +573,84 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 #endif
   pari_add_module(functions_gp);
   pari_add_module(functions_highlevel);
-  pari_add_oldmodule(functions_oldgp);
 
   init_graph();
-#ifdef READLINE
-  init_readline();
-#endif
+  cb_pari_quit = gp_quit;
   cb_pari_whatnow = whatnow;
   cb_pari_sigint = gp_sigint_fun;
   cb_pari_handle_exception = gp_handle_exception;
   cb_pari_ask_confirm = gp_ask_confirm;
   gp_expand_path(GP_DATA->path);
+  pari_mt_init(); /* MPI: will not return on slaves (pari_MPI_rank = 0) */
+
+#ifdef READLINE
+  init_readline();
+#endif
+  if (GP_DATA->flags & gpd_EMACS) init_emacs();
+  if (GP_DATA->flags & gpd_TEXMACS) init_texmacs();
 
   timer_start(GP_DATA->T);
   if (!(GP_DATA->flags & gpd_QUIET)) gp_head();
+  if (GP_DATA->flags & gpd_TEST) init_test();
   if (s_A.n)
   {
     FILE *l = pari_logfile;
     long i;
     pari_logfile = NULL;
-    for (i = 0; i < s_A.n; pari_free(A[i]),i++) read_main((char*)A[i]);
+    for (i = 0; i < s_A.n; pari_free(A[i]),i++) read_main(A[i]);
     /* Reading one of the input files above can set pari_logfile.
      * Don't restore in that case. */
     if (!pari_logfile) pari_logfile = l;
   }
   pari_stack_delete(&s_A);
-  (void)gp_main_loop(gp_RECOVER|gp_ISMAIN);
+  (void)gp_main_loop(1);
   gp_quit(0); return 0; /* not reached */
 }
 
-/*******************************************************************/
-/**                                                               **/
-/**                          GP OUTPUT                            **/
-/**                                                               **/
-/*******************************************************************/
-    /* EXTERNAL PRETTYPRINTER */
-/* Wait for prettinprinter to finish, to prevent new prompt from overwriting
- * the output.  Fill the output buffer, wait until it is read.
- * Better than sleep(2): give possibility to print */
-static void
-prettyp_wait(FILE *out)
-{
-  const char *s = "                                                     \n";
-  long i = 2000;
-
-  fputs("\n\n", out); fflush(out); /* start translation */
-  while (--i) fputs(s, out);
-  fputs("\n", out); fflush(out);
-}
-
-/* initialise external prettyprinter (tex2mail) */
-static int
-prettyp_init(void)
-{
-  gp_pp *pp = GP_DATA->pp;
-  if (!pp->cmd) return 0;
-  if (pp->file || (pp->file = try_pipe(pp->cmd, mf_OUT))) return 1;
-
-  pari_warn(warner,"broken prettyprinter: '%s'",pp->cmd);
-  pari_free(pp->cmd); pp->cmd = NULL;
-  sd_output("1", d_SILENT);
-  return 0;
-}
-
-/* n = history number. if n = 0 no history */
-static int
-tex2mail_output(GEN z, long n)
-{
-  pariout_t T = *(GP_DATA->fmt); /* copy */
-  FILE *log = pari_logfile, *out;
-
-  if (!prettyp_init()) return 0;
-  out = GP_DATA->pp->file->file;
-  /* Emit first: there may be lines before the prompt */
-  if (n) term_color(c_OUTPUT);
-  pari_flush();
-  T.prettyp = f_TEX;
-  /* history number */
-  if (n)
-  {
-    pari_sp av = avma;
-    const char *c_hist = term_get_color(NULL, c_HIST);
-    const char *c_out = term_get_color(NULL, c_OUTPUT);
-    if (!(GP_DATA->flags & gpd_QUIET))
-    {
-      if (*c_hist || *c_out)
-        fprintf(out, "\\LITERALnoLENGTH{%s}\\%%%ld =\\LITERALnoLENGTH{%s} ",
-                     c_hist, n, c_out);
-      else
-        fprintf(out, "\\%%%ld = ", n);
-    }
-    if (log) {
-      switch (logstyle) {
-      case logstyle_plain:
-        fprintf(log, "%%%ld = ", n);
-        break;
-      case logstyle_color:
-        fprintf(log, "%s%%%ld = %s", c_hist, n, c_out);
-        break;
-      case logstyle_TeX:
-        fprintf(log, "\\PARIout{%ld}", n);
-        break;
-      }
-    }
-    avma = av;
-  }
-  /* output */
-  fputGEN_pariout(z, &T, out);
-  /* flush and restore, output to logfile */
-  prettyp_wait(out);
-  if (log) {
-    if (logstyle == logstyle_TeX) {
-      T.TeXstyle |= TEXSTYLE_BREAK;
-      fputGEN_pariout(z, &T, log);
-      fputc('%', log);
-    } else {
-      T.prettyp = f_RAW;
-      fputGEN_pariout(z, &T, log);
-    }
-    fputc('\n', log); fflush(log);
-  }
-  if (n) term_color(c_NONE);
-  return 1;
-}
-
-    /* TEXMACS */
-static void
-texmacs_output(GEN z, long n)
-{
-  char *sz = GENtoTeXstr(z);
-  printf("%clatex:", DATA_BEGIN);
-  if (n) printf("\\magenta\\%%%ld = ", n);
-  printf("$\\blue %s$%c", sz,DATA_END);
-  pari_free(sz); fflush(stdout);
-}
-
-    /* REGULAR */
-static void
-normal_output(GEN z, long n)
-{
-  long l = 0;
-  char *s;
-  /* history number */
-  if (n)
-  {
-    char buf[64];
-    if (!(GP_DATA->flags & gpd_QUIET))
-    {
-      term_color(c_HIST);
-      sprintf(buf, "%%%ld = ", n);
-      pari_puts(buf);
-      l = strlen(buf);
-    }
-  }
-  /* output */
-  term_color(c_OUTPUT);
-  s = GENtostr(z);
-  if (GP_DATA->lim_lines)
-    lim_lines_output(s, l, GP_DATA->lim_lines);
-  else
-    pari_puts(s);
-  pari_free(s);
-  term_color(c_NONE); pari_putc('\n');
-}
-
 void
-gp_output(GEN z, gp_data *G)
-{
-  if (G->flags & gpd_TEST) {
-    init_linewrap(76);
-    gen_output(z, G->fmt); pari_putc('\n');
-  }
-  else if (G->flags & gpd_TEXMACS)
-    texmacs_output(z, G->hist->total);
-  else if (G->fmt->prettyp != f_PRETTY || !tex2mail_output(z, G->hist->total))
-    normal_output(z, G->hist->total);
-  pari_flush();
-}
-
-/*******************************************************************/
-/**                                                               **/
-/**                     GP-SPECIFIC DEFAULTS                      **/
-/**                                                               **/
-/*******************************************************************/
-
-static long
-atocolor(const char *s)
+pari_breakpoint(void)
 {
-  long l = atol(s);
-  if (l <   0) l =   0;
-  if (l > 255) l = 255;
-  return l;
+  if (!pari_last_was_newline()) pari_putc('\n');
+  closure_err(0);
+  if (cb_pari_break_loop && cb_pari_break_loop(-1)) return;
+  cb_pari_err_recover(e_MISC);
 }
 
-GEN
-sd_graphcolormap(const char *v, long flag)
+void
+dbg_down(long k)
 {
-  char *p, *q;
-  long i, j, l, a, s, *lp;
-
-  if (v)
-  {
-    char *t = filtre(v, 0);
-    if (*t != '[' || t[strlen(t)-1] != ']')
-      pari_err(e_SYNTAX, "incorrect value for graphcolormap", t, t);
-    for (s = 0, p = t+1, l = 2, a=0; *p; p++)
-      if (*p == '[')
-      {
-        a++;
-        while (*++p != ']')
-          if (!*p || *p == '[')
-            pari_err(e_SYNTAX, "incorrect value for graphcolormap", p, t);
-      }
-      else if (*p == '"')
-      {
-        s += sizeof(long)+1;
-        while (*p && *++p != '"') s++;
-        if (!*p) pari_err(e_SYNTAX, "incorrect value for graphcolormap", p, t);
-        s = (s+sizeof(long)-1) & ~(sizeof(long)-1);
-      }
-      else if (*p == ',')
-        l++;
-    if (l < 4)
-      pari_err(e_MISC, "too few colors (< 4) in graphcolormap");
-    if (pari_colormap) pari_free(pari_colormap);
-    pari_colormap = (GEN)pari_malloc((l+4*a)*sizeof(long) + s);
-    pari_colormap[0] = evaltyp(t_VEC)|evallg(l);
-    for (p = t+1, i = 1, lp = pari_colormap+l; i < l; p++)
-      switch(*p)
-      {
-      case '"':
-        gel(pari_colormap, i) = lp;
-        q = ++p; while (*q != '"') q++;
-        *q = 0;
-        j = 1 + nchar2nlong(q-p+1);
-        lp[0] = evaltyp(t_STR)|evallg(j);
-        strncpy(GSTR(lp), p, q-p+1);
-        lp += j; p = q;
-        break;
-      case '[': {
-        const char *ap[3];
-        gel(pari_colormap, i) = lp;
-        lp[0] = evaltyp(t_VECSMALL)|_evallg(4);
-        for (ap[0] = ++p, j=0; *p && *p != ']'; p++)
-          if (*p == ',' && j<2) { *p++ = 0; ap[++j] = p; }
-        while (j<2) ap[++j] = "0";
-        if (j>2 || *p != ']')
-        {
-          char buf[100];
-          sprintf(buf, "incorrect value for graphcolormap[%ld]: ", i);
-          pari_err(e_SYNTAX, buf, p, t);
-        }
-        *p = '\0';
-        lp[1] = atocolor(ap[0]);
-        lp[2] = atocolor(ap[1]);
-        lp[3] = atocolor(ap[2]);
-        lp += 4;
-        break;
-      }
-      case ',':
-      case ']':
-        i++;
-        break;
-      default:
-        pari_err(e_SYNTAX, "incorrect value for graphcolormap", p, t);
-      }
-    pari_free(t);
-  }
-  if (flag == d_RETURN || flag == d_ACKNOWLEDGE)
-  {
-    GEN cols = cgetg(lg(pari_colormap), t_VEC);
-    long i;
-
-    for (i = 1; i < lg(cols); i++)
-    {
-      GEN c = gel(pari_colormap, i);
-      if (typ(c) == t_STR)
-        gel(cols, i) = gcopy(c);
-      else
-        gel(cols, i) = vecsmall_to_vec(c);
-    }
-    if (flag == d_RETURN) return cols;
-    pari_printf("   graphcolormap = %Ps\n", cols);
-  }
-  return gnil;
+  if (k<0) k=0;
+  dbg_level -= k;
+  if (dbg_level<0) dbg_level=0;
+  gp_err_recover(e_NONE);
 }
 
 GEN
-sd_graphcolors(const char *v, long flag)
-{
-  long i, l;
-  char *p;
-
-  if (v) {
-    char *t = filtre(v, 0);
-    for (p = t+1, l=2; *p != ']'; p++)
-      if (*p == ',') l++;
-      else if (*p < '0' || *p > '9')
-        pari_err(e_SYNTAX, "incorrect value for graphcolors", p, t);
-    if (*++p) pari_err(e_SYNTAX, "incorrect value for graphcolors", p, t);
-    if (pari_graphcolors) pari_free(pari_graphcolors);
-    pari_graphcolors = cgetalloc(t_VECSMALL, l);
-    for (p = t+1, i=0; *p; p++)
-    {
-      long n = 0;
-      while (*p >= '0' && *p <= '9')
-      {
-        n *= 10;
-        n += *p-'0';
-        p++;
-      }
-      pari_graphcolors[++i] = n;
-    }
-    pari_free(t);
-  }
-  switch(flag)
-  {
-  case d_RETURN:
-    return vecsmall_to_vec(pari_graphcolors);
-  case d_ACKNOWLEDGE:
-    pari_printf("   graphcolors = %Ps\n", vecsmall_to_vec(pari_graphcolors));
-  }
-  return gnil;
-}
+dbg_err(void) { GEN E = pari_err_last(); return E? gcopy(E):gnil; }
 
-GEN
-sd_help(const char *v, long flag)
+void
+dbg_up(long k)
 {
-  const char *str;
-  if (v)
-  {
-    if (GP_DATA->secure)
-      pari_err(e_MISC,"[secure mode]: can't modify 'help' default (to %s)",v);
-    if (Help) pari_free((void*)Help);
-#ifndef _WIN32
-    Help = path_expand(v);
-#else
-    Help = strdup(v);
-#endif
-  }
-  str = Help? Help: "none";
-  if (flag == d_RETURN) return strtoGENstr(str);
-  if (flag == d_ACKNOWLEDGE)
-    pari_printf("   help = \"%s\"\n", str);
-  return gnil;
+  if (k<0) k=0;
+  dbg_level += k;
+  if (dbg_level>frame_level) dbg_level=frame_level;
+  gp_err_recover(e_NONE);
 }
 
-static GEN
-sd_prompt_set(const char *v, long flag, const char *how, char *p)
+void
+gp_quit(long code)
 {
-  if (v) strncpy(p,v,MAX_PROMPT_LEN);
-  if (flag == d_RETURN) return strtoGENstr(p);
-  if (flag == d_ACKNOWLEDGE)
-    pari_printf("   prompt%s = \"%s\"\n", how, p);
-  return gnil;
+  free_graph();
+  pari_close();
+  kill_buffers_upto(NULL);
+  if (!(GP_DATA->flags & gpd_QUIET)) pari_puts("Goodbye!\n");
+  if (cb_pari_end_output) cb_pari_end_output();
+  exit(code);
 }
-GEN
-sd_prompt(const char *v, long flag)
-{ return sd_prompt_set(v, flag, "", Prompt); }
-GEN
-sd_prompt_cont(const char *v, long flag)
-{ return sd_prompt_set(v, flag, "_cont", Prompt_cont); }
 
-GEN
-sd_breakloop(const char *v, long flag)
-{ return sd_toggle(v,flag,"breakloop", &(GP_DATA->breakloop)); }
-GEN
-sd_echo(const char *v, long flag)
-{ return sd_toggle(v,flag,"echo", &(GP_DATA->echo)); }
-GEN
-sd_timer(const char *v, long flag)
-{ return sd_toggle(v,flag,"timer", &(GP_DATA->chrono)); }
-GEN
-sd_recover(const char *v, long flag)
-{ return sd_toggle(v,flag,"recover", &(GP_DATA->recover)); }
-
-#ifndef READLINE /* default not implemented */
-GEN
-sd_readline(const char *v, long flag)
-{ (void)v; (void)flag; return gnil; }
-GEN
-sd_histfile(const char *v, long flag)
-{ (void)v; (void)flag; return gnil; }
-#endif
-
-GEN
-sd_psfile(const char *v, long flag)
-{ return sd_string(v, flag, "psfile", &current_psfile); }
+void
+whatnow0(char *s) { whatnow(pariOut, s,0); }
 
-GEN
-sd_lines(const char *v, long flag)
-{ return sd_ulong(v,flag,"lines",&(GP_DATA->lim_lines), 0,LONG_MAX,NULL); }
-GEN
-sd_linewrap(const char *v, long flag)
-{
-  ulong old = GP_DATA->linewrap, n = GP_DATA->linewrap;
-  GEN z = sd_ulong(v,flag,"linewrap",&n, 0,LONG_MAX,NULL);
-  if (old)
-  { if (!n) resetout(1); }
-  else
-  { if (n) init_linewrap(n); }
-  GP_DATA->linewrap = n; return z;
-}
+#include "gp_init.h"
+#include "../graph/rect.h"
+#include "highlvl.h"
diff --git a/src/gp/gp.h b/src/gp/gp.h
index 4de1327..ea4cee5 100644
--- a/src/gp/gp.h
+++ b/src/gp/gp.h
@@ -17,68 +17,23 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 /*                                                                       */
 /*************************************************************************/
 BEGINEXTERN
-
-void aide(const char *s, long flag);
-void echo_and_log(const char *prompt, const char *s);
-int  get_line_from_readline(const char *prompt, const char *prompt_cont, filtre_t *F);
-void readline_prompt_color(char *s, int c);
-void gp_output(GEN z, gp_data *G);
+void init_emacs(void);
 void init_readline(void);
-void texmacs_completion(const char *s, long pos);
-void print_fun_list(char **list, long nbli);
-
-/* aide() */
-#define h_REGULAR 0
-#define h_LONG    1
-#define h_APROPOS 2
-#define h_RL      4
+void init_texmacs(void);
 
 /* readline completions */
 extern const char *keyword_list[];
 
-/* TeXmacs */
-#define DATA_BEGIN  ((char) 2)
-#define DATA_END    ((char) 5)
-#define DATA_ESCAPE ((char) 27)
-
 /* gp specific routines */
-void alarm0(long s);
 void dbg_down(long k);
-GEN  dbg_err(void);
 void dbg_up(long k);
-GEN  extern0(const char *cmd);
-GEN  externstr(const char *cmd);
-GEN  gp_alarm(long s, GEN code);
+GEN dbg_err(void);
 void gp_quit(long exitcode);
-GEN  input0(void);
 void pari_breakpoint(void);
-GEN  read0(const char *s);
-GEN  readstr(const char *s);
-void system0(const char *cmd);
 int  whatnow(PariOUT *out, const char *s, int silent);
-GEN sd_breakloop(const char *v, long flag);
-GEN sd_echo(const char *v, long flag);
-GEN sd_graphcolormap(const char *v, long flag);
-GEN sd_graphcolors(const char *v, long flag);
-GEN sd_help(const char *v, long flag);
-GEN sd_histfile(const char *v, long flag);
-GEN sd_lines(const char *v, long flag);
-GEN sd_linewrap(const char *v, long flag);
-GEN sd_prompt(const char *v, long flag);
-GEN sd_prompt_cont(const char *v, long flag);
-GEN sd_psfile(const char *v, long flag);
-GEN sd_readline(const char *v, long flag);
-GEN sd_recover(const char *v, long flag);
-GEN sd_timer(const char *v, long flag);
-#define MAX_PROMPT_LEN 128
-const char *do_prompt(char *buf, const char *prompt, filtre_t *F);
 
-extern entree  functions_highlevel[];
-/* list of GP-specific defaults */
-extern entree functions_gp_default[], functions_gp_rl_default[];
-/* list of GP-specific functions */
-extern entree  functions_gp[];
-/* list of old GP-specific fonctions (up to 1.39.15) */
-extern entree functions_oldgp[];
+extern void (*cb_gp_output)(GEN z);
+extern void (*cb_pari_end_output)(void);
 
+extern entree  functions_highlevel[], functions_gp[];
 ENDEXTERN
diff --git a/src/gp/gp_default.h b/src/gp/gp_default.h
deleted file mode 100644
index b7f6afa..0000000
--- a/src/gp/gp_default.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* This file is autogenerated from the database. */
-/* See src/desc/gen_proto */
-/* Do not edit*/
-entree functions_gp_default[]={
-{"breakloop",0,(void*)sd_breakloop,16,"",""},
-{"echo",0,(void*)sd_echo,16,"",""},
-{"graphcolormap",0,(void*)sd_graphcolormap,16,"",""},
-{"graphcolors",0,(void*)sd_graphcolors,16,"",""},
-{"help",0,(void*)sd_help,16,"",""},
-{"histfile",0,(void*)sd_histfile,16,"",""},
-{"lines",0,(void*)sd_lines,16,"",""},
-{"linewrap",0,(void*)sd_linewrap,16,"",""},
-{"prompt",0,(void*)sd_prompt,16,"",""},
-{"prompt_cont",0,(void*)sd_prompt_cont,16,"",""},
-{"psfile",0,(void*)sd_psfile,16,"",""},
-{"readline",0,(void*)sd_readline,16,"",""},
-{"recover",0,(void*)sd_recover,16,"",""},
-{"timer",0,(void*)sd_timer,16,"",""},
-{NULL,0,NULL,0,NULL,NULL} /* sentinel */
-};
diff --git a/src/gp/gp_init.c b/src/gp/gp_init.c
deleted file mode 100644
index 76745bc..0000000
--- a/src/gp/gp_init.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/* Copyright (C) 2000  The PARI group.
-
-This file is part of the PARI/GP package.
-
-PARI/GP 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. It is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY WHATSOEVER.
-
-Check the License for details. You should have received a copy of it, along
-with the package; see the file 'COPYING'. If not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
-
-/*******************************************************************/
-/*                                                                 */
-/*                    GP-SPECIFIC FUNCTIONS                        */
-/*                                                                 */
-/*******************************************************************/
-#include "pari.h"
-#include "paripriv.h"
-#include "../graph/rect.h"
-#include "gp.h"
-
-static void whatnow0(char *s) { whatnow(pariOut, s,0); }
-
-static void
-allocatemem0(GEN z)
-{
-  ulong newsize;
-  if (!z) newsize = 0;
-  else {
-    if (typ(z) != t_INT) pari_err_TYPE("allocatemem",z);
-    newsize = itou(z);
-    if (signe(z) < 0) pari_err_DOMAIN("allocatemem","size","<",gen_0,z);
-  }
-  allocatemem(newsize);
-}
-
-#include "gp_init.h"
-#include "gp_default.h"
-
-/* Backward Compatibility */
-
-static GEN
-gtype(GEN x)
-{
-  return stoi(typ(x));
-}
-
-static GEN
-gsettype(GEN x,long t)
-{
-  x=gcopy(x); settyp(x,t); return x;
-}
-
-static long
-setserieslength(long n)
-{
-  long m=precdl;
-  if(n>0) precdl=n;
-  return m;
-}
-
-static long
-setprecr(long n)
-{
-  long m = GP_DATA->fmt->sigd;
-  if (n > 0) { GP_DATA->fmt->sigd = n; precreal = ndec2prec(n); }
-  return m;
-}
-
-entree functions_oldgp[] = {
-{"allocatemem",11,(void *)allocatemem0,2,"vLp","allocatemem(s)=allocates a new stack of s bytes, or doubles the stack if size is 0"},
-{"box",35,(void *)rectbox,10,"vLGG","box(w,x2,y2)=if the cursor is at position (x1,y1), draw a box with diagonal (x1,y1) and (x2,y2) in rectwindow w (cursor does not move)"},
-{"color",2,(void *)rectcolor,2,"vLL","color(w,c)=set default color to c in rectwindow. Possible values for c are 1=sienna, 2=cornsilk, 3=red, 4=black, 5=grey, 6=blue, 7=gainsborough"},
-{"cursor",11,(void*)rectcursor,10,"vLp","cursor(w)=current position of cursor in rectwindow w"},
-{"default",0,(void*)default0,11,"D\"\",r,D\"\",s,D0,L,","default({opt},{v},{flag}): set the default opt to v. If v is omitted, print the current default for opt. If no argument is given, print a list of all defaults as well as their values. If flag is non-zero, return the result instead of printing it on screen. See manual for details"},
-{"draw",1,(void*)rectdraw,10,"vGp","draw(list)=draw vector of rectwindows list at indicated x,y positions; list is a vector w1,x1,y1,w2,x2,y2,etc..."},
-{"initrect",34,(void*)initrect,10,"vLLL","initrect(w,x,y)=initialize rectwindow w to size x,y"},
-{"kill",85,(void*)kill0,11,"vr","kill(x)=kills the present value of the variable or function x. Returns new value or 0"},
-{"killrect",11,(void *)killrect,10,"vL","killrect(w)=erase the rectwindow w"},
-{"line",35,(void *)rectline,10,"vLGG","line(w,x2,y2)=if cursor is at position (x1,y1), draw a line from (x1,y1) to (x2,y2) (and move the cursor) in the rectwindow w"},
-{"lines",35,(void *)rectlines,10,"vLGG","lines(w,listx,listy)=draws an open polygon in rectwindow w where listx and listy contain the x (resp. y) coordinates of the vertices"},
-{"move",35,(void*)rectmove,10,"vLGG","move(w,x,y)=move cursor to position x,y in rectwindow w"},
-{"plot",99,(void *)plot,10,"vV=GGEDGDGp","plot(X=a,b,expr)=crude plot of expression expr, X goes from a to b"},
-{"ploth",37,(void *)ploth,10,"V=GGEp","ploth(X=a,b,expr)=plot of expression expr, X goes from a to b in high resolution"},
-{"ploth2",37,(void *)ploth2,10,"V=GGEp","ploth2(X=a,b,[expr1,expr2])=plot of points [expr1,expr2], X goes from a to b in high resolution"},
-{"plothmult",37,(void *)plothmult,10,"V=GGEp","plothmult(X=a,b,[expr1,...])=plot of expressions expr1,..., X goes from a to b in high resolution"},
-{"plothraw",2,(void *)plothraw,10,"GGp","plothraw(listx,listy)=plot in high resolution points whose x (resp. y) coordinates are in listx (resp. listy)"},
-{"point",35,(void *)rectpoint,10,"vLGG","point(w,x,y)=draw a point (and move cursor) at position x,y in rectwindow w"},
-{"points",35,(void *)rectpoints,10,"vLGG","points(w,listx,listy)=draws in rectwindow w the points whose x (resp y) coordinates are in listx (resp listy)"},
-{"postdraw",1,(void *)postdraw,10,"vG","postdraw(list)=same as plotdraw, except that the output is a PostScript program in file \"pari.ps\""},
-{"postploth",37,(void *)postploth,10,"V=GGEpD0,L,D0,L,","postploth(X=a,b,expr)=same as ploth, except that the output is a PostScript program in the file \"pari.ps\""},
-{"postploth2",37,(void *)postploth2,10,"V=GGEpD0,L,","postploth2(X=a,b,[expr1,expr2])=same as ploth2, except that the output is a PostScript program in the file \"pari.ps\""},
-{"postplothraw",2,(void *)postplothraw,10,"GGD0,L,","postplothraw(listx,listy)=same as plothraw, except that the output is a PostScript program in the file \"pari.ps\""},
-{"pprint",0,(void*)print,11,"vs*","pprint(a)=outputs a in beautified format ending with newline"},
-{"pprint1",0,(void*)print1,11,"vs*","pprint1(a)=outputs a in beautified format without ending with newline"},
-{"print",0,(void*)print,11,"vs*","print(a)=outputs a in raw format ending with newline"},
-{"print1",0,(void*)print1,11,"vs*","print1(a)=outputs a in raw format without ending with newline"},
-{"rbox",35,(void *)rectrbox,10,"vLGG","rbox(w,dx,dy)=if the cursor is at (x1,y1), draw a box with diagonal (x1,y1)-(x1+dx,y1+dy) in rectwindow w (cursor does not move)"},
-{"read",0,(void *)input0,11,"","read()=read an expression from the input file or standard input"},
-{"rline",35,(void *)rectrline,10,"vLGG","rline(w,dx,dy)=if the cursor is at (x1,y1), draw a line from (x1,y1) to (x1+dx,y1+dy) (and move the cursor) in the rectwindow w"},
-{"rlines",35,(void *)rectlines,10,"vLGG","rlines(w,dx,dy)=draw in rectwindow w the points given by vector of first coordinates xsand vector of second coordinates, connect them by lines"},
-{"rmove",35,(void *)rectrmove,10,"vLGG","rmove(w,dx,dy)=move cursor to position (dx,dy) relative to the present position in the rectwindow w"},
-{"rpoint",35,(void *)rectrpoint,10,"vLGG","rpoint(w,dx,dy)=draw a point (and move cursor) at position dx,dy relative to present position of the cursor in rectwindow w"},
-{"rpoints",35,(void *)rectpoints,10,"vLGG","rpoints(w,xs,ys)=draw in rectwindow w the points given by vector of first coordinates xs and vector of second coordinates ys"},
-{"scale",59,(void *)rectscale,10,"vLGGGG","scale(w,x1,x2,y1,y2)=scale the coordinates in rectwindow w so that x goes from x1 to x2 and y from y1 to y2 (y2<y1 is allowed)"},
-{"setprecision",15,(void *)setprecr,2,"lL","setprecision(n)=set the current precision to n decimal digits if n>0, or return the current precision if n<=0"},
-{"setserieslength",15,(void *)setserieslength,2,"lL","setserieslength(n)=set the default length of power series to n if n>0, or return the current default length if n<=0"},
-{"settype",21,(void *)gsettype,2,"GL","settype(x,t)=make a copy of x with type t (to use with extreme care)"},
-{"string",57,(void*)rectstring,10,"vLs","string(w,x)=draw in rectwindow w the string corresponding to x, where x is either a string, or a number in R, written in format 9.3"},
-{"system",70,(void*) system0,11,"vs","system(a): a being a string, execute the system command a (not valid on every machine)"},
-{"texprint",0,(void*)printtex,11,"vs*","texprint(a)=outputs a in TeX format"},
-{"type",1,(void *)gtype,2,"Gp","type(x)=internal type number of the GEN x"},
-
-{NULL,0,NULL,0,NULL,NULL} /* sentinel */
-,};
diff --git a/src/gp/gp_init.h b/src/gp/gp_init.h
index f5d11bd..3fe2c09 100644
--- a/src/gp/gp_init.h
+++ b/src/gp/gp_init.h
@@ -2,19 +2,11 @@
 /* See src/desc/gen_proto */
 /* Do not edit*/
 entree functions_gp[]={
-{"alarm",0,(void*)gp_alarm,11,"D0,L,DE","alarm({s = 0},{code}): if code is omitted, trigger an \"e_ALARM\" exception after s seconds, cancelling any previously set alarm; stop a pending alarm if s = 0 or is omitted. Otherwise, evaluate code, aborting after s seconds."},
-{"allocatemem",0,(void*)allocatemem0,11,"vDG","allocatemem({s=0}): allocates a new stack of s bytes. doubles the stack if s is omitted."},
-{"breakpoint",0,(void*)pari_breakpoint,11,"v","breakpoint(): interrupt the program and enter the breakloop. The program continues when the breakloop is exited."},
-{"dbg_down",0,(void*)dbg_down,11,"vD1,L,","dbg_down({n=1}): (break loop) go down n frames. Cancel a previous dbg_up."},
-{"dbg_err",0,(void*)dbg_err,11,"","dbg_err(): (break loop) return the error data of the current error, if any."},
-{"dbg_up",0,(void*)dbg_up,11,"vD1,L,","dbg_up({n=1}): (break loop) go up n frames. Allow to inspect data of the parent function."},
-{"extern",0,(void*)extern0,11,"s","extern(str): execute shell command str, and feeds the result to GP (as if loading from file)."},
-{"externstr",0,(void*)externstr,11,"s","externstr(str): execute shell command str, and returns the result as a vector of GP strings, one component per output line."},
-{"input",0,(void*)input0,11,"","input(): read an expression from the input file or standard input."},
-{"quit",0,(void*)gp_quit,11,"vD0,L,","quit({status = 0}): quit, return to the system with exit status 'status'."},
-{"read",0,(void*)read0,11,"D\"\",s,","read({filename}): read from the input file filename. If filename is omitted, reread last input file, be it from read() or \\r."},
-{"readstr",0,(void*)readstr,11,"D\"\",s,","readstr({filename}): returns the vector of GP strings containing the lines in filename."},
-{"system",0,(void*)system0,11,"vs","system(str): str being a string, execute the system command str."},
-{"whatnow",0,(void*)whatnow0,11,"vr","whatnow(key): if key was present in GP version 1.39.15 or lower, gives the new function name."},
+{"breakpoint",0,(void*)pari_breakpoint,13,"v","breakpoint(): interrupt the program and enter the breakloop. The program continues when the breakloop is exited."},
+{"dbg_down",0,(void*)dbg_down,13,"vD1,L,","dbg_down({n=1}): (break loop) go down n frames. Cancel a previous dbg_up."},
+{"dbg_err",0,(void*)dbg_err,13,"","dbg_err(): (break loop) return the error data of the current error, if any."},
+{"dbg_up",0,(void*)dbg_up,13,"vD1,L,","dbg_up({n=1}): (break loop) go up n frames. Allow to inspect data of the parent function."},
+{"quit",0,(void*)gp_quit,13,"vD0,L,","quit({status = 0}): quit, return to the system with exit status 'status'."},
+{"whatnow",0,(void*)whatnow0,13,"vr","whatnow(key): if key was present in GP version 1.39.15 or lower, gives the new function name."},
 {NULL,0,NULL,0,NULL,NULL} /* sentinel */
 };
diff --git a/src/gp/gp_rl.c b/src/gp/gp_rl.c
index 069deac..9919cae 100644
--- a/src/gp/gp_rl.c
+++ b/src/gp/gp_rl.c
@@ -35,11 +35,6 @@ BEGINEXTERN
 ENDEXTERN
 
 /**************************************************************************/
-
-enum { DO_MATCHED_INSERT = 2, DO_ARGS_COMPLETE = 4 };
-static ulong readline_state = DO_ARGS_COMPLETE;
-static char *current_histfile = NULL;
-
 static int pari_rl_back;
 static int did_init_matched = 0;
 static entree *current_ep = NULL;
@@ -47,8 +42,8 @@ static entree *current_ep = NULL;
 static int
 change_state(const char *msg, ulong flag, int count)
 {
-  int c = (readline_state & flag) != 0;
-  ulong o_readline_state = readline_state;
+  int c = (GP_DATA->readline_state & flag) != 0;
+  ulong state = GP_DATA->readline_state;
 
   switch(count)
   {
@@ -57,11 +52,10 @@ change_state(const char *msg, ulong flag, int count)
     case -2: c = 1 - c; /* toggle */
   }
   if (c)
-    readline_state |= flag;
+    GP_DATA->readline_state |= flag;
   else {
-    readline_state &= ~flag;
-    if (!readline_state && o_readline_state)
-        readline_state = 1;
+    GP_DATA->readline_state &= ~flag;
+    if (!GP_DATA->readline_state && state) GP_DATA->readline_state = 1;
   }
   rl_save_prompt();
   rl_message("[%s: %s] ", msg, c? "on": "off");
@@ -95,13 +89,12 @@ static int did_matched_insert;
 static int
 pari_rl_matched_insert_suspend(int count, int key)
 {
-  ulong o_readline_state = readline_state;
+  ulong state = GP_DATA->readline_state;
   (void)count; (void)key;
 
-  did_matched_insert = (readline_state & DO_MATCHED_INSERT);
-  readline_state &= ~DO_MATCHED_INSERT;
-  if (!readline_state && o_readline_state)
-    readline_state = 1;
+  did_matched_insert = (GP_DATA->readline_state & DO_MATCHED_INSERT);
+  GP_DATA->readline_state &= ~DO_MATCHED_INSERT;
+  if (!GP_DATA->readline_state && state) GP_DATA->readline_state = 1;
   return 1;
 }
 
@@ -110,7 +103,7 @@ pari_rl_matched_insert_restore(int count, int key)
 {
   (void)count; (void)key;
   if (did_matched_insert)
-    readline_state |= DO_MATCHED_INSERT;
+    GP_DATA->readline_state |= DO_MATCHED_INSERT;
   return 1;
 }
 
@@ -126,7 +119,7 @@ pari_rl_matched_insert(int count, int key)
   if (count <= 0)
     return change_state("electric parens", DO_MATCHED_INSERT, count);
   while (paropen[i] && paropen[i] != key) i++;
-  if (!paropen[i] || !(readline_state & DO_MATCHED_INSERT) || GP_DATA->flags & gpd_EMACS)
+  if (!paropen[i] || !(GP_DATA->readline_state & DO_MATCHED_INSERT) || GP_DATA->flags & gpd_EMACS)
     return ((RLCI)rl_insert)(count,key);
   rl_begin_undo_group();
   ((RLCI)rl_insert)(count,key);
@@ -140,7 +133,7 @@ pari_rl_default_matched_insert(int count, int key)
 {
     if (!did_init_matched) {
       did_init_matched = 1;
-      readline_state |= DO_MATCHED_INSERT;
+      GP_DATA->readline_state |= DO_MATCHED_INSERT;
     }
     return pari_rl_matched_insert(count, key);
 }
@@ -307,39 +300,6 @@ get_matches(int code, const char *text, GF f)
 }
 
 static char *
-generator(void *list, const char *text, int *nn, int len)
-{
-  const char *def = NULL;
-  int n = *nn;
-
-  /* Return the next name which partially matches from list.*/
-  do
-    def = (((entree *) list)[n++]).name;
-  while (def && strncmp(def,text,len));
-  *nn = n;
-  if (def)
-  {
-    char *name = strcpy((char*)pari_malloc(strlen(def)+1), def);
-    return name;
-  }
-  return NULL; /* no names matched */
-}
-static char *
-old_generator(const char *text,int state)
-{
-  static int n,len;
-  static char *res;
-
-  if (!state) { res = (char*)"a"; n=0; len=strlen(text); }
-  if (res)
-  {
-    res = generator((void *)oldfonctions,text,&n,len);
-    if (res) return res;
-    n=0;
-  }
-  return generator((void *)functions_oldgp,text,&n,len);
-}
-static char *
 add_prefix(const char *name, const char *text, long junk)
 {
   char *s = strncpy((char*)pari_malloc(strlen(name)+1+junk),text,junk);
@@ -355,8 +315,9 @@ init_prefix(const char *text, int *len, int *junk, char **TEXT)
   *junk = j;
   *len  = l - j;
 }
+
 static int
-is_internal(entree *ep) { return ep->menu >= 13 && ep->menu <= 15; }
+is_internal(entree *ep) { return *ep->name == '_'; }
 
 /* Generator function for command completion.  STATE lets us know whether
  * to start from scratch; without any state (i.e. STATE == 0), then we
@@ -474,7 +435,7 @@ rl_print_aide(char *s, int flag)
   rl_point = 0; rl_end = 0; pari_outfile = rl_outstream;
   rl_save_prompt();
   rl_message("%s",""); /* rl_message("") ==> "zero length format" warning */
-  aide(s, flag);
+  gp_help(s, flag);
   rl_restore_prompt();
   rl_point = p; rl_end = e; pari_outfile = save;
   rl_clear_message();
@@ -497,7 +458,7 @@ add_space(int start)
   m[1] = NULL; return m;
 }
 
-static char **
+char **
 pari_completion(char *text, int START, int END)
 {
   int i, first=0, start=START;
@@ -548,8 +509,6 @@ pari_completion(char *text, int START, int END)
 
     if (strncmp(rl_line_buffer + i,"default",7) == 0)
       return get_matches(-2, text, default_generator);
-    if (strncmp(rl_line_buffer + i,"whatnow",7) == 0)
-      return get_matches(-1, text, old_generator);
     if ( strncmp(rl_line_buffer + i,"read",4)  == 0
       || strncmp(rl_line_buffer + i,"write",5) == 0)
       return get_matches(-1, text, rl_filename_completion_function);
@@ -559,7 +518,7 @@ pari_completion(char *text, int START, int END)
     k = END;
     while (k > j && isspace((int)rl_line_buffer[k])) k--;
     /* If we are in empty parens, insert the default arguments */
-    if ((readline_state & DO_ARGS_COMPLETE) && k == j
+    if ((GP_DATA->readline_state & DO_ARGS_COMPLETE) && k == j
          && (rl_line_buffer[j] == ')' || !rl_line_buffer[j])
          && (iend - i < (long)sizeof(buf))
          && ( strncpy(buf, rl_line_buffer + i, iend - i),
@@ -618,192 +577,15 @@ rl_long_help(int count, int key) { (void)count; return rl_short_help(-1,key); }
 static void
 init_histfile(void)
 {
-  if (current_histfile && read_history(current_histfile))
-    write_history(current_histfile);
-}
-
-void
-init_readline(void)
-{
-  static int init_done = 0;
-
-  if (init_done) return;
-  if (! GP_DATA->use_readline) readline_state = 0;
-  init_done = 1;
-  init_histfile();
-
-  /* Allow conditional parsing of the ~/.inputrc file. */
-  rl_readline_name = "Pari-GP";
-
-  /* added ~, ? and , */
-  rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{(?~";
-  rl_special_prefixes = "~";
-
-  /* custom completer */
-  rl_attempted_completion_function = (rl_completion_func_t*) pari_completion;
-
-  /* we always want the whole list of completions under emacs */
-  if (GP_DATA->flags & gpd_EMACS) rl_completion_query_items = 0x8fff;
-
-  rl_add_defun("short-help", rl_short_help, -1);
-  rl_add_defun("long-help", rl_long_help, -1);
-  rl_add_defun("pari-complete", pari_rl_complete, '\t');
-  rl_add_defun("pari-matched-insert", pari_rl_default_matched_insert, -1);
-  rl_add_defun("pari-matched-insert-suspend", pari_rl_matched_insert_suspend, -1);
-  rl_add_defun("pari-matched-insert-restore", pari_rl_matched_insert_restore, -1);
-  rl_add_defun("pari-forward-sexp", pari_rl_forward_sexp, -1);
-  rl_add_defun("pari-backward-sexp", pari_rl_backward_sexp, -1);
-
-  rl_bind_key_in_map('h', rl_short_help, emacs_meta_keymap);
-  rl_bind_key_in_map('H', rl_long_help,  emacs_meta_keymap);
-
-#define KSbind(s,f,k) rl_generic_bind(ISFUNC, (s), (char*)(f), (k))
-
-  KSbind("OP",   rl_short_help,  emacs_meta_keymap); /* f1, vt100 */
-  KSbind("[11~", rl_short_help,  emacs_meta_keymap); /* f1, xterm */
-  KSbind("OP",   rl_short_help,  vi_movement_keymap); /* f1, vt100 */
-  KSbind("[11~", rl_short_help,  vi_movement_keymap); /* f1, xterm */
-  /* XTerm may signal start/end of paste by emitting F200/F201
-   * TODO: check to what extent this patch has been applied */
-  /* FIXME: For vi mode something more intelligent is needed - to switch to the
-     insert mode - and back when restoring. */
-  KSbind("[200~", pari_rl_matched_insert_suspend,  emacs_meta_keymap);  /* pre-paste xterm */
-  KSbind("[200~", pari_rl_matched_insert_suspend,  vi_movement_keymap); /* pre-paste xterm */
-  KSbind("[201~", pari_rl_matched_insert_restore,  emacs_meta_keymap);  /* post-paste xterm */
-  KSbind("[201~", pari_rl_matched_insert_restore,  vi_movement_keymap); /* post-paste xterm */
-  rl_bind_key_in_map('(', pari_rl_matched_insert, emacs_standard_keymap);
-  rl_bind_key_in_map('[', pari_rl_matched_insert, emacs_standard_keymap);
-  rl_bind_key_in_map(6, pari_rl_forward_sexp,  emacs_meta_keymap); /* M-C-f */
-  rl_bind_key_in_map(2, pari_rl_backward_sexp, emacs_meta_keymap); /* M-C-b */
-}
-
-void
-readline_prompt_color(char *s, int c)
-{
-#ifdef RL_PROMPT_START_IGNORE
-  *s++ = RL_PROMPT_START_IGNORE;
-  term_get_color(s, c);
-  s += strlen(s);
-  *s++ = RL_PROMPT_END_IGNORE;
-  *s = 0;
-#else
-  term_get_color(s, c);
-#endif
-}
-
-/* readline-specific defaults */
-GEN
-sd_readline(const char *v, long flag)
-{
-  const char *msg[] = {
-    "(bits 0x2/0x4 control matched-insert/arg-complete)", NULL};
-  ulong o_readline_state = readline_state;
-  GEN res = sd_ulong(v,flag,"readline", &readline_state, 0, 7, msg);
-
-  if (o_readline_state != readline_state)
-    (void)sd_toggle(readline_state? "1": "0", d_SILENT, "readline", &(GP_DATA->use_readline));
-  return res;
-}
-GEN
-sd_histfile(const char *v, long flag)
-{
-  char *old = current_histfile;
-  GEN r = sd_string(v, flag, "histfile", &current_histfile);
-  if (v && !*v)
-  {
-    free(current_histfile);
-    current_histfile = NULL;
-  }
-  else if (current_histfile != old && (!old || strcmp(old,current_histfile)))
-    init_histfile();
-  return r;
-}
-
-static void
-print_escape_string(char *s)
-{
-  long l = strlen(s);
-  char *t, *t0 = (char*)pari_malloc(l * 3 + 3);
-
-  t = t0; *t++ = '"';
-  for ( ;*s; *t++ = *s++)
-    switch(*s)
-    {
-      case DATA_BEGIN:
-      case DATA_END:
-      case DATA_ESCAPE: *t++ = DATA_ESCAPE; continue;
-
-      case '\\':
-      case '"': *t++ = '\\'; continue;
-    }
-  *t++ = '"';
-  *t = '\0'; puts(t0); pari_free(t0);
-}
-
-static char *
-completion_word(long end)
-{
-  char *s = rl_line_buffer + end, *found_quote = NULL;
-  long i;
-  /* truncate at cursor position */
-  *s = 0;
-  /* first look for unclosed string */
-  for (i=0; i < end; i++)
-  {
-    switch(rl_line_buffer[i])
-    {
-      case '"':
-        found_quote = found_quote? NULL: rl_line_buffer + i;
-        break;
-
-      case '\\': i++; break;
-    }
-
-  }
-  if (found_quote) return found_quote + 1; /* return next char after quote */
-
-  /* else find beginning of word */
-  while (s >  rl_line_buffer)
-  {
-    s--;
-    if (!is_keyword_char(*s)) { s++; break; }
-  }
-  return s;
-}
-
-/* completion required, cursor on s + pos. Complete wrt strict left prefix */
-void
-texmacs_completion(const char *s, long pos)
-{
-  char **matches, *text;
-
-  if (rl_line_buffer) pari_free(rl_line_buffer);
-  rl_line_buffer = pari_strdup(s);
-  text = completion_word(pos);
-  /* text = start of expression we complete */
-  rl_end = strlen(s)-1;
-  rl_point = pos;
-  matches = pari_completion(text, text - rl_line_buffer, pos);
-  printf("%cscheme:(tuple",DATA_BEGIN);
-  if (matches)
-  {
-    long i, prelen = (rl_line_buffer+pos) - text;
-    char *t = (char*)pari_malloc(prelen+1);
-    strncpy(t, text, prelen); t[prelen] = 0; /* prefix */
-    printf(" ");
-    print_escape_string(t); pari_free(t);
-    for (i = matches[1]? 1: 0; matches[i]; i++)
-    {
-      printf(" ");
-      print_escape_string(matches[i] + prelen);
-      pari_free(matches[i]);
-    }
-    pari_free(matches);
-  }
-  printf(")%c", DATA_END);
-  fflush(stdout);
+  char *h = GP_DATA->histfile;
+  if (h && read_history(h)) write_history(h);
 }
 
+/*******************************************************************/
+/*                                                                 */
+/*                   GET LINE FROM READLINE                        */
+/*                                                                 */
+/*******************************************************************/
 static int
 history_is_new(char *s)
 {
@@ -818,7 +600,7 @@ history_is_new(char *s)
 static void
 gp_add_history(char *s)
 {
-  if (history_is_new(s)) { add_history(s); append_history(1,current_histfile); }
+  if (history_is_new(s)) { add_history(s); append_history(1,GP_DATA->histfile); }
 }
 
 /* Read line; returns a malloc()ed string of the user input or NULL on EOF.
@@ -826,15 +608,19 @@ gp_add_history(char *s)
 static char *
 gprl_input(char **endp, int first, input_method *IM, filtre_t *F)
 {
-  char buf[MAX_PROMPT_LEN + 24];
+  pari_sp av = avma;
   Buffer *b = F->buf;
   ulong used = *endp - b->buf;
   ulong left = b->len - used, l;
-  const char *prompt = first? IM->prompt
-                            : do_prompt(buf, IM->prompt_cont, F);
+  const char *p;
   char *s, *t;
 
-  if (! (s = readline(prompt)) ) return NULL; /* EOF */
+  if (first) p = IM->prompt;
+  else {
+    p = F->in_comment ? GP_DATA->prompt_comment: IM->prompt_cont;
+    p = gp_format_prompt(p);
+  }
+  if (! (s = readline(p)) ) { avma = av; return NULL; } /* EOF */
   gp_add_history(s); /* Makes a copy */
   l = strlen(s) + 1;
   /* put back \n that readline stripped. This is needed for
@@ -852,7 +638,7 @@ gprl_input(char **endp, int first, input_method *IM, filtre_t *F)
     fix_buffer(b, b->len + incr);
     *endp = b->buf + used;
   }
-  return t;
+  avma = av; return t;
 }
 
 /* request one line interactively.
@@ -865,6 +651,12 @@ get_line_from_readline(const char *prompt, const char *prompt_cont, filtre_t *F)
   char *s;
   input_method IM;
 
+  if (!GP_DATA->use_readline)
+  {
+    pari_puts(prompt); pari_flush();
+    return get_line_from_file(prompt, F, pari_infile);
+  }
+
   IM.prompt      = prompt;
   IM.prompt_cont = prompt_cont;
   IM.getline = &gprl_input;
@@ -883,8 +675,65 @@ get_line_from_readline(const char *prompt, const char *prompt_cont, filtre_t *F)
       }
       gp_add_history(s);
     }
-    echo_and_log(prompt, s);
+    gp_echo_and_log(prompt, s);
   }
   return 1;
 }
+
+void
+init_readline(void)
+{
+  static int init_done = 0;
+
+  if (init_done) return;
+  if (! GP_DATA->use_readline) GP_DATA->readline_state = 0;
+  init_done = 1;
+  init_histfile();
+  cb_pari_init_histfile = init_histfile;
+  cb_pari_get_line_interactive = get_line_from_readline;
+
+  /* Allow conditional parsing of the ~/.inputrc file. */
+  rl_readline_name = "Pari-GP";
+
+  /* added ~, ? and , */
+  rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{(?~";
+  rl_special_prefixes = "~";
+
+  /* custom completer */
+  rl_attempted_completion_function = (rl_completion_func_t*) pari_completion;
+
+  /* we always want the whole list of completions under emacs */
+  if (GP_DATA->flags & gpd_EMACS) rl_completion_query_items = 0x8fff;
+
+  rl_add_defun("short-help", rl_short_help, -1);
+  rl_add_defun("long-help", rl_long_help, -1);
+  rl_add_defun("pari-complete", pari_rl_complete, '\t');
+  rl_add_defun("pari-matched-insert", pari_rl_default_matched_insert, -1);
+  rl_add_defun("pari-matched-insert-suspend", pari_rl_matched_insert_suspend, -1);
+  rl_add_defun("pari-matched-insert-restore", pari_rl_matched_insert_restore, -1);
+  rl_add_defun("pari-forward-sexp", pari_rl_forward_sexp, -1);
+  rl_add_defun("pari-backward-sexp", pari_rl_backward_sexp, -1);
+
+  rl_bind_key_in_map('h', rl_short_help, emacs_meta_keymap);
+  rl_bind_key_in_map('H', rl_long_help,  emacs_meta_keymap);
+
+#define KSbind(s,f,k) rl_generic_bind(ISFUNC, (s), (char*)(f), (k))
+
+  KSbind("OP",   rl_short_help,  emacs_meta_keymap); /* f1, vt100 */
+  KSbind("[11~", rl_short_help,  emacs_meta_keymap); /* f1, xterm */
+  KSbind("OP",   rl_short_help,  vi_movement_keymap); /* f1, vt100 */
+  KSbind("[11~", rl_short_help,  vi_movement_keymap); /* f1, xterm */
+  /* XTerm may signal start/end of paste by emitting F200/F201
+   * TODO: check to what extent this patch has been applied */
+  /* FIXME: For vi mode something more intelligent is needed - to switch to the
+     insert mode - and back when restoring. */
+  KSbind("[200~", pari_rl_matched_insert_suspend,  emacs_meta_keymap);  /* pre-paste xterm */
+  KSbind("[200~", pari_rl_matched_insert_suspend,  vi_movement_keymap); /* pre-paste xterm */
+  KSbind("[201~", pari_rl_matched_insert_restore,  emacs_meta_keymap);  /* post-paste xterm */
+  KSbind("[201~", pari_rl_matched_insert_restore,  vi_movement_keymap); /* post-paste xterm */
+  rl_bind_key_in_map('(', pari_rl_matched_insert, emacs_standard_keymap);
+  rl_bind_key_in_map('[', pari_rl_matched_insert, emacs_standard_keymap);
+  rl_bind_key_in_map(6, pari_rl_forward_sexp,  emacs_meta_keymap); /* M-C-f */
+  rl_bind_key_in_map(2, pari_rl_backward_sexp, emacs_meta_keymap); /* M-C-b */
+}
 #endif
diff --git a/src/gp/highlvl.h b/src/gp/highlvl.h
index 28ca5ca..84806d0 100644
--- a/src/gp/highlvl.h
+++ b/src/gp/highlvl.h
@@ -2,34 +2,34 @@
 /* See src/desc/gen_proto */
 /* Do not edit*/
 entree functions_highlevel[]={
-{"plot",0,(void*)plot,10,"vV=GGEDGDGp","plot(X=a,b,expr,{Ymin},{Ymax}): crude plot of expression expr, X goes from a to b, with Y ranging from Ymin to Ymax. If Ymin (resp. Ymax) is not given, the minimum (resp. the maximum) of the expression is used instead."},
-{"plotbox",0,(void*)rectbox,10,"vLGG","plotbox(w,x2,y2): if the cursor is at position (x1,y1), draw a box with diagonal (x1,y1) and (x2,y2) in rectwindow w (cursor does not move)."},
-{"plotclip",0,(void*)rectclip,10,"vL","plotclip(w): clip the contents of the rectwindow to the bounding box (except strings)."},
-{"plotcolor",0,(void*)rectcolor,10,"vLL","plotcolor(w,c): in rectwindow w, set default color to c. Possible values for c are given by the graphcolormap default: factory settings are 1=black, 2=blue, 3=sienna, 4=red, 5=green, 6=grey, 7=gainsborough."},
-{"plotcopy",0,(void*)rectcopy_gen,10,"vLLGGD0,L,","plotcopy(sourcew,destw,dx,dy,{flag=0}): copy the contents of rectwindow sourcew to rectwindow destw with offset (dx,dy). If flag's bit 1 is set, dx and dy express fractions of the size of the current output device, otherwise dx and dy are in pixels. dx and dy are relative positions of northwest corners if other bits of flag vanish, otherwise of: 2: southwest, 4: southeast, 6: northeast corners."},
-{"plotcursor",0,(void*)rectcursor,10,"L","plotcursor(w): current position of cursor in rectwindow w."},
-{"plotdraw",0,(void*)rectdraw_flag,10,"vGD0,L,","plotdraw(list, {flag=0}): draw vector of rectwindows list at indicated x,y positions; list is a vector w1,x1,y1,w2,x2,y2,etc. If flag!=0, x1, y1 etc. express fractions of the size of the current output device."},
-{"ploth",0,(void*)ploth,10,"V=GGEpD0,M,D0,L,\nParametric|1; Recursive|2; no_Rescale|4; no_X_axis|8; no_Y_axis|16; no_Frame|32; no_Lines|64; Points_too|128; Splines|256; no_X_ticks|512; no_Y_ticks|1024; Same_ticks|2048; Complex|4096","ploth(X=a,b,expr,{flags=0},{n=0}): plot of expression expr, X goes from a to b in high resolution. Both flags and n are optional. Binary digits of flags mean: 1=Parametric, 2=Recursive, 4=no_Rescale, 8=no_X_axis, 16=no_Y_axis, 32=no_Frame, 64=no_Lines (do no [...]
-{"plothraw",0,(void*)plothraw,10,"GGD0,L,","plothraw(listx,listy,{flag=0}): plot in high resolution points whose x (resp. y) coordinates are in listx (resp. listy). If flag is 1, join points, other non-0 flags should be combinations of bits 8,16,32,64,128,256 meaning the same as for ploth()."},
-{"plothsizes",0,(void*)plothsizes_flag,10,"D0,L,","plothsizes({flag=0}): returns array of 6 elements: terminal width and height, sizes for ticks in horizontal and vertical directions, width and height of characters. If flag=0, sizes of ticks and characters are in pixels, otherwise are fractions of the screen size."},
-{"plotinit",0,(void*)initrect_gen,10,"vLDGDGD0,L,","plotinit(w,{x},{y},{flag=0}): initialize rectwindow w to size x,y. If flag!=0, x and y express fractions of the size of the current output device. Omitting x or y means use the full size of the device."},
-{"plotkill",0,(void*)killrect,10,"vL","plotkill(w): erase the rectwindow w."},
-{"plotlines",0,(void*)rectlines,10,"vLGGD0,L,","plotlines(w,X,Y,{flag=0}): draws an open polygon in rectwindow w where X and Y contain the x (resp. y) coordinates of the vertices. If X and Y are both single values (i.e not vectors), draw the corresponding line (and move cursor). If (optional) flag is non-zero, close the polygon."},
-{"plotlinetype",0,(void*)rectlinetype,10,"vLL","plotlinetype(w,type): change the type of following lines in rectwindow w. type -2 corresponds to frames, -1 to axes, larger values may correspond to something else. w=-1 changes highlevel plotting."},
-{"plotmove",0,(void*)rectmove,10,"vLGG","plotmove(w,x,y): move cursor to position x,y in rectwindow w."},
-{"plotpoints",0,(void*)rectpoints,10,"vLGG","plotpoints(w,X,Y): draws in rectwindow w the points whose x (resp y) coordinates are in X (resp Y). If X and Y are both single values (i.e not vectors), draw the corresponding point (and move cursor)."},
-{"plotpointsize",0,(void*)rectpointsize,10,"vLG","plotpointsize(w,size): change the \"size\" of following points in rectwindow w. w=-1 changes global value."},
-{"plotpointtype",0,(void*)rectpointtype,10,"vLL","plotpointtype(w,type): change the type of following points in rectwindow w. type -1 corresponds to a dot, larger values may correspond to something else. w=-1 changes highlevel plotting."},
-{"plotrbox",0,(void*)rectrbox,10,"vLGG","plotrbox(w,dx,dy): if the cursor is at (x1,y1), draw a box with diagonal (x1,y1)-(x1+dx,y1+dy) in rectwindow w (cursor does not move)."},
-{"plotrecth",0,(void*)rectploth,10,"LV=GGEpD0,M,D0,L,\nParametric|1; Recursive|2; no_Rescale|4; no_X_axis|8; no_Y_axis|16; no_Frame|32; no_Lines|64; Points_too|128; Splines|256; no_X_ticks|512; no_Y_ticks|1024; Same_ticks|2048; Complex|4096","plotrecth(w,X=a,b,expr,{flag=0},{n=0}): writes to rectwindow w the curve output of ploth(w,X=a,b,expr,flag,n). Returns a vector for the bounding box."},
-{"plotrecthraw",0,(void*)rectplothraw,10,"LGD0,L,","plotrecthraw(w,data,{flags=0}): plot graph(s) for data in rectwindow w, where data is a vector of vectors. If plot is parametric, length of data should be even, and pairs of entries give curves to plot. If not, first entry gives x-coordinate, and the other ones y-coordinates. Admits the same optional flags as plotrecth, save that recursive plot is meaningless."},
-{"plotrline",0,(void*)rectrline,10,"vLGG","plotrline(w,dx,dy): if the cursor is at (x1,y1), draw a line from (x1,y1) to (x1+dx,y1+dy) (and move the cursor) in the rectwindow w."},
-{"plotrmove",0,(void*)rectrmove,10,"vLGG","plotrmove(w,dx,dy): move cursor to position (dx,dy) relative to the present position in the rectwindow w."},
-{"plotrpoint",0,(void*)rectrpoint,10,"vLGG","plotrpoint(w,dx,dy): draw a point (and move cursor) at position dx,dy relative to present position of the cursor in rectwindow w."},
-{"plotscale",0,(void*)rectscale,10,"vLGGGG","plotscale(w,x1,x2,y1,y2): scale the coordinates in rectwindow w so that x goes from x1 to x2 and y from y1 to y2 (y2<y1 is allowed)."},
-{"plotstring",0,(void*)rectstring3,10,"vLsD0,L,","plotstring(w,x,{flags=0}): draw in rectwindow w the string corresponding to x. Bits 1 and 2 of flag regulate horizontal alignment: left if 0, right if 2, center if 1. Bits 4 and 8 regulate vertical alignment: bottom if 0, top if 8, v-center if 4. Can insert additional gap between point and string: horizontal if bit 16 is set, vertical if bit 32 is set."},
-{"psdraw",0,(void*)postdraw_flag,10,"vGD0,L,","psdraw(list, {flag=0}): same as plotdraw, except that the output is a PostScript program in psfile (pari.ps by default), and flag!=0 scales the plot from size of the current output device to the standard PostScript plotting size."},
-{"psploth",0,(void*)postploth,10,"V=GGEpD0,L,D0,L,","psploth(X=a,b,expr,{flags=0},{n=0}): same as ploth, except that the output is a PostScript program in psfile (pari.ps by default)."},
-{"psplothraw",0,(void*)postplothraw,10,"GGD0,L,","psplothraw(listx,listy,{flag=0}): same as plothraw, except that the output is a postscript program in psfile (pari.ps by default)."},
+{"plot",0,(void*)plot,12,"vV=GGEDGDGp","plot(X=a,b,expr,{Ymin},{Ymax}): crude plot of expression expr, X goes from a to b, with Y ranging from Ymin to Ymax. If Ymin (resp. Ymax) is not given, the minimum (resp. the maximum) of the expression is used instead."},
+{"plotbox",0,(void*)rectbox,12,"vLGG","plotbox(w,x2,y2): if the cursor is at position (x1,y1), draw a box with diagonal (x1,y1) and (x2,y2) in rectwindow w (cursor does not move)."},
+{"plotclip",0,(void*)rectclip,12,"vL","plotclip(w): clip the contents of the rectwindow to the bounding box (except strings)."},
+{"plotcolor",0,(void*)rectcolor,12,"vLL","plotcolor(w,c): in rectwindow w, set default color to c. Possible values for c are given by the graphcolormap default: factory settings are 1=black, 2=blue, 3=sienna, 4=red, 5=green, 6=grey, 7=gainsborough."},
+{"plotcopy",0,(void*)rectcopy_gen,12,"vLLGGD0,L,","plotcopy(sourcew,destw,dx,dy,{flag=0}): copy the contents of rectwindow sourcew to rectwindow destw with offset (dx,dy). If flag's bit 1 is set, dx and dy express fractions of the size of the current output device, otherwise dx and dy are in pixels. dx and dy are relative positions of northwest corners if other bits of flag vanish, otherwise of: 2: southwest, 4: southeast, 6: northeast corners."},
+{"plotcursor",0,(void*)rectcursor,12,"L","plotcursor(w): current position of cursor in rectwindow w."},
+{"plotdraw",0,(void*)rectdraw_flag,12,"vGD0,L,","plotdraw(list, {flag=0}): draw vector of rectwindows list at indicated x,y positions; list is a vector w1,x1,y1,w2,x2,y2,etc. If flag!=0, x1, y1 etc. express fractions of the size of the current output device."},
+{"ploth",0,(void*)ploth,12,"V=GGEpD0,M,D0,L,\nParametric|1; Recursive|2; no_Rescale|4; no_X_axis|8; no_Y_axis|16; no_Frame|32; no_Lines|64; Points_too|128; Splines|256; no_X_ticks|512; no_Y_ticks|1024; Same_ticks|2048; Complex|4096","ploth(X=a,b,expr,{flags=0},{n=0}): plot of expression expr, X goes from a to b in high resolution. Both flags and n are optional. Binary digits of flags mean: 1=Parametric, 2=Recursive, 4=no_Rescale, 8=no_X_axis, 16=no_Y_axis, 32=no_Frame, 64=no_Lines (do no [...]
+{"plothraw",0,(void*)plothraw,12,"GGD0,L,","plothraw(listx,listy,{flag=0}): plot in high resolution points whose x (resp. y) coordinates are in listx (resp. listy). If flag is 1, join points, other non-0 flags should be combinations of bits 8,16,32,64,128,256 meaning the same as for ploth()."},
+{"plothsizes",0,(void*)plothsizes_flag,12,"D0,L,","plothsizes({flag=0}): returns array of 6 elements: terminal width and height, sizes for ticks in horizontal and vertical directions, width and height of characters. If flag=0, sizes of ticks and characters are in pixels, otherwise are fractions of the screen size."},
+{"plotinit",0,(void*)initrect_gen,12,"vLDGDGD0,L,","plotinit(w,{x},{y},{flag=0}): initialize rectwindow w to size x,y. If flag!=0, x and y express fractions of the size of the current output device. Omitting x or y means use the full size of the device."},
+{"plotkill",0,(void*)killrect,12,"vL","plotkill(w): erase the rectwindow w."},
+{"plotlines",0,(void*)rectlines,12,"vLGGD0,L,","plotlines(w,X,Y,{flag=0}): draws an open polygon in rectwindow w where X and Y contain the x (resp. y) coordinates of the vertices. If X and Y are both single values (i.e not vectors), draw the corresponding line (and move cursor). If (optional) flag is non-zero, close the polygon."},
+{"plotlinetype",0,(void*)rectlinetype,12,"vLL","plotlinetype(w,type): change the type of following lines in rectwindow w. type -2 corresponds to frames, -1 to axes, larger values may correspond to something else. w=-1 changes highlevel plotting."},
+{"plotmove",0,(void*)rectmove,12,"vLGG","plotmove(w,x,y): move cursor to position x,y in rectwindow w."},
+{"plotpoints",0,(void*)rectpoints,12,"vLGG","plotpoints(w,X,Y): draws in rectwindow w the points whose x (resp y) coordinates are in X (resp Y). If X and Y are both single values (i.e not vectors), draw the corresponding point (and move cursor)."},
+{"plotpointsize",0,(void*)rectpointsize,12,"vLG","plotpointsize(w,size): change the \"size\" of following points in rectwindow w. w=-1 changes global value."},
+{"plotpointtype",0,(void*)rectpointtype,12,"vLL","plotpointtype(w,type): change the type of following points in rectwindow w. type -1 corresponds to a dot, larger values may correspond to something else. w=-1 changes highlevel plotting."},
+{"plotrbox",0,(void*)rectrbox,12,"vLGG","plotrbox(w,dx,dy): if the cursor is at (x1,y1), draw a box with diagonal (x1,y1)-(x1+dx,y1+dy) in rectwindow w (cursor does not move)."},
+{"plotrecth",0,(void*)rectploth,12,"LV=GGEpD0,M,D0,L,\nParametric|1; Recursive|2; no_Rescale|4; no_X_axis|8; no_Y_axis|16; no_Frame|32; no_Lines|64; Points_too|128; Splines|256; no_X_ticks|512; no_Y_ticks|1024; Same_ticks|2048; Complex|4096","plotrecth(w,X=a,b,expr,{flag=0},{n=0}): writes to rectwindow w the curve output of ploth(w,X=a,b,expr,flag,n). Returns a vector for the bounding box."},
+{"plotrecthraw",0,(void*)rectplothraw,12,"LGD0,L,","plotrecthraw(w,data,{flags=0}): plot graph(s) for data in rectwindow w, where data is a vector of vectors. If plot is parametric, length of data should be even, and pairs of entries give curves to plot. If not, first entry gives x-coordinate, and the other ones y-coordinates. Admits the same optional flags as plotrecth, save that recursive plot is meaningless."},
+{"plotrline",0,(void*)rectrline,12,"vLGG","plotrline(w,dx,dy): if the cursor is at (x1,y1), draw a line from (x1,y1) to (x1+dx,y1+dy) (and move the cursor) in the rectwindow w."},
+{"plotrmove",0,(void*)rectrmove,12,"vLGG","plotrmove(w,dx,dy): move cursor to position (dx,dy) relative to the present position in the rectwindow w."},
+{"plotrpoint",0,(void*)rectrpoint,12,"vLGG","plotrpoint(w,dx,dy): draw a point (and move cursor) at position dx,dy relative to present position of the cursor in rectwindow w."},
+{"plotscale",0,(void*)rectscale,12,"vLGGGG","plotscale(w,x1,x2,y1,y2): scale the coordinates in rectwindow w so that x goes from x1 to x2 and y from y1 to y2 (y2<y1 is allowed)."},
+{"plotstring",0,(void*)rectstring3,12,"vLsD0,L,","plotstring(w,x,{flags=0}): draw in rectwindow w the string corresponding to x. Bits 1 and 2 of flag regulate horizontal alignment: left if 0, right if 2, center if 1. Bits 4 and 8 regulate vertical alignment: bottom if 0, top if 8, v-center if 4. Can insert additional gap between point and string: horizontal if bit 16 is set, vertical if bit 32 is set."},
+{"psdraw",0,(void*)postdraw_flag,12,"vGD0,L,","psdraw(list, {flag=0}): same as plotdraw, except that the output is a PostScript program in psfile (pari.ps by default), and flag!=0 scales the plot from size of the current output device to the standard PostScript plotting size."},
+{"psploth",0,(void*)postploth,12,"V=GGEpD0,L,D0,L,","psploth(X=a,b,expr,{flags=0},{n=0}): same as ploth, except that the output is a PostScript program in psfile (pari.ps by default)."},
+{"psplothraw",0,(void*)postplothraw,12,"GGD0,L,","psplothraw(listx,listy,{flag=0}): same as plothraw, except that the output is a postscript program in psfile (pari.ps by default)."},
 {NULL,0,NULL,0,NULL,NULL} /* sentinel */
 };
diff --git a/src/gp/texmacs.c b/src/gp/texmacs.c
new file mode 100644
index 0000000..b49eabd
--- /dev/null
+++ b/src/gp/texmacs.c
@@ -0,0 +1,268 @@
+/* Copyright (C) 2000  The PARI group.
+
+This file is part of the PARI/GP package.
+
+PARI/GP 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. It is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY WHATSOEVER.
+
+Check the License for details. You should have received a copy of it, along
+with the package; see the file 'COPYING'. If not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+/*******************************************************************/
+/*                                                                 */
+/*                    TEXMACS-SPECIFIC STUFF                       */
+/*                                                                 */
+/*******************************************************************/
+#include "pari.h"
+
+#include "paripriv.h"
+#include "gp.h"
+
+#define DATA_BEGIN  ((char) 2)
+#define DATA_END    ((char) 5)
+#define DATA_ESCAPE ((char) 27)
+
+/*******************************************************************/
+/*                                                                 */
+/*                      READLINE INTERFACE                         */
+/*                                                                 */
+/*******************************************************************/
+static int did_complete = 0;
+char **pari_completion(char *text, int START, int END);
+
+#ifdef READLINE
+BEGINEXTERN
+#include <readline/readline.h>
+ENDEXTERN
+
+static void
+print_escape_string(char *s)
+{
+  long l = strlen(s);
+  char *t, *t0 = (char*)pari_malloc(l * 3 + 3);
+
+  t = t0; *t++ = '"';
+  for ( ;*s; *t++ = *s++)
+    switch(*s)
+    {
+      case DATA_BEGIN:
+      case DATA_END:
+      case DATA_ESCAPE: *t++ = DATA_ESCAPE; continue;
+
+      case '\\':
+      case '"': *t++ = '\\'; continue;
+    }
+  *t++ = '"';
+  *t = '\0'; puts(t0); pari_free(t0);
+}
+
+static char *
+completion_word(long end)
+{
+  char *s = rl_line_buffer + end, *found_quote = NULL;
+  long i;
+  /* truncate at cursor position */
+  *s = 0;
+  /* first look for unclosed string */
+  for (i=0; i < end; i++)
+  {
+    switch(rl_line_buffer[i])
+    {
+      case '"':
+        found_quote = found_quote? NULL: rl_line_buffer + i;
+        break;
+
+      case '\\': i++; break;
+    }
+
+  }
+  if (found_quote) return found_quote + 1; /* return next char after quote */
+
+  /* else find beginning of word */
+  while (s >  rl_line_buffer)
+  {
+    s--;
+    if (!is_keyword_char(*s)) { s++; break; }
+  }
+  return s;
+}
+
+/* completion required, cursor on s + pos. Complete wrt strict left prefix */
+static void
+tm_completion(const char *s, long pos)
+{
+  char **matches, *text;
+
+  if (rl_line_buffer) pari_free(rl_line_buffer);
+  rl_line_buffer = pari_strdup(s);
+  text = completion_word(pos);
+  /* text = start of expression we complete */
+  rl_end = strlen(s)-1;
+  rl_point = pos;
+  matches = pari_completion(text, text - rl_line_buffer, pos);
+  printf("%cscheme:(tuple",DATA_BEGIN);
+  if (matches)
+  {
+    long i, prelen = (rl_line_buffer+pos) - text;
+    char *t = (char*)pari_malloc(prelen+1);
+    strncpy(t, text, prelen); t[prelen] = 0; /* prefix */
+    printf(" ");
+    print_escape_string(t); pari_free(t);
+    for (i = matches[1]? 1: 0; matches[i]; i++)
+    {
+      printf(" ");
+      print_escape_string(matches[i] + prelen);
+      pari_free(matches[i]);
+    }
+    pari_free(matches);
+  }
+  printf(")%c", DATA_END);
+  fflush(stdout);
+}
+#else
+/* no-op */
+static void
+tm_completion(const char *s, long pos) { (void)s; (void)pos; }
+#endif
+
+typedef struct {
+  char *cmd;
+  long n; /* number of args */
+  char **v; /* args */
+} tm_cmd;
+
+static void
+tm_parse_command(tm_cmd *c, const char *ch)
+{
+  long l = strlen(ch);
+  char *t, *s = (char*)ch, *send = s+l-1;
+  char **A;
+  pari_stack s_A;
+
+  if (*s != DATA_BEGIN || *send-- != DATA_END)
+    pari_err(e_MISC, "missing DATA_[BEGIN | END] in TeXmacs command");
+  s++;
+  if (strncmp(s, "special:", 8)) pari_err(e_MISC, "unrecognized TeXmacs command");
+  s += 8;
+  if (*s != '(' || *send-- != ')')
+    pari_err(e_MISC, "missing enclosing parentheses for TeXmacs command");
+  s++; t = s;
+  pari_skip_alpha(&s);
+  c->cmd = pari_strndup(t, s - t);
+  pari_stack_init(&s_A,sizeof(*A),(void**)&A);
+  for (c->n = 0; s <= send; c->n++)
+  {
+    char *u = (char*)pari_malloc(strlen(s) + 1);
+    pari_skip_space(&s);
+    if (*s == '"') s = pari_translate_string(s, u, t);
+    else
+    { /* read integer */
+      t = s;
+      while (isdigit((int)*s)) s++;
+      strncpy(u, t, s - t); u[s-t] = 0;
+    }
+    pari_stack_pushp(&s_A, u);
+  }
+  c->v = A;
+}
+
+static void
+tm_free_cmd(tm_cmd *c)
+{
+  while (c->n--) pari_free((void*)c->v[c->n]);
+  pari_free((void*)c->v);
+}
+
+static void
+tm_handle_command(const char *s)
+{
+  tm_cmd c;
+  tm_parse_command(&c, s);
+  if (strcmp(c.cmd, "complete"))
+    pari_err(e_MISC,"Texmacs command %s not implemented", c.cmd);
+  if (c.n != 2)
+    pari_err(e_MISC,"was expecting 2 arguments for Texmacs command");
+  tm_completion(c.v[0], atol(c.v[1]));
+  tm_free_cmd(&c);
+  did_complete = 1;
+}
+
+/****/
+
+int
+tm_is_interactive() { return 0; }
+
+static int tm_is_waiting = 0;
+/* tell TeXmacs GP will start outputing data */
+void
+tm_start_output(void)
+{
+  if (!tm_is_waiting) { printf("%cverbatim:",DATA_BEGIN); fflush(stdout); }
+  tm_is_waiting = 1;
+}
+/* tell TeXmacs GP is done and is waiting for new data */
+void
+tm_end_output(void)
+{
+  if (tm_is_waiting) { printf("%c", DATA_END); fflush(stdout); }
+  tm_is_waiting = 0;
+}
+char *
+tm_fgets(char *s, int n, FILE *f)
+{
+  if (!did_complete)
+  { /* we need input */
+    tm_start_output();
+    tm_end_output();
+  }
+  return fgets(s,n,f);
+}
+
+int
+tm_get_line(const char *prompt, const char *prompt_cont, filtre_t *F)
+{
+  int res = get_line_from_file(prompt, F, pari_infile);
+  (void)prompt_cont;
+  if (res)
+  {
+    char *s = F->buf->buf;
+    did_complete = 0;
+    if (pari_infile == stdin && *s == DATA_BEGIN)
+    { tm_handle_command(s); *s = 0; }
+    else
+      tm_start_output();
+  }
+  return res;
+}
+
+void
+tm_output(GEN z)
+{
+  char *sz = GENtoTeXstr(z);
+  printf("%clatex:", DATA_BEGIN);
+  printf("\\magenta\\%%%ld = ", GP_DATA->hist->total);
+  printf("$\\blue %s$%c", sz,DATA_END);
+  pari_free(sz); fflush(stdout);
+  pari_flush();
+}
+
+void
+init_texmacs(void)
+{
+#ifdef READLINE
+  printf("%ccommand:(cas-supports-completions-set! \"pari\")%c\n",
+         DATA_BEGIN, DATA_END);
+#endif
+  cb_pari_fgets_interactive = tm_fgets;
+  cb_pari_get_line_interactive = tm_get_line;
+
+  cb_pari_start_output = tm_start_output;
+  cb_pari_end_output = tm_end_output;
+  cb_pari_is_interactive = tm_is_interactive;
+  cb_gp_output = tm_output;
+  disable_color = 1;
+  tm_start_output();
+}
diff --git a/src/gp/whatnow.c b/src/gp/whatnow.c
index 6d3b2c7..d13791d 100644
--- a/src/gp/whatnow.c
+++ b/src/gp/whatnow.c
@@ -14,17 +14,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 #include "pari.h"
 #include "paripriv.h"
 #include "gp.h"
-
-typedef struct whatnow_t
-{
-  const char *name, *oldarg, *newarg;
-} whatnow_t;
-
-#define SAME NULL
-#define REMOV (char *)1L
-#define _REMOV {REMOV,NULL,NULL}
-#define _SAME  {SAME,NULL,NULL}
-
 #include "whatnow.h"
 
 static void
@@ -42,35 +31,21 @@ msg(PariOUT *out, const char *s)
 int
 whatnow(PariOUT *out, const char *s, int flag)
 {
-  int n;
   const char *def;
-  whatnow_t wp;
+  const whatnow_t *wp = whatnowlist;
   entree *ep;
 
-  if (flag && s[0] && !s[1]) return 0; /* special case "i" and "o" */
-  n = 0;
-  do
-    def = (oldfonctions[n++]).name;
-  while (def && strcmp(def,s));
-  if (!def)
-  {
-    int m = 0;
-    do
-      def = (functions_oldgp[m++]).name;
-    while (def && strcmp(def,s));
-    n += m - 1;
-  }
+  while (wp->old && strcmp(wp->old,s)) wp++;
   /* Above linear search is slow, esp. if the symbol is not found. BUT no
    * point in wasting time by preallocating [ or autoloading ] a hashtable:
    * whatnow() is never used in a case where speed would be necessary */
-  if (!def)
+  if (!wp->old)
   {
     if (!flag)
       msg(out, "As far as I can recall, this function never existed");
     return 0;
   }
-
-  wp = whatnowlist[n-1]; def = wp.name;
+  def = wp->name;
   if (def == SAME)
   {
     if (!flag)
@@ -80,23 +55,22 @@ whatnow(PariOUT *out, const char *s, int flag)
   if (flag)
   {
     out_term_color(out, c_NONE);
-    out_print_text(out, "\nA function with that name existed in GP-1.39.15; to run in backward compatibility mode, type \"default(compatible,3)\", or set \"compatible = 3\" in your GPRC file.");
+    out_print_text(out, "\nA function with that name existed in GP-1.39.15. Please update your script.");
     out_putc(out, '\n');
   }
 
   if (def == REMOV)
   {
-    msg(out, "This function was suppressed");
+    msg(out, "This function no longer exists");
     return 0;
   }
-  if (!strcmp(def,"x*y")) ep = NULL;
-  else {
-    ep = is_entry(wp.name);
-    if (!ep) pari_err_BUG("whatnow");
-  }
+  /* special case compimag -> x*y */
+  if (!strcmp(def,"x*y")) def = "_*_";
+  ep = is_entry(def);
+  if (!ep) pari_err_BUG("whatnow");
   out_puts(out, "New syntax: ");
   out_term_color(out, c_ERR);
-  out_printf(out, "%s%s ===> %s%s\n\n", s, wp.oldarg, wp.name, wp.newarg);
-  if (ep) msg(out, ep->help);
+  out_printf(out, "%s%s ===> %s%s\n\n", s, wp->oldarg, wp->name, wp->newarg);
+  msg(out, ep->help);
   out_term_color(out, c_NONE); return 1;
 }
diff --git a/src/gp/whatnow.h b/src/gp/whatnow.h
index ecc347c..b51f238 100644
--- a/src/gp/whatnow.h
+++ b/src/gp/whatnow.h
@@ -1,657 +1,666 @@
-/* generated by the perl script 'whatnow' */
-static const whatnow_t whatnowlist[]={
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-{"elladd","(e,z1,z2)","(e,z1,z2)"},
-_SAME,
-{"matadjoint","(x)","(x)"},
-_SAME,
-{"ellak","(e,n)","(e,n)"},
-_SAME,
-{"algdep","(x,n,dec)","(x,n,dec)"},
-{"nfalgtobasis","(nf,x)","(nf,x)"},
-{"ellan","(e,n)","(e,n)"},
-{"ellap","(e,n)","(e,n)"},
-{"ellap","(e,n)","(e,n)"},
-{"padicappr","(x,a)","(x,a)"},
-_SAME,
-_SAME,
-_SAME,
-{"matcompanion","(x)","(x)"},
-_SAME,
-_SAME,
-{"nfbasis","(x)","(x)"},
-{"nfbasis","(x)","(x,2)"},
-{"nfbasistoalg","(nf,x)","(nf,x)"},
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-{"ellbil","(e,z1,z2)","(e,z1,z2)"},
-{"binomial","(x,y)","(x,y)"},
-_SAME,
-_SAME,
-{"contfrac","(x,lmax)","(x,,lmax)"},
-{"factor","(x,lim)","(x,lim)"},
-{"bnfcertify","(bnf)","(bnf)"},
-_REMOV,
-_REMOV,
-_REMOV,
-_REMOV,
-{"quadclassunit","(D,c1,c2,g)","(D,,[c1,c2,g])"},
-{"bnfinit","(P)","(P,2)"},
-{"bnfinit","(P)","(P,1)"},
-{"bnfinit","(P)","(P)"},
-{"bnfnarrow","(bnf)","(bnf)"},
-{"bnrinit","(bnf,ideal)","(bnf,ideal)"},
-{"bnrinit","(bnf,ideal)","(bnf,ideal)"},
-{"bnrinit","(bnf,ideal)","(bnf,ideal,1)"},
-{"quadclassunit","(D)","(D)"},
-{"sizebyte","(x)","(x)"},
-_SAME,
-_SAME,
-{"contfrac","(x)","(x)"},
-{"contfrac","(b,x)","(x,b)"},
-_REMOV,
-{"charpoly","(x,y)","(x,y)"},
-{"charpoly","(x,y)","(x,y,1)"},
-{"charpoly","(x,y)","(x,y,2)"},
-{"ellchangecurve","(x,y)","(x,y)"},
-_SAME,
-{"ellchangepoint","(x,y)","(x,y)"},
-{"qfbclassno","(x)","(x)"},
-{"qfbclassno","(x)","(x,1)"},
-{"polcoeff","(x,s)","(x,s)"},
-{"x*y","(x,y)",""},
-{"component","(x,s)","(x,s)"},
-{"polcompositum","(pol1,pol2)","(pol1,pol2)"},
-{"polcompositum","(pol1,pol2)","(pol1,pol2,1)"},
-{"qfbcompraw","(x,y)","(x,y)"},
-_SAME,
-{"bnrconductor","(a1)","(a1)"},
-{"bnrconductorofchar","(bnr,chi)","(bnr,chi)"},
-_SAME,
-_SAME,
-_SAME,
-{"serconvol","(x,y)","(x,y)"},
-_SAME,
-{"core","(x)","(x,1)"},
-_SAME,
-{"coredisc","(x)","(x,1)"},
-_SAME,
-_SAME,
-{"truncate","(x)","(x,&e)"},
-{"polcyclo","(n)","(n)"},
-{"factorback","(fa)","(fa)"},
-{"bnfdecodemodule","(nf,fa)","(nf,fa)"},
-{"poldegree","(x)","(x)"},
-{"denominator","(x)","(x)"},
-{"lindep","(x)","(x,-1)"},
-_SAME,
-{"matdet","(x)","(x)"},
-{"matdet","(x)","(x,1)"},
-{"matdetint","(x)","(x)"},
-{"matdiagonal","(x)","(x)"},
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-{"poldisc","(x)","(x)"},
-{"nfdisc","(x)","(x)"},
-{"nfdisc","(x)","(x,2)"},
-{"bnrdisc","(bnr,subgroup)","(bnr,subgroup)"},
-{"bnrdisc","(bnr)","(bnr,,,2)"},
-{"bnrdisclist","(bnf,list)","(bnf,list)"},
-{"bnrdisclist","(bnf,arch,bound)","(bnf,bound,arch)"},
-{"bnrdisclist","(bnf,bound)","(bnf,bound,,1)"},
-{"bnrdisclist","(bnf,bound)","(bnf,bound)"},
-{"bnrdisc","(bnr,subgroup)","(bnr,subgroup,,1)"},
-{"bnrdisc","(bnr,subgroup)","(bnr,subgroup,,3)"},
-_SAME,
-{"divrem","(x,y)","(x,y)"},
-{"sumdiv","(n,X,expr)","(n,X,expr)"},
-{"mateigen","(x)","(x)"},
-_SAME,
-_SAME,
-_SAME,
-{"Euler","",""},
-_SAME,
-_SAME,
-{"vecextract","(x,y)","(x,y)"},
-{"factorial","(x)","(x)"},
-{"factorcantor","(x,p)","(x,p)"},
-{"factorff","(x,p,a)","(x,p,a)"},
-{"factormod","(x,p)","(x,p)"},
-_SAME,
-{"nfbasis","(x,p)","(x,,p)"},
-{"nfdisc","(x,p)","(x,,p)"},
-{"polred","(x,p)","(x,,p)"},
-{"polred","(x,p)","(x,2,p)"},
-_SAME,
-_SAME,
-{"factorpadic","(x,p,r)","(x,p,r,1)"},
-{"factor","(x,l,hint)","(x)"},
-{"factor","(x,l,hint)","(x)"},
-{"fibonacci","(x)","(x)"},
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-{"ffinit","(p,n)","(p,n)"},
-_SAME,
-{"polgalois","(x)","(x)"},
-{"nfgaloisapply","(nf,aut,x)","(nf,aut,x)"},
-{"nfgaloisconj","(nf)","(nf)"},
-{"nfgaloisconj","(nf)","(nf,2)"},
-{"nfgaloisconj","","(nf,1)"},
-{"gammah","(x)","(x)"},
-_SAME,
-{"matsolve","(a,b)","(a,b)"},
-{"matsolvemod","(M,D,Y)","(M,D,Y)"},
-{"matsolvemod","(M,D,Y)","(M,D,Y,1)"},
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-{"ellglobalred","(x,y)","(x,y)"},
-_REMOV,
-{"qfbhclassno","(x)","(x)"},
-{"ellheight","(e,x)","(e,x)"},
-{"ellheight","(e,x)","(e,x,1)"},
-{"mathnf","(x)","(x)"},
-{"mathnf","(x)","(x,1)"},
-_REMOV,
-{"mathnfmod","(x,d)","(x,d)"},
-{"mathnfmodid","(x,d)","(x,d)"},
-{"mathnf","(x)","(x,3)"},
-{"mathess","(x)","(x)"},
-{"hilbert","(x,y)","(x,y)"},
-{"mathilbert","(n)","(n)"},
-{"hilbert","(x,y,p)","(x,y,p)"},
-{"vector","(n,X,expr)","(n,X,expr)"},
-_SAME,
-{"I","",""},
-_SAME,
-{"idealaddtoone","(nf,list)","(nf,list)"},
-{"idealaddtoone","(nf,x,y)","(nf,x,y)"},
-_SAME,
-{"idealappr","(nf,x)","(nf,x,1)"},
-_SAME,
-_SAME,
-_SAME,
-{"idealdiv","(nf,x,y)","(nf,x,y,1)"},
-_SAME,
-{"idealhnf","(nf,x)","(nf,x)"},
-{"idealhnf","(nf,x)","(nf,x)"},
-_SAME,
-_SAME,
-{"idealinv","(nf,x)","(nf,x,1)"},
-_SAME,
-_SAME,
-{"ideallistarch","(nf,list,arch)","(nf,list,arch)"},
-{"ideallist","(nf,list)","(nf,list,2)"},
-{"ideallistarch","","(nf,list,arch)"},
-{"ideallistarch","","(nf,list,arch)"},
-{"ideallist","","(nf,list,3)"},
-{"ideallist","(nf,bound)","(nf,bound)"},
-{"ideallist","(nf,bound)","(nf,bound,1)"},
-{"idealred","(nf,x,vdir)","(nf,x,vdir)"},
-_SAME,
-{"idealmul","(nf,x,y)","(nf,x,y,1)"},
-_SAME,
-_SAME,
-{"idealpow","(nf,x,y)","(nf,x,y,1)"},
-_SAME,
-{"idealtwoelt","(nf,x,a)","(nf,x,a)"},
-_SAME,
-{"matid","(n)","(n)"},
-_SAME,
-_SAME,
-{"matimage","(x)","(x)"},
-{"matimage","(x)","(x,1)"},
-{"matimagecompl","(x)","(x)"},
-_SAME,
-_REMOV,
-_REMOV,
-_REMOV,
-{"incgam","(s,x,y)","(s,x,y)"},
-{"matindexrank","(x)","(x)"},
-{"vecsort","(x)","(x,,1)"},
-{"nfinit","(pol)","(pol)"},
-{"nfinit","(x)","(x,2)"},
-{"nfinit","(x)","(x,3)"},
-{"ellinit","(x)","(x)"},
-{"zetakinit","(x)","(x)"},
-{"intformal","(x,y)","(x,y)"},
-{"matintersect","(x,y)","(x,y)"},
-{"intnum","(x=a,b,s)","(x=a,b,s,1)"},
-{"intnum","(x=a,b,s)","(x=a,b,s,2)"},
-_SAME,
-{"intnum","(x=a,b,s)","(x=a,b,s,3)"},
-{"matinverseimage","(x,y)","(x,y)"},
-{"matisdiagonal","(x)","(x)"},
-{"isfundamental","(x)","(x)"},
-{"nfisideal","(nf,x)","(nf,x)"},
-{"nfisincl","(x,y)","(x,y)"},
-{"nfisincl","(nf1,nf2)","(nf1,nf2,1)"},
-{"polisirreducible","(x)","(x)"},
-{"nfisisom","(x,y)","(x,y)"},
-{"nfisisom","(x,y)","(x,y)"},
-{"ellisoncurve","(e,x)","(e,x)"},
-_SAME,
-{"bnfisprincipal","(bnf,x)","(bnf,x,0)"},
-{"bnfisprincipal","(bnf,x)","(bnf,x,2)"},
-{"bnfisprincipal","(bnf,x)","(bnf,x)"},
-{"bnfisprincipal","(bnf,x)","(bnf,x,3)"},
-{"bnrisprincipal","(bnf,x)","(bnf,x)"},
-_SAME,
-{"ispseudoprime","(x)","(x)"},
-{"sqrtint","(x)","(x)"},
-{"setisset","(x)","(x)"},
-{"issquarefree","(x)","(x)"},
-_SAME,
-{"bnfisunit","(bnf,x)","(bnf,x)"},
-{"qfjacobi","(x)","(x)"},
-{"besseljh","(n,x)","(n,x)"},
-{"ellj","(x)","(x)"},
-_REMOV,
-{"besselk","(nu,x)","(nu,x)"},
-{"besselk","(nu,x)","(nu,x)"},
-{"matker","(x)","(x)"},
-{"matker","(x)","(x,1)"},
-{"matkerint","(x)","(x)"},
-{"matkerint","(x)","(x,1)"},
-_REMOV,
-{"kronecker","(x,y)","(x,y)"},
-_REMOV,
-{"zetak","(nfz,s)","(nfz,s,1)"},
-{"serlaplace","(x)","(x)"},
-_SAME,
-{"pollegendre","(n)","(n)"},
-_SAME,
-_SAME,
-{"vecsort","(x)","(x,,2)"},
-_SAME,
-_SAME,
-{"lindep","(x)","(x,1)"},
-{"qflll","(x)","(x)"},
-_REMOV,
-{"qflll","(x)","(x,8)"},
-{"qflllgram","(x)","(x)"},
-_REMOV,
-{"qflllgram","(x)","(x,8)"},
-{"qflllgram","(x)","(x,1)"},
-{"qflllgram","(x)","(x,4)"},
-{"qflllgram","(x)","(x,5)"},
-{"qflll","(x)","(x,1)"},
-{"qflll","(x)","(x,2)"},
-{"qflll","(x)","(x,4)"},
-{"qflll","(x)","(x,5)"},
-_REMOV,
-{"log","(x)","(x)"},
-_SAME,
-{"elllocalred","(e)","(e)"},
-_SAME,
-{"log","(x)","(x,1)"},
-{"elllseries","(e,s,N,A)","(e,s,A)"},
-{"bnfinit","(sbnf)","(sbnf)"},
-{"Mat","(x)","(x)"},
-{"vecextract","(x,y,z)","(x,y,z)"},
-{"ellheightmatrix","(e,x)","(e,x)"},
-_SAME,
-_SAME,
-{"matrixqz","(x,p)","(x,-1)"},
-{"matrixqz","(x,p)","(x,-2)"},
-_SAME,
-_SAME,
-_SAME,
-{"idealmin","(nf,ix,vdir)","(nf,ix,vdir)"},
-{"qfminim","(x,bound,maxnum)","(x,bound,maxnum)"},
-{"qfminim","(x,bound)","(x,bound,,1)"},
-{"Mod","(x,y)","(x,y)"},
-{"Mod","(x,y,p)","(x,y)"},
-_SAME,
-{"gcd","(x,y)","(x,y,1)"},
-{"moebius","(n)","(n)"},
-_SAME,
-_SAME,
-_SAME,
-{"nfeltdiv","(nf,a,b)","(nf,a,b)"},
-{"nfeltdiveuc","(nf,a,b)","(nf,a,b)"},
-{"nfeltdivrem","(nf,a,b)","(nf,a,b)"},
-{"nfhnf","(nf,x)","(nf,x)"},
-{"nfhnfmod","(nf,x,detx)","(nf,x,detx)"},
-{"nfeltmod","(nf,a,b)","(nf,a,b)"},
-{"nfeltmul","(nf,a,b)","(nf,a,b)"},
-{"nfeltpow","(nf,a,k)","(nf,a,k)"},
-{"nfeltreduce","(nf,a,id)","(nf,a,id)"},
-{"nfsnf","(nf,x)","(nf,x)"},
-{"nfeltval","(nf,a,pr)","(nf,a,pr)"},
-_SAME,
-_SAME,
-{"qfbnucomp","(x,y,l)","(x,y,l)"},
-_SAME,
-{"numerator","(x)","(x)"},
-{"qfbnupow","(x,n)","(x,n)"},
-{"O","(x)","(x)"},
-_SAME,
-{"ellordinate","(e,x)","(e,x)"},
-{"znorder","(x)","(x)"},
-{"ellorder","(e,x)","(e,x)"},
-{"polredord","(x)","(x)"},
-_SAME,
-{"matpascal","(n)","(n)"},
-{"qfperfection","(a)","(a)"},
-{"numtoperm","(n,k)","(n,k)"},
-{"permtonum","(vect)","(vect)"},
-{"qfbprimeform","(x,p)","(x,p)"},
-{"eulerphi","(x)","(x)"},
-{"Pi","",""},
-{"contfracpnqn","(x)","(x)"},
-{"ellztopoint","(e,z)","(e,z)"},
-{"polinterpolate","(xa,ya,x)","(xa,ya,p)"},
-_SAME,
-{"polred","(x)","(x,2)"},
-_SAME,
-{"polredabs","(x)","(x,1)"},
-{"polredabs","(x)","(x,4)"},
-{"polredabs","(x)","(x,8)"},
-{"polredabs","(x)","(x,2)"},
-_SAME,
-{"variable","(x)","(x)"},
-{"Pol","(x,v)","(x,v)"},
-_SAME,
-{"polylog","(m,x)","(m,x,1)"},
-{"polylog","(m,x)","(m,x,2)"},
-{"polylog","(m,x)","(m,x,3)"},
-{"Polrev","(x,v)","(x,v)"},
-{"polzagier","(n,m)","(n,m)"},
-{"ellmul","(e,x,n)","(e,x,n)"},
-{"qfbpowraw","(x,n)","(x,n)"},
-{"precision","(x,n)","(x,n)"},
-_SAME,
-_SAME,
-{"idealprimedec","(nf,p)","(nf,p)"},
-_SAME,
-{"znprimroot","(n)","(n)"},
-_REMOV,
-_REMOV,
-{"prod","(x,X=a,b,expr)","(X=a,b,expr,x)"},
-_SAME,
-_SAME,
-{"prodinf","(X=a,expr)","(X=a,expr,1)"},
-_SAME,
-{"Qfb","(a,b,c)","(a,b,c)"},
-{"Qfb","(a,b,c,d)","(a,b,c,d)"},
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-{"matrank","(x)","(x)"},
-{"bnrclassno","(bnf,x)","(bnf,x)"},
-{"bnrclassnolist","(bnf,liste)","(bnf,liste)"},
-_SAME,
-{"polrecip","(x)","(x)"},
-{"qfbred","(x)","(x)"},
-{"qfbred","(x)","(x)"},
-{"qfbred","(x,d)","(x,2,,d)"},
-{"poldiscreduced","(f)","(f)"},
-{"quadregulator","(x)","(x)"},
-_REMOV,
-{"polresultant","(x,y)","(x,y)"},
-{"polresultant","(x,y)","(x,y,1)"},
-{"serreverse","(x)","(x)"},
-{"qfbred","(x)","(x,1)"},
-{"qfbred","(x,d)","(x,3,,d)"},
-{"round","(x)","(x,&e)"},
-_SAME,
-{"rnfdisc","(nf,pol)","(nf,pol)"},
-_SAME,
-{"rnfequation","(nf,pol)","(nf,pol,1)"},
-{"rnfhnfbasis","(bnf,order)","(bnf,order)"},
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-{"polrootsmod","(x,p)","(x,p)"},
-{"polrootsmod","(x,p)","(x,p,1)"},
-{"polrootspadic","(x,p,r)","(x,p,r)"},
-{"polroots","(x)","(x)"},
-{"nfrootsof1","(nf)","(nf)"},
-_REMOV,
-_SAME,
-{"round","(x)","(x,&e)"},
-{"Ser","(x,v)","(x,v)"},
-{"Set","(x)","(x)"},
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-{"sigma","(k,x)","(x,k)"},
-_SAME,
-{"qfsign","(x)","(x)"},
-{"bnfsignunit","(bnf)","(bnf)"},
-{"factormod","(x,p)","(x,p,1)"},
-_SAME,
-_SAME,
-_SAME,
-{"sizedigit","(x)","(x)"},
-{"nfbasis","(x)","(x,1)"},
-{"bnfcompress","(x)","(x)"},
-{"nfdisc","(x)","(x,1)"},
-{"factor","(x)","(x,0)"},
-{"ellinit","(x)","(x,1)"},
-{"polred","(x)","(x,1)"},
-{"polred","(x)","(x,3)"},
-{"matsnf","(x)","(x)"},
-{"matsnf","(x)","(x,1)"},
-{"matsnf","(x)","(x,4)"},
-{"matsnf","(x)","(x,2)"},
-_SAME,
-{"vecsort","(x)","(x)"},
-_SAME,
-{"qfgaussred","(x)","(x)"},
-_SAME,
-{"gcd","(x,y)","(x,y,2)"},
-{"polsturm","(x)","(x)"},
-{"polsturm","(x,a,b)","(x,a,b)"},
-{"polsubcyclo","(p,d)","(p,d)"},
-{"ellsub","(e,a,b)","(e,a,b)"},
-_SAME,
-{"sum","(x,X=a,b,expr)","(X=a,b,expr,x)"},
-_SAME,
-{"sumalt","(X=a,expr)","(X=a,expr,1)"},
-_SAME,
-_SAME,
-{"sumpos","(X=a,expr)","(X=a,expr,1)"},
-{"matsupplement","(x)","(x)"},
-{"polsylvestermatrix","(x,y)","(x,y)"},
-_SAME,
-_SAME,
-{"elltaniyama","(e)","(e)"},
-_SAME,
-{"polchebyshev","(n)","(n)"},
-{"teichmuller","(x)","(x)"},
-_SAME,
-_SAME,
-_REMOV,
-_REMOV,
-{"elltors","(e)","(e)"},
-_SAME,
-{"mattranspose","(x)","(x)"},
-{"truncate","(x)","(x)"},
-{"poltschirnhaus","(x)","(x)"},
-_REMOV,
-{"quadunit","(x)","(x)"},
-_SAME,
-_SAME,
-{"Vec","(x)","(x)"},
-{"vecsort","(x)","(x,,1)"},
-{"vecsort","(x)","(x,,2)"},
-_SAME,
-_SAME,
-_SAME,
-_SAME,
-{"vectorv","(n,X,expr)","(n,X,expr)"},
-{"ellwp","(e)","(e)"},
-{"weber","(x)","(x)"},
-{"weber","(x)","(x,2)"},
-_SAME,
-{"ellpointtoz","(e,P)","(e,P)"},
-_SAME,
-_SAME,
-{"ideallog","(nf,x,bid)","(nf,x,bid)"},
-{"idealstar","(nf,I)","(nf,I)"},
-{"idealstar","(nf,id)","(nf,id,1)"},
-{"idealstar","(nf,id)","(nf,id,2)"},
-_SAME,
+typedef struct whatnow_t
+{
+  const char *old,  *name, *oldarg, *newarg;
+} whatnow_t;
+
+#define SAME NULL
+#define REMOV (char *)1L
 
-_SAME,
-{"plotbox","(x,a)","(x,a)"},
-{"plotcolor","(w,c)","(w,c)"},
-{"plotcursor","(w)","(w)"},
-_SAME,
-{"plotdraw","(list)","(list)"},
-{"plotinit","(w,x,y)","(w,x,y)"},
-_SAME,
-{"plotkill","(w)","(w)"},
-{"plotlines","(w,x2,y2)","(w,x2,y2)"},
-{"plotlines","(w,x2,y2)","(w,x2,y2)"},
-{"plotmove","(w,x,y)","(w,x,y)"},
-_SAME,
-_SAME,
-{"ploth","(X=a,b,expr)","(X=a,b,expr,1)"},
-{"ploth","(X=a,b,expr)","(X=a,b,expr)"},
-_SAME,
-{"plotpoints","(w,x,y)","(w,x,y)"},
-{"plotpoints","(w,x,y)","(w,x,y)"},
-{"psdraw","(list)","(list)"},
-{"psploth","(X=a,b,expr)","(X=a,b,expr)"},
-{"psploth","(X=a,b,expr)","(X=a,b,expr,1)"},
-{"psplothraw","(listx,listy)","(listx,listy)"},
-_REMOV,
-_REMOV,
-_SAME,
-_SAME,
-{"plotrbox","(w,dx,dy)","(w,dx,dy)"},
-{"input","(x)","(x)"},
-{"plotrline","(w,dx,dy)","(w,dx,dy)"},
-{"plotrlines","(w,dx,dy)","(w,dx,dy,1)"},
-{"plotrmove","(w,dx,dy)","(w,dx,dy)"},
-{"plotrpoint","(w,dx,dy)","(w,dx,dy)"},
-{"plotrpoints","(w,dx,dy)","(w,dx,dy)"},
-{"plotscale","(w,x1,x2,y1,y2)","(w,x1,x2,y1,y2)"},
-{"default","(n)","(realprecision,n)"},
-{"default","(n)","(seriesprecision,n)"},
-{"type","(x,t)","(x,t)"},
-{"plotstring","(w,x)","(w,x)"},
-_SAME,
-{"printtex","(x)","(x)"},
-_SAME
+#define _REMOV REMOV,NULL,NULL
+#define _SAME  SAME,NULL,NULL
+static const whatnow_t whatnowlist[]={
+{"!_",_SAME},
+{"#_",_SAME},
+{"%",_SAME},
+{"+_",_SAME},
+{"-_",_SAME},
+{"_!",_SAME},
+{"_!=_",_SAME},
+{"_%=_",_SAME},
+{"_%_",_SAME},
+{"_&&_",_SAME},
+{"_'",_SAME},
+{"_*=_",_SAME},
+{"_*_",_SAME},
+{"_++",_SAME},
+{"_+=_",_SAME},
+{"_+_",_SAME},
+{"_--",_SAME},
+{"_-=_",_SAME},
+{"_-_",_SAME},
+{"_.a1",_SAME},
+{"_.a2",_SAME},
+{"_.a3",_SAME},
+{"_.a4",_SAME},
+{"_.a6",_SAME},
+{"_.area",_SAME},
+{"_.b2",_SAME},
+{"_.b4",_SAME},
+{"_.b6",_SAME},
+{"_.b8",_SAME},
+{"_.bid",_SAME},
+{"_.bnf",_SAME},
+{"_.c4",_SAME},
+{"_.c6",_SAME},
+{"_.clgp",_SAME},
+{"_.codiff",_SAME},
+{"_.cyc",_SAME},
+{"_.diff",_SAME},
+{"_.disc",_SAME},
+{"_.e",_SAME},
+{"_.eta",_SAME},
+{"_.f",_SAME},
+{"_.fu",_SAME},
+{"_.futu",_SAME},
+{"_.gen",_SAME},
+{"_.group",_SAME},
+{"_.index",_SAME},
+{"_.j",_SAME},
+{"_.mod",_SAME},
+{"_.nf",_SAME},
+{"_.no",_SAME},
+{"_.omega",_SAME},
+{"_.orders",_SAME},
+{"_.p",_SAME},
+{"_.pol",_SAME},
+{"_.r1",_SAME},
+{"_.r2",_SAME},
+{"_.reg",_SAME},
+{"_.roots",_SAME},
+{"_.sign",_SAME},
+{"_.t2",_SAME},
+{"_.tate",_SAME},
+{"_.tu",_SAME},
+{"_.tufu",_SAME},
+{"_.zk",_SAME},
+{"_.zkst",_SAME},
+{"_/=_",_SAME},
+{"_/_",_SAME},
+{"_<<=_",_SAME},
+{"_<<_",_SAME},
+{"_<=_",_SAME},
+{"_<_",_SAME},
+{"_==_",_SAME},
+{"_>=_",_SAME},
+{"_>>=_",_SAME},
+{"_>>_",_SAME},
+{"_>_",_SAME},
+{"_[_.._,_.._]",_SAME},
+{"_[_.._]",_SAME},
+{"_\\/=_",_SAME},
+{"_\\/_",_SAME},
+{"_\\=_",_SAME},
+{"_\\_",_SAME},
+{"_^_",_SAME},
+{"_^s",_SAME},
+{"__",_SAME},
+{"_derivfun",_SAME},
+{"_eval_mnemonic",_SAME},
+{"_multi_if",_SAME},
+{"_void_if",_SAME},
+{"_||_",_SAME},
+{"_~",_SAME},
+{"O",_SAME},
+{"O(_^_)",_SAME},
+{"Str",_SAME},
+{"abs",_SAME},
+{"acos",_SAME},
+{"acosh",_SAME},
+{"addell","elladd","(e,z1,z2)","(e,z1,z2)"},
+{"addprimes",_SAME},
+{"adj","matadjoint","(x)","(x)"},
+{"agm",_SAME},
+{"akell","ellak","(e,n)","(e,n)"},
+{"algdep",_SAME},
+{"algdep2","algdep","(x,n,dec)","(x,n,dec)"},
+{"algtobasis","nfalgtobasis","(nf,x)","(nf,x)"},
+{"anell","ellan","(e,n)","(e,n)"},
+{"apell","ellap","(e,n)","(e,n)"},
+{"apell2","ellap","(e,n)","(e,n)"},
+{"apprpadic","padicappr","(x,a)","(x,a)"},
+{"arg",_SAME},
+{"asin",_SAME},
+{"asinh",_SAME},
+{"assmat","matcompanion","(x)","(x)"},
+{"atan",_SAME},
+{"atanh",_SAME},
+{"basis","nfbasis","(x)","(x)"},
+{"basis2","nfbasis","(x)","(x,2)"},
+{"basistoalg","nfbasistoalg","(nf,x)","(nf,x)"},
+{"bernreal",_SAME},
+{"bernvec",_SAME},
+{"bestappr",_SAME},
+{"bezout",_SAME},
+{"bezoutres",_SAME},
+{"bigomega",_SAME},
+{"bilhell","ellbil","(e,z1,z2)","(e,z1,z2)"},
+{"bin","binomial","(x,y)","(x,y)"},
+{"binary",_SAME},
+{"bittest",_SAME},
+{"boundcf","contfrac","(x,lmax)","(x,,lmax)"},
+{"boundfact","factor","(x,lim)","(x,lim)"},
+{"buchcertify","bnfcertify","(bnf)","(bnf)"},
+{"buchfu",_REMOV},
+{"buchgen",_REMOV},
+{"buchgenforcefu",_REMOV},
+{"buchgenfu",_REMOV},
+{"buchimag","quadclassunit","(D,c1,c2,g)","(D,,[c1,c2,g])"},
+{"buchinit","bnfinit","(P)","(P,2)"},
+{"buchinitforcefu","bnfinit","(P)","(P,1)"},
+{"buchinitfu","bnfinit","(P)","(P)"},
+{"buchnarrow","bnfnarrow","(bnf)","(bnf)"},
+{"buchray","bnrinit","(bnf,ideal)","(bnf,ideal)"},
+{"buchrayinit","bnrinit","(bnf,ideal)","(bnf,ideal)"},
+{"buchrayinitgen","bnrinit","(bnf,ideal)","(bnf,ideal,1)"},
+{"buchreal","quadclassunit","(D)","(D)"},
+{"bytesize","sizebyte","(x)","(x)"},
+{"ceil",_SAME},
+{"centerlift",_SAME},
+{"cf","contfrac","(x)","(x)"},
+{"cf2","contfrac","(b,x)","(x,b)"},
+{"changevar",_REMOV},
+{"char","charpoly","(x,y)","(x,y)"},
+{"char1","charpoly","(x,y)","(x,y,1)"},
+{"char2","charpoly","(x,y)","(x,y,2)"},
+{"chell","ellchangecurve","(x,y)","(x,y)"},
+{"chinese",_SAME},
+{"chptell","ellchangepoint","(x,y)","(x,y)"},
+{"classno","qfbclassno","(x)","(x)"},
+{"classno2","qfbclassno","(x)","(x,1)"},
+{"coeff","polcoeff","(x,s)","(x,s)"},
+{"compimag","x*y","(x,y)",""},
+{"compo","component","(x,s)","(x,s)"},
+{"compositum","polcompositum","(pol1,pol2)","(pol1,pol2)"},
+{"compositum2","polcompositum","(pol1,pol2)","(pol1,pol2,1)"},
+{"comprealraw","qfbcompraw","(x,y)","(x,y)"},
+{"concat",_SAME},
+{"conductor","bnrconductor","(a1)","(a1)"},
+{"conductorofchar","bnrconductorofchar","(bnr,chi)","(bnr,chi)"},
+{"conj",_SAME},
+{"conjvec",_SAME},
+{"content",_SAME},
+{"convol","serconvol","(x,y)","(x,y)"},
+{"core",_SAME},
+{"core2","core","(x)","(x,1)"},
+{"coredisc",_SAME},
+{"coredisc2","coredisc","(x)","(x,1)"},
+{"cos",_SAME},
+{"cosh",_SAME},
+{"cvtoi","truncate","(x)","(x,&e)"},
+{"cyclo","polcyclo","(n)","(n)"},
+{"decodefactor","factorback","(fa)","(fa)"},
+{"decodemodule","bnfdecodemodule","(nf,fa)","(nf,fa)"},
+{"degree","poldegree","(x)","(x)"},
+{"denom","denominator","(x)","(x)"},
+{"deplin","lindep","(x)","(x,-1)"},
+{"deriv",_SAME},
+{"det","matdet","(x)","(x)"},
+{"det2","matdet","(x)","(x,1)"},
+{"detint","matdetint","(x)","(x)"},
+{"diagonal","matdiagonal","(x)","(x)"},
+{"dilog",_SAME},
+{"dirdiv",_SAME},
+{"direuler",_SAME},
+{"dirmul",_SAME},
+{"dirzetak",_SAME},
+{"disc","poldisc","(x)","(x)"},
+{"discf","nfdisc","(x)","(x)"},
+{"discf2","nfdisc","(x)","(x,2)"},
+{"discrayabs","bnrdisc","(bnr,subgroup)","(bnr,subgroup)"},
+{"discrayabscond","bnrdisc","(bnr)","(bnr,,,2)"},
+{"discrayabslist","bnrdisclist","(bnf,list)","(bnf,list)"},
+{"discrayabslistarch","bnrdisclist","(bnf,arch,bound)","(bnf,bound,arch)"},
+{"discrayabslistarchall","bnrdisclist","(bnf,bound)","(bnf,bound,,1)"},
+{"discrayabslistlong","bnrdisclist","(bnf,bound)","(bnf,bound)"},
+{"discrayrel","bnrdisc","(bnr,subgroup)","(bnr,subgroup,,1)"},
+{"discrayrelcond","bnrdisc","(bnr,subgroup)","(bnr,subgroup,,3)"},
+{"divisors",_SAME},
+{"divres","divrem","(x,y)","(x,y)"},
+{"divsum","sumdiv","(n,X,expr)","(n,X,expr)"},
+{"eigen","mateigen","(x)","(x)"},
+{"eint1",_SAME},
+{"erfc",_SAME},
+{"eta",_SAME},
+{"euler","Euler","",""},
+{"eval",_SAME},
+{"exp",_SAME},
+{"extract","vecextract","(x,y)","(x,y)"},
+{"fact","factorial","(x)","(x)"},
+{"factcantor","factorcantor","(x,p)","(x,p)"},
+{"factfq","factorff","(x,p,a)","(x,p,a)"},
+{"factmod","factormod","(x,p)","(x,p)"},
+{"factor",_SAME},
+{"factoredbasis","nfbasis","(x,p)","(x,,p)"},
+{"factoreddiscf","nfdisc","(x,p)","(x,,p)"},
+{"factoredpolred","polred","(x,p)","(x,,p)"},
+{"factoredpolred2","polred","(x,p)","(x,2,p)"},
+{"factornf",_SAME},
+{"factorpadic",_SAME},
+{"factorpadic2","factorpadic","(x,p,r)","(x,p,r,1)"},
+{"factpol","factor","(x,l,hint)","(x)"},
+{"factpol2","factor","(x,l,hint)","(x)"},
+{"fibo","fibonacci","(x)","(x)"},
+{"floor",_SAME},
+{"for",_SAME},
+{"fordiv",_SAME},
+{"forprime",_SAME},
+{"forstep",_SAME},
+{"forvec",_SAME},
+{"fpn","ffinit","(p,n)","(p,n)"},
+{"frac",_SAME},
+{"galois","polgalois","(x)","(x)"},
+{"galoisapply","nfgaloisapply","(nf,aut,x)","(nf,aut,x)"},
+{"galoisconj","nfgaloisconj","(nf)","(nf)"},
+{"galoisconj1","nfgaloisconj","(nf)","(nf,2)"},
+{"galoisconjforce","nfgaloisconj","","(nf,1)"},
+{"gamh","gammah","(x)","(x)"},
+{"gamma",_SAME},
+{"gauss","matsolve","(a,b)","(a,b)"},
+{"gaussmodulo","matsolvemod","(M,D,Y)","(M,D,Y)"},
+{"gaussmodulo2","matsolvemod","(M,D,Y)","(M,D,Y,1)"},
+{"gcd",_SAME},
+{"getheap",_SAME},
+{"getrand",_SAME},
+{"getstack",_SAME},
+{"gettime",_SAME},
+{"globalred","ellglobalred","(x,y)","(x,y)"},
+{"goto",_REMOV},
+{"hclassno","qfbhclassno","(x)","(x)"},
+{"hell","ellheight","(e,x)","(e,x)"},
+{"hell2","ellheight","(e,x)","(e,x,1)"},
+{"hermite","mathnf","(x)","(x)"},
+{"hermite2","mathnf","(x)","(x,1)"},
+{"hermitehavas",_REMOV},
+{"hermitemod","mathnfmod","(x,d)","(x,d)"},
+{"hermitemodid","mathnfmodid","(x,d)","(x,d)"},
+{"hermiteperm","mathnf","(x)","(x,3)"},
+{"hess","mathess","(x)","(x)"},
+{"hilb","hilbert","(x,y)","(x,y)"},
+{"hilbert","mathilbert","(n)","(n)"},
+{"hilbp","hilbert","(x,y,p)","(x,y,p)"},
+{"hvector","vector","(n,X,expr)","(n,X,expr)"},
+{"hyperu",_SAME},
+{"i","I","",""},
+{"idealadd",_SAME},
+{"idealaddmultone","idealaddtoone","(nf,list)","(nf,list)"},
+{"idealaddone","idealaddtoone","(nf,x,y)","(nf,x,y)"},
+{"idealappr",_SAME},
+{"idealapprfact","idealappr","(nf,x)","(nf,x,1)"},
+{"idealchinese",_SAME},
+{"idealcoprime",_SAME},
+{"idealdiv",_SAME},
+{"idealdivexact","idealdiv","(nf,x,y)","(nf,x,y,1)"},
+{"idealfactor",_SAME},
+{"idealhermite","idealhnf","(nf,x)","(nf,x)"},
+{"idealhermite2","idealhnf","(nf,x)","(nf,x)"},
+{"idealintersect",_SAME},
+{"idealinv",_SAME},
+{"idealinv2","idealinv","(nf,x)","(nf,x,1)"},
+{"ideallist",_SAME},
+{"ideallistarch",_SAME},
+{"ideallistarchgen","ideallistarch","(nf,list,arch)","(nf,list,arch)"},
+{"ideallistunit","ideallist","(nf,list)","(nf,list,2)"},
+{"ideallistunitarch","ideallistarch","","(nf,list,arch)"},
+{"ideallistunitarchgen","ideallistarch","","(nf,list,arch)"},
+{"ideallistunitgen","ideallist","","(nf,list,3)"},
+{"ideallistzstar","ideallist","(nf,bound)","(nf,bound)"},
+{"ideallistzstargen","ideallist","(nf,bound)","(nf,bound,1)"},
+{"ideallllred","idealred","(nf,x,vdir)","(nf,x,vdir)"},
+{"idealmul",_SAME},
+{"idealmulred","idealmul","(nf,x,y)","(nf,x,y,1)"},
+{"idealnorm",_SAME},
+{"idealpow",_SAME},
+{"idealpowred","idealpow","(nf,x,y)","(nf,x,y,1)"},
+{"idealtwoelt",_SAME},
+{"idealtwoelt2","idealtwoelt","(nf,x,a)","(nf,x,a)"},
+{"idealval",_SAME},
+{"idmat","matid","(n)","(n)"},
+{"if",_SAME},
+{"imag",_SAME},
+{"image","matimage","(x)","(x)"},
+{"image2","matimage","(x)","(x,1)"},
+{"imagecompl","matimagecompl","(x)","(x)"},
+{"incgam",_SAME},
+{"incgam1",_REMOV},
+{"incgam2",_REMOV},
+{"incgam3",_REMOV},
+{"incgam4","incgam","(s,x,y)","(s,x,y)"},
+{"indexrank","matindexrank","(x)","(x)"},
+{"indsort","vecsort","(x)","(x,,1)"},
+{"initalg","nfinit","(pol)","(pol)"},
+{"initalgred","nfinit","(x)","(x,2)"},
+{"initalgred2","nfinit","(x)","(x,3)"},
+{"initell","ellinit","(x)","(x)"},
+{"initzeta","zetakinit","(x)","(x)"},
+{"integ","intformal","(x,y)","(x,y)"},
+{"intersect","matintersect","(x,y)","(x,y)"},
+{"intgen","intnum","(x=a,b,s)","(x=a,b,s,1)"},
+{"intinf","intnum","(x=a,b,s)","(x=a,b,s,2)"},
+{"intnum",_SAME},
+{"intopen","intnum","(x=a,b,s)","(x=a,b,s,3)"},
+{"inverseimage","matinverseimage","(x,y)","(x,y)"},
+{"isdiagonal","matisdiagonal","(x)","(x)"},
+{"isfund","isfundamental","(x)","(x)"},
+{"isideal","nfisideal","(nf,x)","(nf,x)"},
+{"isincl","nfisincl","(x,y)","(x,y)"},
+{"isinclfast","nfisincl","(nf1,nf2)","(nf1,nf2,1)"},
+{"isirreducible","polisirreducible","(x)","(x)"},
+{"isisom","nfisisom","(x,y)","(x,y)"},
+{"isisomfast","nfisisom","(x,y)","(x,y)"},
+{"isoncurve","ellisoncurve","(e,x)","(e,x)"},
+{"isprime",_SAME},
+{"isprincipal","bnfisprincipal","(bnf,x)","(bnf,x,0)"},
+{"isprincipalforce","bnfisprincipal","(bnf,x)","(bnf,x,2)"},
+{"isprincipalgen","bnfisprincipal","(bnf,x)","(bnf,x)"},
+{"isprincipalgenforce","bnfisprincipal","(bnf,x)","(bnf,x,3)"},
+{"isprincipalray","bnrisprincipal","(bnf,x)","(bnf,x)"},
+{"isprincipalraygen",_SAME},
+{"ispsp","ispseudoprime","(x)","(x)"},
+{"isqrt","sqrtint","(x)","(x)"},
+{"isset","setisset","(x)","(x)"},
+{"issqfree","issquarefree","(x)","(x)"},
+{"issquare",_SAME},
+{"isunit","bnfisunit","(bnf,x)","(bnf,x)"},
+{"jacobi","qfjacobi","(x)","(x)"},
+{"jbesselh","besseljh","(n,x)","(n,x)"},
+{"jell","ellj","(x)","(x)"},
+{"karamul",_REMOV},
+{"kbessel","besselk","(nu,x)","(nu,x)"},
+{"kbessel2","besselk","(nu,x)","(nu,x)"},
+{"ker","matker","(x)","(x)"},
+{"keri","matker","(x)","(x,1)"},
+{"kerint","matkerint","(x)","(x)"},
+{"kerint1","matkerint","(x)","(x,1)"},
+{"kerint2",_REMOV},
+{"kro","kronecker","(x,y)","(x,y)"},
+{"label",_REMOV},
+{"lambdak","zetak","(nfz,s)","(nfz,s,1)"},
+{"laplace","serlaplace","(x)","(x)"},
+{"lcm",_SAME},
+{"legendre","pollegendre","(n)","(n)"},
+{"length",_SAME},
+{"lex",_SAME},
+{"lexsort","vecsort","(x)","(x,,2)"},
+{"lift",_SAME},
+{"lindep",_SAME},
+{"lindep2","lindep","(x)","(x,1)"},
+{"lll","qflll","(x)","(x)"},
+{"lll1",_REMOV},
+{"lllgen","qflll","(x)","(x,8)"},
+{"lllgram","qflllgram","(x)","(x)"},
+{"lllgram1",_REMOV},
+{"lllgramgen","qflllgram","(x)","(x,8)"},
+{"lllgramint","qflllgram","(x)","(x,1)"},
+{"lllgramkerim","qflllgram","(x)","(x,4)"},
+{"lllgramkerimgen","qflllgram","(x)","(x,5)"},
+{"lllint","qflll","(x)","(x,1)"},
+{"lllintpartial","qflll","(x)","(x,2)"},
+{"lllkerim","qflll","(x)","(x,4)"},
+{"lllkerimgen","qflll","(x)","(x,5)"},
+{"lllrat",_REMOV},
+{"ln","log","(x)","(x)"},
+{"lngamma",_SAME},
+{"localred","elllocalred","(e)","(e)"},
+{"log",_SAME},
+{"logagm","log","(x)","(x,1)"},
+{"lseriesell","elllseries","(e,s,N,A)","(e,s,A)"},
+{"makebigbnf","bnfinit","(sbnf)","(sbnf)"},
+{"mat","Mat","(x)","(x)"},
+{"matextract","vecextract","(x,y,z)","(x,y,z)"},
+{"mathell","ellheightmatrix","(e,x)","(e,x)"},
+{"matrix",_SAME},
+{"matrixqz",_SAME},
+{"matrixqz2","matrixqz","(x,p)","(x,-1)"},
+{"matrixqz3","matrixqz","(x,p)","(x,-2)"},
+{"matsize",_SAME},
+{"max",_SAME},
+{"min",_SAME},
+{"minideal","idealmin","(nf,ix,vdir)","(nf,ix,vdir)"},
+{"minim","qfminim","(x,bound,maxnum)","(x,bound,maxnum)"},
+{"minim2","qfminim","(x,bound)","(x,bound,,1)"},
+{"mod","Mod","(x,y)","(x,y)"},
+{"modp","Mod","(x,y,p)","(x,y)"},
+{"modreverse",_SAME},
+{"modulargcd","gcd","(x,y)","(x,y,1)"},
+{"mu","moebius","(n)","(n)"},
+{"newtonpoly",_SAME},
+{"nextprime",_SAME},
+{"nfdetint",_SAME},
+{"nfdiv","nfeltdiv","(nf,a,b)","(nf,a,b)"},
+{"nfdiveuc","nfeltdiveuc","(nf,a,b)","(nf,a,b)"},
+{"nfdivres","nfeltdivrem","(nf,a,b)","(nf,a,b)"},
+{"nfhermite","nfhnf","(nf,x)","(nf,x)"},
+{"nfhermitemod","nfhnfmod","(nf,x,detx)","(nf,x,detx)"},
+{"nfmod","nfeltmod","(nf,a,b)","(nf,a,b)"},
+{"nfmul","nfeltmul","(nf,a,b)","(nf,a,b)"},
+{"nfpow","nfeltpow","(nf,a,k)","(nf,a,k)"},
+{"nfreduce","nfeltreduce","(nf,a,id)","(nf,a,id)"},
+{"nfsmith","nfsnf","(nf,x)","(nf,x)"},
+{"nfval","nfeltval","(nf,a,pr)","(nf,a,pr)"},
+{"norm",_SAME},
+{"norml2",_SAME},
+{"nucomp","qfbnucomp","(x,y,l)","(x,y,l)"},
+{"numdiv",_SAME},
+{"numer","numerator","(x)","(x)"},
+{"nupow","qfbnupow","(x,n)","(x,n)"},
+{"o","O","(x)","(x)"},
+{"omega",_SAME},
+{"ordell","ellordinate","(e,x)","(e,x)"},
+{"order","znorder","(x)","(x)"},
+{"orderell","ellorder","(e,x)","(e,x)"},
+{"ordred","polredord","(x)","(x)"},
+{"padicprec",_SAME},
+{"pascal","matpascal","(n)","(n)"},
+{"perf","qfperfection","(a)","(a)"},
+{"permutation","numtoperm","(n,k)","(n,k)"},
+{"permutation2num","permtonum","(vect)","(vect)"},
+{"pf","qfbprimeform","(x,p)","(x,p)"},
+{"phi","eulerphi","(x)","(x)"},
+{"pi","Pi","",""},
+{"pnqn","contfracpnqn","(x)","(x)"},
+{"pointell","ellztopoint","(e,z)","(e,z)"},
+{"polint","polinterpolate","(xa,ya,x)","(xa,ya,p)"},
+{"polred",_SAME},
+{"polred2","polred","(x)","(x,2)"},
+{"polredabs",_SAME},
+{"polredabs2","polredabs","(x)","(x,1)"},
+{"polredabsall","polredabs","(x)","(x,4)"},
+{"polredabsfast","polredabs","(x)","(x,8)"},
+{"polredabsnored","polredabs","(x)","(x,2)"},
+{"polsym",_SAME},
+{"polvar","variable","(x)","(x)"},
+{"poly","Pol","(x,v)","(x,v)"},
+{"polylog",_SAME},
+{"polylogd","polylog","(m,x)","(m,x,1)"},
+{"polylogdold","polylog","(m,x)","(m,x,2)"},
+{"polylogp","polylog","(m,x)","(m,x,3)"},
+{"polyrev","Polrev","(x,v)","(x,v)"},
+{"polzag","polzagier","(n,m)","(n,m)"},
+{"powell","ellmul","(e,x,n)","(e,x,n)"},
+{"powrealraw","qfbpowraw","(x,n)","(x,n)"},
+{"prec","precision","(x,n)","(x,n)"},
+{"precision",_SAME},
+{"prime",_SAME},
+{"primedec","idealprimedec","(nf,p)","(nf,p)"},
+{"primes",_SAME},
+{"primroot","znprimroot","(n)","(n)"},
+{"principalideal",_REMOV},
+{"principalidele",_REMOV},
+{"prod","prod","(x,X=a,b,expr)","(X=a,b,expr,x)"},
+{"prodeuler",_SAME},
+{"prodinf",_SAME},
+{"prodinf1","prodinf","(X=a,expr)","(X=a,expr,1)"},
+{"psi",_SAME},
+{"qfi","Qfb","(a,b,c)","(a,b,c)"},
+{"qfr","Qfb","(a,b,c,d)","(a,b,c,d)"},
+{"quaddisc",_SAME},
+{"quadgen",_SAME},
+{"quadpoly",_SAME},
+{"random",_SAME},
+{"rank","matrank","(x)","(x)"},
+{"rayclassno","bnrclassno","(bnf,x)","(bnf,x)"},
+{"rayclassnolist","bnrclassnolist","(bnf,liste)","(bnf,liste)"},
+{"real",_SAME},
+{"recip","polrecip","(x)","(x)"},
+{"redimag","qfbred","(x)","(x)"},
+{"redreal","qfbred","(x)","(x)"},
+{"redrealnod","qfbred","(x,d)","(x,2,,d)"},
+{"reduceddisc","poldiscreduced","(f)","(f)"},
+{"regula","quadregulator","(x)","(x)"},
+{"reorder",_REMOV},
+{"resultant","polresultant","(x,y)","(x,y)"},
+{"resultant2","polresultant","(x,y)","(x,y,1)"},
+{"reverse","serreverse","(x)","(x)"},
+{"rhoreal","qfbred","(x)","(x,1)"},
+{"rhorealnod","qfbred","(x,d)","(x,3,,d)"},
+{"rndtoi","round","(x)","(x,&e)"},
+{"rnfbasis",_SAME},
+{"rnfdiscf","rnfdisc","(nf,pol)","(nf,pol)"},
+{"rnfequation",_SAME},
+{"rnfequation2","rnfequation","(nf,pol)","(nf,pol,1)"},
+{"rnfhermitebasis","rnfhnfbasis","(bnf,order)","(bnf,order)"},
+{"rnfisfree",_SAME},
+{"rnflllgram",_SAME},
+{"rnfpolred",_SAME},
+{"rnfpseudobasis",_SAME},
+{"rnfsteinitz",_SAME},
+{"rootmod","polrootsmod","(x,p)","(x,p)"},
+{"rootmod2","polrootsmod","(x,p)","(x,p,1)"},
+{"rootpadic","polrootspadic","(x,p,r)","(x,p,r)"},
+{"roots","polroots","(x)","(x)"},
+{"rootsof1","nfrootsof1","(nf)","(nf)"},
+{"rootsold",_REMOV},
+{"round",_SAME},
+{"rounderror","round","(x)","(x,&e)"},
+{"series","Ser","(x,v)","(x,v)"},
+{"set","Set","(x)","(x)"},
+{"setintersect",_SAME},
+{"setminus",_SAME},
+{"setrand",_SAME},
+{"setsearch",_SAME},
+{"setunion",_SAME},
+{"shift",_SAME},
+{"shiftmul",_SAME},
+{"sigma",_SAME},
+{"sigmak","sigma","(k,x)","(x,k)"},
+{"sign",_SAME},
+{"signat","qfsign","(x)","(x)"},
+{"signunit","bnfsignunit","(bnf)","(bnf)"},
+{"simplefactmod","factormod","(x,p)","(x,p,1)"},
+{"simplify",_SAME},
+{"sin",_SAME},
+{"sinh",_SAME},
+{"size","sizedigit","(x)","(x)"},
+{"smallbasis","nfbasis","(x)","(x,1)"},
+{"smallbuchinit","bnfcompress","(x)","(x)"},
+{"smalldiscf","nfdisc","(x)","(x,1)"},
+{"smallfact","factor","(x)","(x,0)"},
+{"smallinitell","ellinit","(x)","(x,1)"},
+{"smallpolred","polred","(x)","(x,1)"},
+{"smallpolred2","polred","(x)","(x,3)"},
+{"smith","matsnf","(x)","(x)"},
+{"smith2","matsnf","(x)","(x,1)"},
+{"smithclean","matsnf","(x)","(x,4)"},
+{"smithpol","matsnf","(x)","(x,2)"},
+{"solve",_SAME},
+{"sort","vecsort","(x)","(x)"},
+{"sqr",_SAME},
+{"sqred","qfgaussred","(x)","(x)"},
+{"sqrt",_SAME},
+{"srgcd","gcd","(x,y)","(x,y,2)"},
+{"sturm","polsturm","(x)","(x)"},
+{"sturmpart","polsturm","(x,a,b)","(x,a,b)"},
+{"subcyclo","polsubcyclo","(p,d)","(p,d)"},
+{"subell","ellsub","(e,a,b)","(e,a,b)"},
+{"subst",_SAME},
+{"sum","sum","(x,X=a,b,expr)","(X=a,b,expr,x)"},
+{"sumalt",_SAME},
+{"sumalt2","sumalt","(X=a,expr)","(X=a,expr,1)"},
+{"suminf",_SAME},
+{"sumpos",_SAME},
+{"sumpos2","sumpos","(X=a,expr)","(X=a,expr,1)"},
+{"supplement","matsupplement","(x)","(x)"},
+{"sylvestermatrix","polsylvestermatrix","(x,y)","(x,y)"},
+{"system",_SAME},
+{"tan",_SAME},
+{"tanh",_SAME},
+{"taniyama","elltaniyama","(e)","(e)"},
+{"taylor",_SAME},
+{"tchebi","polchebyshev","(n)","(n)"},
+{"teich","teichmuller","(x)","(x)"},
+{"theta",_SAME},
+{"thetanullk",_SAME},
+{"threetotwo",_REMOV},
+{"threetotwo2",_REMOV},
+{"torsell","elltors","(e)","(e)"},
+{"trace",_SAME},
+{"trans","mattranspose","(x)","(x)"},
+{"trunc","truncate","(x)","(x)"},
+{"tschirnhaus","poltschirnhaus","(x)","(x)"},
+{"twototwo",_REMOV},
+{"unit","quadunit","(x)","(x)"},
+{"until",_SAME},
+{"valuation",_SAME},
+{"vec","Vec","(x)","(x)"},
+{"vecindexsort","vecsort","(x)","(x,,1)"},
+{"veclexsort","vecsort","(x)","(x,,2)"},
+{"vecmax",_SAME},
+{"vecmin",_SAME},
+{"vecsort",_SAME},
+{"vector",_SAME},
+{"vvector","vectorv","(n,X,expr)","(n,X,expr)"},
+{"weipell","ellwp","(e)","(e)"},
+{"wf","weber","(x)","(x)"},
+{"wf2","weber","(x)","(x,2)"},
+{"while",_SAME},
+{"zell","ellpointtoz","(e,P)","(e,P)"},
+{"zeta",_SAME},
+{"zetak",_SAME},
+{"zideallog","ideallog","(nf,x,bid)","(nf,x,bid)"},
+{"zidealstar","idealstar","(nf,I)","(nf,I)"},
+{"zidealstarinit","idealstar","(nf,id)","(nf,id,1)"},
+{"zidealstarinitgen","idealstar","(nf,id)","(nf,id,2)"},
+{"znstar",_SAME},
+{"allocatemem",_SAME},
+{"box","plotbox","(x,a)","(x,a)"},
+{"color","plotcolor","(w,c)","(w,c)"},
+{"cursor","plotcursor","(w)","(w)"},
+{"default",_SAME},
+{"draw","plotdraw","(list)","(list)"},
+{"initrect","plotinit","(w,x,y)","(w,x,y)"},
+{"kill",_SAME},
+{"killrect","plotkill","(w)","(w)"},
+{"line","plotlines","(w,x2,y2)","(w,x2,y2)"},
+{"lines","plotlines","(w,x2,y2)","(w,x2,y2)"},
+{"move","plotmove","(w,x,y)","(w,x,y)"},
+{"plot",_SAME},
+{"ploth",_SAME},
+{"ploth2","ploth","(X=a,b,expr)","(X=a,b,expr,1)"},
+{"plothmult","ploth","(X=a,b,expr)","(X=a,b,expr)"},
+{"plothraw",_SAME},
+{"point","plotpoints","(w,x,y)","(w,x,y)"},
+{"points","plotpoints","(w,x,y)","(w,x,y)"},
+{"postdraw","psdraw","(list)","(list)"},
+{"postploth","psploth","(X=a,b,expr)","(X=a,b,expr)"},
+{"postploth2","psploth","(X=a,b,expr)","(X=a,b,expr,1)"},
+{"postplothraw","psplothraw","(listx,listy)","(listx,listy)"},
+{"pprint",_REMOV},
+{"pprint1",_REMOV},
+{"print",_SAME},
+{"print1",_SAME},
+{"rbox","plotrbox","(w,dx,dy)","(w,dx,dy)"},
+{"read","input","(x)","(x)"},
+{"rline","plotrline","(w,dx,dy)","(w,dx,dy)"},
+{"rlines","plotrlines","(w,dx,dy)","(w,dx,dy,1)"},
+{"rmove","plotrmove","(w,dx,dy)","(w,dx,dy)"},
+{"rpoint","plotrpoint","(w,dx,dy)","(w,dx,dy)"},
+{"rpoints","plotrpoints","(w,dx,dy)","(w,dx,dy)"},
+{"scale","plotscale","(w,x1,x2,y1,y2)","(w,x1,x2,y1,y2)"},
+{"setprecision","default","(n)","(realprecision,n)"},
+{"setserieslength","default","(n)","(seriesprecision,n)"},
+{"settype","type","(x,t)","(x,t)"},
+{"string","plotstring","(w,x)","(w,x)"},
+{"texprint","printtex","(x)","(x)"},
+{"type",_SAME},
+{NULL,_SAME}
 };
diff --git a/src/graph/plotQt.c b/src/graph/plotQt.c
index f55caf6..d55f78d 100644
--- a/src/graph/plotQt.c
+++ b/src/graph/plotQt.c
@@ -101,12 +101,12 @@ Plotter::Plotter( long *w, long *x, long *y, long lw,
     this->setCaption( "Pari QtPlot");
 #endif
     this->setFont( font);
-    numcolors = lg(pari_colormap)-1;
+    numcolors = lg(GP_DATA->colormap)-1;
     color = (QColor*)pari_malloc(numcolors*sizeof(QColor));
-    for (i = 1; i < lg(pari_colormap); i++)
+    for (i = 1; i < lg(GP_DATA->colormap); i++)
     {
       int r, g, b;
-      color_to_rgb(gel(pari_colormap,i), &r, &g, &b);
+      color_to_rgb(gel(GP_DATA->colormap,i), &r, &g, &b);
       color[i-1] = QColor(r, g, b);
     }
     this->setBackgroundColor( color[0]);
diff --git a/src/graph/plotQt4.c b/src/graph/plotQt4.c
index a3e8428..e9a9b23 100644
--- a/src/graph/plotQt4.c
+++ b/src/graph/plotQt4.c
@@ -114,12 +114,12 @@ Plotter::Plotter( long *w, long *x, long *y, long lw,
     this->setCaption( "Pari QtPlot");
 #endif
     this->setFont( font);
-    numcolors = lg(pari_colormap)-1;
+    numcolors = lg(GP_DATA->colormap)-1;
     color = (QColor*)gpmalloc(numcolors*sizeof(QColor));
-    for (i = 1; i < lg(pari_colormap); i++)
+    for (i = 1; i < lg(GP_DATA->colormap); i++)
     {
       int r, g, b;
-      color_to_rgb(gel(pari_colormap,i), &r, &g, &b);
+      color_to_rgb(gel(GP_DATA->colormap,i), &r, &g, &b);
       color[i-1] = QColor(r, g, b);
     }
     QPalette palette;
diff --git a/src/graph/plotWin32.c b/src/graph/plotWin32.c
index 17dfc32..ffcd988 100644
--- a/src/graph/plotWin32.c
+++ b/src/graph/plotWin32.c
@@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 static void SetForeground(void *data, long col)
 {
   int r,g,b;
-  color_to_rgb(gel(pari_colormap,col), &r, &g, &b);
+  color_to_rgb(gel(GP_DATA->colormap,col), &r, &g, &b);
 
   HPEN hOldPen = SelectObject((HDC)data, CreatePen(PS_SOLID, 2, RGB(r,g,b)));
   if( hOldPen ) DeleteObject(hOldPen);
diff --git a/src/graph/plotX.c b/src/graph/plotX.c
index 53af787..af7b0e7 100644
--- a/src/graph/plotX.c
+++ b/src/graph/plotX.c
@@ -181,7 +181,7 @@ rectdraw0(long *w, long *x, long *y, long lw)
   if (!font_info) exiterr("cannot open 9x15 font");
   XSetErrorHandler(Xerror);
   XSetIOErrorHandler(IOerror);
-  PARI_ColorSetUp(display,pari_colormap);
+  PARI_ColorSetUp(display,GP_DATA->colormap);
 
   screen = DefaultScreen(display);
   win = XCreateSimpleWindow
@@ -218,7 +218,7 @@ rectdraw0(long *w, long *x, long *y, long lw)
   oldheight = pari_plot.height;
   dx.display= display;
   dx.win = win;
-  dx.numcolors = lg(pari_colormap)-1;
+  dx.numcolors = lg(GP_DATA->colormap)-1;
   dx.gc = gc;
   plotX.sc = &SetForeground;
   plotX.pt = &DrawPoint;
diff --git a/src/graph/plotfltk.c b/src/graph/plotfltk.c
index e04cc41..a0b903d 100644
--- a/src/graph/plotfltk.c
+++ b/src/graph/plotfltk.c
@@ -60,12 +60,12 @@ Plotter::Plotter( long *w, long *x, long *y, long lw,
     long i;
 
     this->my_w=w; this->my_x=x; this->my_y=y; this->my_lw=lw;
-    numcolors = lg(pari_colormap)-1;
+    numcolors = lg(GP_DATA->colormap)-1;
     color = (Fl_Color*)pari_malloc(numcolors*sizeof(Fl_Color));
-    for (i = 1; i < lg(pari_colormap); i++)
+    for (i = 1; i < lg(GP_DATA->colormap); i++)
     {
       int r, g, b;
-      color_to_rgb(gel(pari_colormap,i), &r, &g, &b);
+      color_to_rgb(gel(GP_DATA->colormap,i), &r, &g, &b);
       color[i-1] = rgb_color(r, g, b);
     }
 }
diff --git a/src/graph/plotport.c b/src/graph/plotport.c
index da17978..16edb6f 100644
--- a/src/graph/plotport.c
+++ b/src/graph/plotport.c
@@ -117,7 +117,7 @@ plot(GEN a, GEN b, GEN code, GEN ysmlu,GEN ybigu, long prec)
 {
   const char BLANK = ' ', YY = '|', XX_UPPER = '\'', XX_LOWER = '.';
   long jz, j, i, sig;
-  pari_sp av = avma, av2, limite;
+  pari_sp av = avma;
   int jnew, jpre = 0; /* for lint */
   GEN x, dx;
   double diff, dyj, ysml, ybig, y[ISCR+1];
@@ -135,11 +135,12 @@ plot(GEN a, GEN b, GEN code, GEN ysmlu,GEN ybigu, long prec)
     scr[i][JSCR]= XX_UPPER;
     for (j=2; j<JSCR; j++) scr[i][j] = BLANK;
   }
-  av2 = avma; limite=stack_lim(av2,1);
   ysml = ybig = 0.; /* -Wall */
   for (i=1; i<=ISCR; i++)
   {
+    pari_sp av2 = avma;
     y[i] = gtodouble( READ_EXPR(code,x) );
+    avma = av2;
     if (i == 1)
       ysml = ybig = y[1];
     else
@@ -148,11 +149,6 @@ plot(GEN a, GEN b, GEN code, GEN ysmlu,GEN ybigu, long prec)
       if (y[i] > ybig) ybig = y[i];
     }
     x = addrr(x,dx);
-    if (low_stack(limite, stack_lim(av2,1)))
-    {
-      if (DEBUGMEM>1) pari_warn(warnmem,"plot");
-      x = gerepileuptoleaf(av2, x);
-    }
   }
   avma = av;
   if (ysmlu) ysml = gtodouble(ysmlu);
@@ -163,7 +159,7 @@ plot(GEN a, GEN b, GEN code, GEN ysmlu,GEN ybigu, long prec)
   /* work around bug in gcc-4.8 (32bit): plot(x=-5,5,sin(x)))) */
   jz = 3 - (long)(ysml*dyj + 0.5); /* 3 - DTOL(ysml*dyj) */
   z = PICTZERO(jz); jz /= 3;
-  for (i=1; i<=ISCR; i++, avma = av2)
+  for (i=1; i<=ISCR; i++)
   {
     if (0<=jz && jz<=JSCR) scr[i][jz]=z;
     j = 3 + DTOL((y[i]-ysml)*dyj);
@@ -227,8 +223,8 @@ free_graph(void)
     pari_free((void*)rgb_colors->table);
     pari_free((void*)rgb_colors);
   }
-  if (pari_colormap) pari_free(pari_colormap);
-  if (pari_graphcolors) pari_free(pari_graphcolors);
+  if (GP_DATA->colormap) pari_free(GP_DATA->colormap);
+  if (GP_DATA->graphcolors) pari_free(GP_DATA->graphcolors);
 }
 
 static PariRect *
@@ -388,7 +384,7 @@ rectrpoint(long ne, GEN x, GEN y)
 void
 rectcolor(long ne, long c)
 {
-  long n = lg(pari_colormap)-2;
+  long n = lg(GP_DATA->colormap)-2;
   check_rect(ne);
   if (c < 1) pari_err_DOMAIN("rectcolor", "color", "<", gen_1, stoi(c));
   if (c > n) pari_err_DOMAIN("rectcolor", "color", ">", stoi(n), stoi(c));
@@ -820,13 +816,18 @@ rectcopy_gen(long source, long dest, GEN xoff, GEN yoff, long flag)
   long xi, yi;
   if (flag & RECT_CP_RELATIVE) {
     double xd = gtodouble(xoff), yd = gtodouble(yoff);
-
+    if (xd > 1) pari_err_DOMAIN("plotcopy","dx",">",gen_1,xoff);
+    if (xd < 0) pari_err_DOMAIN("plotcopy","dx","<",gen_0,xoff);
+    if (yd > 1) pari_err_DOMAIN("plotcopy","dy",">",gen_1,yoff);
+    if (yd < 0) pari_err_DOMAIN("plotcopy","dy","<",gen_0,yoff);
     PARI_get_plot();
     xi = pari_plot.width - 1;
     yi = pari_plot.height - 1;
     xi = DTOL(xd*xi);
     yi = DTOL(yd*yi);
   } else {
+    if (typ(xoff) != t_INT) pari_err_TYPE("plotcopy",xoff);
+    if (typ(yoff) != t_INT) pari_err_TYPE("plotcopy",yoff);
     xi = itos(xoff);
     yi = itos(yoff);
   }
@@ -850,60 +851,47 @@ rectcopy_gen(long source, long dest, GEN xoff, GEN yoff, long flag)
   rectcopy(source, dest, xi, yi);
 }
 
+static void*
+cp(void* R, size_t t)
+{ void *o = pari_malloc(t); memcpy(o,R,t); return o; }
+
 void
-rectcopy(long source, long dest, long xoff, long yoff)
+rectcopy(long source, long dest, long x, long y)
 {
   PariRect *s = check_rect_init(source), *d = check_rect_init(dest);
-  RectObj *R = RHead(s);
-  RectObj *tail = RTail(d);
-  RectObj *next;
-  int i;
+  RectObj *R, *tail = RTail(d);
+  long i;
 
-  while (R)
+  for (R = RHead(s); R; R = RoNext(R))
   {
+    RectObj *o;
     switch(RoType(R))
     {
       case ROt_PT:
-        next = (RectObj*) pari_malloc(sizeof(RectObj1P));
-        memcpy(next,R,sizeof(RectObj1P));
-        RoPTx(next) += xoff; RoPTy(next) += yoff;
-        RoNext(tail) = next; tail = next;
+        o = (RectObj*)cp(R, sizeof(RectObj1P));
+        RoPTx(o) += x; RoPTy(o) += y;
         break;
       case ROt_LN: case ROt_BX:
-        next = (RectObj*) pari_malloc(sizeof(RectObj2P));
-        memcpy(next,R,sizeof(RectObj2P));
-        RoLNx1(next) += xoff; RoLNy1(next) += yoff;
-        RoLNx2(next) += xoff; RoLNy2(next) += yoff;
-        RoNext(tail) = next; tail = next;
+        o = (RectObj*)cp(R, sizeof(RectObj2P));
+        RoLNx1(o) += x; RoLNy1(o) += y;
+        RoLNx2(o) += x; RoLNy2(o) += y;
         break;
       case ROt_MP: case ROt_ML:
-        next = (RectObj*) pari_malloc(sizeof(RectObjMP));
-        memcpy(next,R,sizeof(RectObjMP));
-        RoMPxs(next) = (double*) pari_malloc(sizeof(double)*RoMPcnt(next));
-        RoMPys(next) = (double*) pari_malloc(sizeof(double)*RoMPcnt(next));
-        memcpy(RoMPxs(next),RoMPxs(R),sizeof(double)*RoMPcnt(next));
-        memcpy(RoMPys(next),RoMPys(R),sizeof(double)*RoMPcnt(next));
-        for (i=0; i<RoMPcnt(next); i++)
-        {
-          RoMPxs(next)[i] += xoff; RoMPys(next)[i] += yoff;
-         }
-        RoNext(tail) = next; tail = next;
+        o = (RectObj*)cp(R, sizeof(RectObjMP));
+        RoMPxs(o) = (double*)cp(RoMPxs(R), sizeof(double)*RoMPcnt(o));
+        RoMPys(o) = (double*)cp(RoMPys(R), sizeof(double)*RoMPcnt(o));
+        for (i=0; i<RoMPcnt(o); i++) { RoMPxs(o)[i] += x; RoMPys(o)[i] += y; }
         break;
       case ROt_ST:
-        next = (RectObj*) pari_malloc(sizeof(RectObjST));
-        memcpy(next,R,sizeof(RectObjMP));
-        RoSTs(next) = (char*) pari_malloc(RoSTl(R)+1);
-        memcpy(RoSTs(next),RoSTs(R),RoSTl(R)+1);
-        RoSTx(next) += xoff; RoSTy(next) += yoff;
-        RoNext(tail) = next; tail = next;
+        o = (RectObj*)cp(R, sizeof(RectObjST));
+        RoSTs(o) = (char*)cp(RoSTs(R),RoSTl(R)+1);
+        RoSTx(o) += x; RoSTy(o) += y;
         break;
-      case ROt_PTT: case ROt_LNT: case ROt_PTS:
-        next = (RectObj*) pari_malloc(sizeof(RectObjPN));
-        memcpy(next,R,sizeof(RectObjPN));
-        RoNext(tail) = next; tail = next;
+      default: /* ROt_PTT, ROt_LNT, ROt_PTS */
+        o = (RectObj*)cp(R, sizeof(RectObjPN));
         break;
     }
-    R=RoNext(R);
+    RoNext(tail) = o; tail = o;
   }
   RoNext(tail) = NULL; RTail(d) = tail;
 }
@@ -1686,10 +1674,10 @@ rectplothrawin(long grect, dblPointList *data, long flags)
     flags |= PLOT_PARAMETRIC;
     flags &= (~PLOT_COMPLEX); /* turn COMPLEX to PARAMETRIC*/
   } else i = 1;
-  max_graphcolors = lg(pari_graphcolors)-1;
+  max_graphcolors = lg(GP_DATA->graphcolors)-1;
   for (ltype = 0; ltype < nc; ltype++)
   {
-    current_color[grect] = pari_graphcolors[1+(ltype%max_graphcolors)];
+    current_color[grect] = GP_DATA->graphcolors[1+(ltype%max_graphcolors)];
     if (param) x = data[i++];
 
     y = data[i++]; nbpoints = y.nb;
@@ -1820,7 +1808,7 @@ plot_count(long *w, long lw, col_counter rcolcnt)
   RectObj *O;
   long col, i;
 
-  for (col = 1; col < lg(pari_colormap)-1; col++)
+  for (col = 1; col < lg(GP_DATA->colormap)-1; col++)
     for (i = 0; i < ROt_MAX; i++) rcolcnt[col][i] = 0;
   for (i = 0; i < lw; i++)
   {
@@ -1908,14 +1896,14 @@ rectdraw_flag(GEN list, long flag) { gendraw(list, 0, flag); }
 static void
 ps_sc(void *data, long col)
 {
-  long l = lg(pari_colormap)-1;
+  long l = lg(GP_DATA->colormap)-1;
   int r, g, b;
   if (col >= l)
   {
     pari_warn(warner,"non-existent color: %ld", col);
     col = l-1;
   }
-  color_to_rgb(gel(pari_colormap,col+1), &r, &g, &b);
+  color_to_rgb(gel(GP_DATA->colormap,col+1), &r, &g, &b);
   fprintf((FILE*)data,"%f %f %f setrgbcolor\n", r/255., g/255., b/255.);
 }
 
@@ -2030,7 +2018,7 @@ gen_rectdraw0(struct plot_eng *eng, long *w, long *x, long *y, long lw, double x
   long i, j;
   long hgapsize = eng->pl->hunit, fheight = eng->pl->fheight;
   long vgapsize = eng->pl->vunit,  fwidth = eng->pl->fwidth;
-  long numcolors = lg(pari_colormap)-1;
+  long numcolors = lg(GP_DATA->colormap)-1;
   for(i=0; i<lw; i++)
   {
     PariRect *e = rectgraph[w[i]];
@@ -2127,19 +2115,18 @@ gen_rectdraw0(struct plot_eng *eng, long *w, long *x, long *y, long lw, double x
 /*                           RGB COLORS                                  */
 /*                                                                       */
 /*************************************************************************/
-#if 0
-/* generated from /etc/X11/rgb.txt by the following perl script */
+/* generated from /etc/X11/rgb.txt by the following perl script
 #!/usr/bin/perl
 while(<>)
 {
   ($hex, $name) = split(/\t\t/, $_);
-  $hex =~ s/^ +//; chomp($name); $name =~ s/ *//g;
+  $hex =~ s/^ +//; chomp($name); $name =~ s, *,,g;
   $hex = sprintf("0x%02x%02x%02x", split(/\s+/, $hex));
   $name = lc($name); next if ($done{$name});
   $done{$name} = 1;
   print "COL(\"$name\", $hex),\n";
 }
-#endif
+*/
 
 #define COL(x,y) {(void*)x,(void*)y,0,NULL}
 static hashentry col_list[] = {
diff --git a/src/graph/plotps.c b/src/graph/plotps.c
index bc73ab3..2de871c 100644
--- a/src/graph/plotps.c
+++ b/src/graph/plotps.c
@@ -19,10 +19,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 #include "paripriv.h"
 #include "rect.h"
 
-BEGINEXTERN
-void system0(const char *s);
-ENDEXTERN
-
 void
 rectdraw0(long *w, long *x, long *y, long lw)
 {
@@ -43,7 +39,7 @@ rectdraw0(long *w, long *x, long *y, long lw)
   v = os_getenv("GP_POSTSCRIPT_VIEWER");
   if (!v) v = "open -W";
   cmd = pari_sprintf("%s \"%s\" 2>/dev/null", v, s);
-  system0(cmd);
+  gpsystem(cmd);
   pari_unlink(s); exit(0);
 }
 
diff --git a/src/headers/paricom.h b/src/headers/paricom.h
index fef9970..7ab6594 100644
--- a/src/headers/paricom.h
+++ b/src/headers/paricom.h
@@ -62,8 +62,8 @@ extern const long CATCH_ALL;
 #define pari_ENDCATCH pari_ENDCATCH2(__iferr_old)
 
 extern const double LOG2, LOG10_2, LOG2_10;
-#ifndef  PI
-#  define PI (3.141592653589)
+#ifndef  M_PI
+#  define M_PI 3.14159265358979323846
 #endif
 
 /* Common global variables: */
@@ -78,21 +78,19 @@ extern THREAD VOLATILE int PARI_SIGINT_block, PARI_SIGINT_pending;
 
 extern const long lontyp[];
 extern void (*cb_pari_ask_confirm)(const char *);
+extern void (*cb_pari_init_histfile)(void);
 extern int  (*cb_pari_whatnow)(PariOUT *out, const char *, int);
+extern void (*cb_pari_quit)(long);
 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 int (*cb_pari_break_loop)(int);
+extern int (*cb_pari_is_interactive)(void);
+extern void (*cb_pari_start_output)(void);
 extern const char *pari_library_path;
-
-enum manage_var_t {
-  manage_var_create,
-  manage_var_delete,
-  manage_var_init,
-  manage_var_next,
-  manage_var_max_avail,
-  manage_var_pop
-};
+extern long *varpriority;
 
 /* pari_init_opts */
 enum {
diff --git a/src/headers/paridecl.h b/src/headers/paridecl.h
index f60b229..c52e3fe 100644
--- a/src/headers/paridecl.h
+++ b/src/headers/paridecl.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2004  The PARI group.
+/* Copyright (C) 1999-2004  The PARI group.
 
 This file is part of the PARI/GP package.
 
@@ -53,6 +53,14 @@ struct bb_algebra
   GEN (*zero)(void *E);
 };
 
+/* black box ring */
+struct bb_ring
+{
+  GEN (*add)(void *E, GEN x, GEN y);
+  GEN (*mul)(void *E, GEN x, GEN y);
+  GEN (*sqr)(void *E, GEN x);
+};
+
 /* OBSOLETE */
 GEN     bernvec(long nomb);
 GEN     buchimag(GEN D, GEN c1, GEN c2, GEN gCO);
@@ -166,23 +174,65 @@ const struct bb_group * get_F2xqE_group(void **E, GEN a2, GEN a6, GEN T);
 GEN     RgE_to_F2xqE(GEN x, GEN T);
 GEN     random_F2xqE(GEN a2, GEN a6, GEN T);
 
+/* Fle.c */
+
+ulong   Fl_elldisc(ulong a4, ulong a6, ulong p);
+ulong   Fl_elldisc_pre(ulong a4, ulong a6, ulong p, ulong pi);
+ulong   Fl_ellj(ulong a4, ulong a6, ulong p);
+void    Fl_ellj_to_a4a6(ulong j, ulong p, ulong *pt_a4, ulong *pt_a6);
+void    Fl_elltwist(ulong a4, ulong a6, ulong D, ulong p, ulong *pt_a4, ulong *pt_a6);
+GEN     Fle_add(GEN P, GEN Q, ulong a4, ulong p);
+GEN     Fle_dbl(GEN P, ulong a4, ulong p);
+GEN     Fle_changepoint(GEN x, GEN ch, ulong p);
+GEN     Fle_changepointinv(GEN x, GEN ch, ulong p);
+GEN     Fle_log(GEN a, GEN b, GEN o, ulong a4, ulong p);
+GEN     Fle_mul(GEN P, GEN n, ulong a4, ulong p);
+GEN     Fle_mulu(GEN P, ulong n, ulong a4, ulong p);
+GEN     Fle_order(GEN z, GEN o, ulong a4, ulong p);
+GEN     Fle_sub(GEN P, GEN Q, ulong a4, ulong p);
+GEN     Fle_to_Flj(GEN P);
+GEN     Flj_add_pre(GEN P, GEN Q, ulong a4, ulong p, ulong pi);
+GEN     Flj_dbl_pre(GEN P, ulong a4, ulong p, ulong pi);
+GEN     Flj_mulu_pre(GEN P, ulong n, ulong a4, ulong p, ulong pi);
+GEN     Flj_neg(GEN Q, ulong p);
+GEN     Flj_to_Fle_pre(GEN P, ulong p, ulong pi);
+GEN     random_Fle(ulong a4, ulong a6, ulong p);
+GEN     random_Fle_pre(ulong a4, ulong a6, ulong p, ulong pi);
+GEN     random_Flj_pre(ulong a4, ulong a6, ulong p, ulong pi);
+
 /* Flx.c */
 
+const struct bb_group * get_Flxq_star(void **E, GEN T, ulong p);
 GEN     Fl_to_Flx(ulong x, long sv);
+int     Fl2_equal1(GEN x);
+GEN     Fl2_inv_pre(GEN x, ulong D, ulong p, ulong pi);
+GEN     Fl2_mul_pre(GEN x, GEN y, ulong D, ulong p, ulong pi);
+ulong   Fl2_norm_pre(GEN x, ulong D, ulong p, ulong pi);
+GEN     Fl2_pow_pre(GEN x, GEN n, ulong D, ulong p, ulong pi);
+GEN     Fl2_sqr_pre(GEN x, ulong D, ulong p, ulong pi);
+GEN     Fl2_sqrtn_pre(GEN a, GEN n, ulong D, ulong p, ulong pi, GEN *zeta);
 GEN     Flc_to_ZC(GEN z);
 GEN     Flm_to_FlxV(GEN x, long sv);
 GEN     Flm_to_FlxX(GEN x, long v,long w);
 GEN     Flm_to_ZM(GEN z);
-GEN     Flv_to_Flx(GEN x, long vs);
-GEN     Flv_to_ZV(GEN z);
+GEN     Flv_FlvV_polint(GEN xa, GEN ya, ulong p, long vs);
+GEN     Flv_inv(GEN x, ulong p);
+void    Flv_inv_inplace(GEN x, ulong p);
+void    Flv_inv_pre_inplace(GEN x, ulong p, ulong pi);
+GEN     Flv_inv_pre(GEN x, ulong p, ulong pi);
 GEN     Flv_polint(GEN xa, GEN ya, ulong p, long vs);
 GEN     Flv_roots_to_pol(GEN a, ulong p, long vs);
+GEN     Flv_to_Flx(GEN x, long vs);
 GEN     Fly_to_FlxY(GEN B, long v);
+GEN     Flv_to_ZV(GEN z);
 GEN     Flx_Fl_add(GEN y, ulong x, ulong p);
 GEN     Flx_Fl_mul(GEN y, ulong x, ulong p);
 GEN     Flx_Fl_mul_to_monic(GEN y, ulong x, ulong p);
+GEN     Flx_Fl2_eval_pre(GEN x, GEN y, ulong D, ulong p, ulong pi);
+GEN     Flx_Flv_multieval(GEN P, GEN v, ulong p);
 GEN     Flx_Flxq_eval(GEN f,GEN x,GEN T,ulong p);
 GEN     Flx_FlxqV_eval(GEN f,GEN x,GEN T,ulong p);
+GEN     Flx_Frobenius(GEN T, ulong p);
 GEN     Flx_add(GEN x, GEN y, ulong p);
 GEN     Flx_deflate(GEN x0, long d);
 GEN     Flx_deriv(GEN z, ulong p);
@@ -191,6 +241,8 @@ GEN     Flx_div_by_X_x(GEN a, ulong x, ulong p, ulong *rem);
 GEN     Flx_divrem(GEN x, GEN y, ulong p, GEN *pr);
 int     Flx_equal(GEN V, GEN W);
 ulong   Flx_eval(GEN x, ulong y, ulong p);
+ulong   Flx_eval_powers_pre(GEN x, GEN y, ulong p, ulong pi);
+ulong   Flx_eval_pre(GEN x, ulong y, ulong p, ulong pi);
 GEN     Flx_extgcd(GEN a, GEN b, ulong p, GEN *ptu, GEN *ptv);
 ulong   Flx_extresultant(GEN a, GEN b, ulong p, GEN *ptU, GEN *ptV);
 GEN     Flx_gcd(GEN a, GEN b, ulong p);
@@ -200,17 +252,19 @@ GEN     Flx_inflate(GEN x0, long d);
 GEN     Flx_invBarrett(GEN T, ulong p);
 int     Flx_is_squarefree(GEN z, ulong p);
 int     Flx_is_smooth(GEN g, long r, ulong p);
+GEN     Flx_matFrobenius(GEN T, ulong p);
 GEN     Flx_mod_Xn1(GEN T, ulong n, ulong p);
 GEN     Flx_mod_Xnm1(GEN T, ulong n, ulong p);
 GEN     Flx_mul(GEN x, GEN y, ulong p);
 GEN     Flx_neg(GEN x, ulong p);
 GEN     Flx_neg_inplace(GEN x, ulong p);
 GEN     Flx_normalize(GEN z, ulong p);
-GEN     Flx_pow(GEN x, long n, ulong p);
+GEN     Flx_powu(GEN x, ulong n, ulong p);
 GEN     Flx_recip(GEN x);
 GEN     Flx_red(GEN z, ulong p);
 GEN     Flx_rem(GEN x, GEN y, ulong p);
 GEN     Flx_renormalize(GEN x, long l);
+GEN     Flx_rescale(GEN P, ulong h, ulong p);
 ulong   Flx_resultant(GEN a, GEN b, ulong p);
 GEN     Flx_shift(GEN a, long n);
 GEN     Flx_splitting(GEN p, long k);
@@ -247,8 +301,11 @@ GEN     FlxX_to_ZXX(GEN B);
 GEN     FlxX_triple(GEN x, ulong p);
 GEN     FlxXV_to_FlxM(GEN v, long n, long sv);
 GEN     FlxY_Flxq_evalx(GEN P, GEN x, GEN T, ulong p);
+GEN     FlxY_FlxqV_evalx(GEN P, GEN x, GEN T, ulong p);
 GEN     FlxY_Flx_div(GEN x, GEN y, ulong p);
+ulong   FlxY_eval_powers_pre(GEN pol, GEN ypowers, GEN xpowers, ulong p, ulong pi);
 GEN     FlxY_evalx(GEN Q, ulong x, ulong p);
+GEN     FlxY_evalx_powers_pre(GEN pol, GEN ypowers, ulong p, ulong pi);
 GEN     FlxYqq_pow(GEN x, GEN n, GEN S, GEN T, ulong p);
 GEN     Flxq_autpow(GEN x, ulong n, GEN T, ulong p);
 GEN     Flxq_autsum(GEN x, ulong n, GEN T, ulong p);
@@ -319,6 +376,8 @@ const struct bb_field *get_Flxq_field(void **E, GEN T, ulong p);
 GEN     pol1_FlxX(long v, long sv);
 GEN     polx_FlxX(long v, long sv);
 GEN     random_Flx(long d1, long v, ulong p);
+GEN     zx_to_Flx(GEN x, ulong p);
+GEN     zxX_to_FlxX(GEN B, ulong p);
 GEN     zxX_to_Kronecker(GEN P, GEN Q);
 
 /* FlxqE.c */
@@ -327,6 +386,7 @@ GEN     Flxq_ellcard(GEN a4, GEN a6, GEN T, ulong p);
 GEN     Flxq_ellgens(GEN a4, GEN a6, GEN ch, GEN D, GEN m, GEN T, ulong p);
 GEN     Flxq_ellgroup(GEN a4, GEN a6, GEN N, GEN T, ulong p, GEN *pt_m);
 GEN     Flxq_ellj(GEN a4, GEN a6, GEN T, ulong p);
+void    Flxq_ellj_to_a4a6(GEN j, GEN T, ulong p, GEN *pt_a4, GEN *pt_a6);
 GEN     FlxqE_add(GEN P, GEN Q, GEN a4, GEN T, ulong p);
 GEN     FlxqE_changepoint(GEN x, GEN ch, GEN T, ulong p);
 GEN     FlxqE_changepointinv(GEN x, GEN ch, GEN T, ulong p);
@@ -345,17 +405,13 @@ GEN     random_FlxqE(GEN a4, GEN a6, GEN T, ulong p);
 /* FpE.c */
 
 long    Fl_elltrace(ulong a4, ulong a6, ulong p);
-GEN     Fle_add(GEN P, GEN Q, ulong a4, ulong p);
-GEN     Fle_dbl(GEN P, ulong a4, ulong p);
-GEN     Fle_mul(GEN P, GEN n, ulong a4, ulong p);
-GEN     Fle_mulu(GEN P, ulong n, ulong a4, ulong p);
-GEN     Fle_order(GEN z, GEN o, ulong a4, ulong p);
-GEN     Fle_sub(GEN P, GEN Q, ulong a4, ulong p);
+long    Fl_elltrace_CM(long CM, ulong a4, ulong a6, ulong p);
 GEN     Fp_ellcard(GEN a4, GEN a6, GEN p);
 GEN     Fp_elldivpol(GEN a4, GEN a6, long n, GEN p);
 GEN     Fp_ellgens(GEN a4, GEN a6, GEN ch, GEN D, GEN m, GEN p);
 GEN     Fp_ellgroup(GEN a4, GEN a6, GEN N, GEN p, GEN *pt_m);
 GEN     Fp_ellj(GEN a4, GEN a6, GEN p);
+int     Fp_elljissupersingular(GEN j, GEN p);
 GEN     Fp_ffellcard(GEN a4, GEN a6, GEN q, long n, GEN p);
 GEN     FpE_add(GEN P, GEN Q, GEN a4, GEN p);
 GEN     FpE_changepoint(GEN x, GEN ch, GEN p);
@@ -374,6 +430,7 @@ GEN     FpXQ_elldivpol(GEN a4, GEN a6, long n, GEN T, GEN p);
 GEN     FpXQ_ellgens(GEN a4, GEN a6, GEN ch, GEN D, GEN m, GEN T, GEN p);
 GEN     FpXQ_ellgroup(GEN a4, GEN a6, GEN N, GEN T, GEN p, GEN *pt_m);
 GEN     FpXQ_ellj(GEN a4, GEN a6, GEN T, GEN p);
+int     FpXQ_elljissupersingular(GEN j, GEN T, GEN p);
 GEN     FpXQE_add(GEN P, GEN Q, GEN a4, GEN T, GEN p);
 GEN     FpXQE_changepoint(GEN x, GEN ch, GEN T, GEN p);
 GEN     FpXQE_changepointinv(GEN x, GEN ch, GEN T, GEN p);
@@ -391,7 +448,6 @@ GEN     RgE_to_FpXQE(GEN x, GEN T, GEN p);
 const struct bb_group * get_FpE_group(void **E, GEN a4, GEN a6, GEN p);
 const struct bb_group * get_FpXQE_group(void **E, GEN a4, GEN a6, GEN T, GEN p);
 GEN     elltrace_extension(GEN t, long n, GEN p);
-GEN     random_Fle(ulong a4, ulong a6, ulong p);
 GEN     random_FpE(GEN a4, GEN a6, GEN p);
 GEN     random_FpXQE(GEN a4, GEN a6, GEN T, GEN p);
 
@@ -411,25 +467,31 @@ GEN     FpX_Fp_sub(GEN x, GEN y, GEN p);
 GEN     FpX_Fp_sub_shallow(GEN y,GEN x,GEN p);
 GEN     FpX_FpXQ_eval(GEN f,GEN x,GEN T,GEN p);
 GEN     FpX_FpXQV_eval(GEN f,GEN x,GEN T,GEN p);
+GEN     FpX_Frobenius(GEN T, GEN p);
 GEN     FpX_add(GEN x, GEN y, GEN p);
 GEN     FpX_center(GEN x, GEN p, GEN pov2);
 GEN     FpX_chinese_coprime(GEN x,GEN y,GEN Tx,GEN Ty,GEN Tz,GEN p);
 GEN     FpX_deriv(GEN x, GEN p);
+GEN     FpX_digits(GEN x, GEN y, GEN p);
 GEN     FpX_disc(GEN x, GEN p);
 GEN     FpX_div_by_X_x(GEN a, GEN x, GEN p, GEN *r);
 GEN     FpX_divrem(GEN x, GEN y, GEN p, GEN *pr);
 GEN     FpX_eval(GEN x,GEN y,GEN p);
 GEN     FpX_extgcd(GEN x, GEN y, GEN p, GEN *ptu, GEN *ptv);
+GEN     FpX_fromdigits(GEN x, GEN T, GEN p);
 GEN     FpX_gcd(GEN x, GEN y, GEN p);
 GEN     FpX_get_red(GEN T, GEN p);
+GEN     FpX_halve(GEN y, GEN p);
 GEN     FpX_halfgcd(GEN x, GEN y, GEN p);
 GEN     FpX_invBarrett(GEN T, GEN p);
 int     FpX_is_squarefree(GEN f, GEN p);
+GEN     FpX_matFrobenius(GEN T, GEN p);
 GEN     FpX_mul(GEN x, GEN y, GEN p);
 GEN     FpX_mulspec(GEN a, GEN b, GEN p, long na, long nb);
 GEN     FpX_mulu(GEN x, ulong y, GEN p);
 GEN     FpX_neg(GEN x, GEN p);
 GEN     FpX_normalize(GEN z, GEN p);
+GEN     FpX_powu(GEN x, ulong n, GEN p);
 GEN     FpX_red(GEN z, GEN p);
 GEN     FpX_rem(GEN x, GEN y, GEN p);
 GEN     FpX_rescale(GEN P, GEN h, GEN p);
@@ -437,6 +499,8 @@ GEN     FpX_resultant(GEN a, GEN b, GEN p);
 GEN     FpX_sqr(GEN x, GEN p);
 GEN     FpX_sub(GEN x, GEN y, GEN p);
 long    FpX_valrem(GEN x0, GEN t, GEN p, GEN *py);
+GEN     FpXC_FpXQV_eval(GEN Q, GEN x, GEN T, GEN p);
+GEN     FpXM_FpXQV_eval(GEN Q, GEN x, GEN T, GEN p);
 GEN     FpXQ_autpow(GEN x, ulong n, GEN T, GEN p);
 GEN     FpXQ_autpowers(GEN aut, long f, GEN T, GEN p);
 GEN     FpXQ_autsum(GEN x, ulong n, GEN T, GEN p);
@@ -461,10 +525,12 @@ GEN     FpXQ_sqrt(GEN a, GEN T, GEN p);
 GEN     FpXQ_sqrtn(GEN a, GEN n, GEN T, GEN p, GEN *zetan);
 GEN     FpXQ_trace(GEN x, GEN T, GEN p);
 GEN     FpXQC_to_mod(GEN z, GEN T, GEN p);
+GEN     FpXQM_autsum(GEN x, ulong n, GEN T, GEN p);
 GEN     FpXT_red(GEN z, GEN p);
 GEN     FpXV_prod(GEN V, GEN p);
 GEN     FpXV_red(GEN z, GEN p);
 int     Fq_issquare(GEN x, GEN T, GEN p);
+GEN     Fq_log(GEN a, GEN g, GEN ord, GEN T, GEN p);
 GEN     FqV_inv(GEN x, GEN T, GEN p);
 GEN     Z_to_FpX(GEN a, GEN p, long v);
 GEN     gener_FpXQ(GEN T, GEN p, GEN *o);
@@ -488,6 +554,7 @@ long    Flx_nbfact(GEN z, ulong p);
 GEN     Flx_nbfact_by_degree(GEN z, long *nb, ulong p);
 long    Flx_nbroots(GEN f, ulong p);
 ulong   Flx_oneroot(GEN f, ulong p);
+ulong   Flx_oneroot_split(GEN f, ulong p);
 GEN     Flx_roots(GEN f, ulong p);
 GEN     FlxqX_Frobenius(GEN S, GEN T, ulong p);
 GEN     FlxqXQ_halfFrobenius(GEN a, GEN S, GEN T, ulong p);
@@ -503,6 +570,7 @@ long    FpX_nbroots(GEN f, GEN p);
 GEN     FpX_oneroot(GEN f, GEN p);
 GEN     FpX_roots(GEN f, GEN p);
 GEN     FpX_rootsff(GEN P, GEN T, GEN p);
+GEN     FpX_split_part(GEN f, GEN p);
 GEN     FpXQX_Frobenius(GEN S, GEN T, GEN p);
 long    FpXQX_nbfact(GEN u, GEN T, GEN p);
 long    FpXQX_nbroots(GEN f, GEN T, GEN p);
@@ -524,12 +592,16 @@ GEN     rootmod0(GEN f, GEN p,long flag);
 GEN     FpXQX_FpXQ_mul(GEN P, GEN U, GEN T, GEN p);
 GEN     FpXQX_FpXQXQV_eval(GEN P, GEN V, GEN S, GEN T, GEN p);
 GEN     FpXQX_FpXQXQ_eval(GEN P, GEN x, GEN S, GEN T, GEN p);
+GEN     FpXQX_div_by_X_x(GEN a, GEN x, GEN T, GEN p, GEN *pr);
 GEN     FpXQX_divrem(GEN x, GEN y, GEN T, GEN p, GEN *pr);
 GEN     FpXQX_divrem_Barrett(GEN x, GEN B, GEN S, GEN T, GEN p, GEN *pr);
+GEN     FpXQX_digits(GEN x, GEN B, GEN T, GEN p);
 GEN     FpXQX_extgcd(GEN x, GEN y, GEN T, GEN p, GEN *ptu, GEN *ptv);
+GEN     FpXQX_fromdigits(GEN x, GEN B, GEN T, GEN p);
 GEN     FpXQX_gcd(GEN P, GEN Q, GEN T, GEN p);
 GEN     FpXQX_invBarrett(GEN S, GEN T, GEN p);
 GEN     FpXQX_mul(GEN x, GEN y, GEN T, GEN p);
+GEN     FpXQX_powu(GEN x, ulong n, GEN T, GEN p);
 GEN     FpXQX_red(GEN z, GEN T, GEN p);
 GEN     FpXQX_rem(GEN x, GEN S, GEN T, GEN p);
 GEN     FpXQX_rem_Barrett(GEN x, GEN mg, GEN S, GEN T, GEN p);
@@ -553,6 +625,7 @@ GEN     FpXX_neg(GEN x, GEN p);
 GEN     FpXX_red(GEN z, GEN p);
 GEN     FpXX_sub(GEN x, GEN y, GEN p);
 GEN     FpXY_FpXQ_evalx(GEN P, GEN x, GEN T, GEN p);
+GEN     FpXY_FpXQV_evalx(GEN P, GEN x, GEN T, GEN p);
 GEN     FpXY_eval(GEN Q, GEN y, GEN x, GEN p);
 GEN     FpXY_evalx(GEN Q, GEN x, GEN p);
 GEN     FpXY_evaly(GEN Q, GEN y, GEN p, long vy);
@@ -560,6 +633,7 @@ GEN     FpXYQQ_pow(GEN x, GEN n, GEN S, GEN T, GEN p);
 GEN     Kronecker_to_FpXQX(GEN z, GEN pol, GEN p);
 GEN     Kronecker_to_ZXX(GEN z, long N, long v);
 GEN     ZXX_mul_Kronecker(GEN x, GEN y, long n);
+GEN     ZXX_sqr_Kronecker(GEN x, long n);
 
 /* FpV.c */
 
@@ -576,6 +650,8 @@ GEN     Flm_Fl_add(GEN x, ulong y, ulong p);
 GEN     Flm_Fl_mul(GEN y, ulong x, ulong p);
 void    Flm_Fl_mul_inplace(GEN y, ulong x, ulong p);
 GEN     Flm_Flc_mul(GEN x, GEN y, ulong p);
+GEN     Flm_Flc_mul_pre(GEN x, GEN y, ulong p, ulong pi);
+GEN     Flm_add(GEN x, GEN y, ulong p);
 GEN     Flm_center(GEN z, ulong p, ulong ps2);
 GEN     Flm_mul(GEN x, GEN y, ulong p);
 GEN     Flm_neg(GEN y, ulong p);
@@ -585,6 +661,7 @@ GEN     Flm_transpose(GEN x);
 GEN     Flv_add(GEN x, GEN y, ulong p);
 void    Flv_add_inplace(GEN x, GEN y, ulong p);
 ulong   Flv_dotproduct(GEN x, GEN y, ulong p);
+ulong   Flv_dotproduct_pre(GEN x, GEN y, ulong p, ulong pi);
 GEN     Flv_center(GEN z, ulong p, ulong ps2);
 GEN     Flv_sub(GEN x, GEN y, ulong p);
 void    Flv_sub_inplace(GEN x, GEN y, ulong p);
@@ -593,11 +670,15 @@ GEN     Fp_to_mod(GEN z, GEN p);
 GEN     FpC_FpV_mul(GEN x, GEN y, GEN p);
 GEN     FpC_Fp_mul(GEN x, GEN y, GEN p);
 GEN     FpC_center(GEN z, GEN p, GEN pov2);
+void    FpC_center_inplace(GEN z, GEN p, GEN pov2);
 GEN     FpC_red(GEN z, GEN p);
 GEN     FpC_to_mod(GEN z, GEN p);
+GEN     FpM_add(GEN x, GEN y, GEN p);
+GEN     FpM_Fp_mul(GEN X, GEN c, GEN p);
 GEN     FpM_FpC_mul(GEN x, GEN y, GEN p);
 GEN     FpM_FpC_mul_FpX(GEN x, GEN y, GEN p, long v);
 GEN     FpM_center(GEN z, GEN p, GEN pov2);
+void    FpM_center_inplace(GEN z, GEN p, GEN pov2);
 GEN     FpM_mul(GEN x, GEN y, GEN p);
 GEN     FpM_powu(GEN x, ulong n, GEN p);
 GEN     FpM_red(GEN z, GEN p);
@@ -630,18 +711,27 @@ GEN     scalar_Flm(long s, long n);
 GEN     zCs_to_ZC(GEN C, long nbrow);
 GEN     zMs_to_ZM(GEN M, long nbrow);
 GEN     zMs_ZC_mul(GEN M, GEN B);
+GEN     ZMV_to_FlmV(GEN z, ulong m);
 
 /* Hensel.c */
 
+GEN     Zp_sqrt(GEN x, GEN p, long e);
 GEN     Zp_sqrtlift(GEN b, GEN a, GEN p, long e);
 GEN     Zp_sqrtnlift(GEN b, GEN n, GEN a, GEN p, long e);
+GEN     ZpX_Frobenius(GEN T, GEN p, long e);
+GEN     ZpX_ZpXQ_liftroot(GEN P, GEN S, GEN T, GEN p, long e);
+GEN     ZpX_ZpXQ_liftroot_ea(GEN P, GEN S, GEN T, GEN p, long n, void *E,
+                     int early(void *E, GEN x, GEN q));
 GEN     ZpX_liftfact(GEN pol, GEN Q, GEN T, GEN p, long e, GEN pe);
 GEN     ZpX_liftroot(GEN f, GEN a, GEN p, long e);
-GEN     ZpX_liftroots(GEN f, GEN S, GEN q, long e);
+GEN     ZpX_liftroots(GEN f, GEN S, GEN p, long e);
+GEN     ZpX_roots(GEN f, GEN p, long e);
 GEN     ZpXQ_inv(GEN a, GEN T, GEN p, long e);
 GEN     ZpXQ_invlift(GEN b, GEN a, GEN T, GEN p, long e);
 GEN     ZpXQ_log(GEN a, GEN T, GEN p, long N);
+GEN     ZpXQ_sqrt(GEN a, GEN T, GEN p, long e);
 GEN     ZpXQ_sqrtnlift(GEN b, GEN n, GEN a, GEN T, GEN p, long e);
+GEN     ZpXQM_prodFrobenius(GEN M, GEN T, GEN p, long e);
 GEN     ZpXQX_liftroot(GEN f, GEN a, GEN T, GEN p, long e);
 GEN     ZpXQX_liftroot_vald(GEN f, GEN a, long v, GEN T, GEN p, long e);
 GEN     gen_ZpX_Dixon(GEN F, GEN V, GEN q, GEN p, long N, void *E,
@@ -672,6 +762,7 @@ GEN     RgC_Rg_mul(GEN x, GEN y);
 GEN     RgC_RgM_mul(GEN x, GEN y);
 GEN     RgC_RgV_mul(GEN x, GEN y);
 GEN     RgC_add(GEN x, GEN y);
+long    RgC_is_ei(GEN x);
 GEN     RgC_neg(GEN x);
 GEN     RgC_sub(GEN x, GEN y);
 GEN     RgM_Rg_add(GEN x, GEN y);
@@ -694,6 +785,7 @@ GEN     RgM_neg(GEN x);
 GEN     RgM_powers(GEN x, long l);
 GEN     RgM_sqr(GEN x);
 GEN     RgM_sub(GEN x, GEN y);
+GEN     RgM_sumcol(GEN A);
 GEN     RgM_transmul(GEN x, GEN y);
 GEN     RgM_transmultosym(GEN x, GEN y);
 GEN     RgM_zc_mul(GEN x, GEN y);
@@ -734,34 +826,17 @@ GEN     QXQV_to_mod(GEN V, GEN T);
 GEN     QXQXV_to_mod(GEN V, GEN T);
 GEN     QXV_QXQ_eval(GEN v, GEN a, GEN T);
 GEN     QXX_QXQ_eval(GEN v, GEN a, GEN T);
-GEN     Rg_to_RgV(GEN x, long N);
+GEN     Rg_RgX_sub(GEN x, GEN y);
+GEN     Rg_to_RgC(GEN x, long N);
 GEN     RgM_to_RgXV(GEN x, long v);
 GEN     RgM_to_RgXX(GEN x, long v,long w);
 GEN     RgV_to_RgX(GEN x, long v);
 GEN     RgV_to_RgM(GEN v, long n);
 GEN     RgV_to_RgX_reverse(GEN x, long v);
-GEN     RgXQC_red(GEN P, GEN T);
-GEN     RgXQV_red(GEN P, GEN T);
-GEN     RgXQX_RgXQ_mul(GEN x, GEN y, GEN T);
-GEN     RgXQX_divrem(GEN x,GEN y,GEN T,GEN *r);
-GEN     RgXQX_mul(GEN x,GEN y,GEN T);
-GEN     RgXQX_pseudodivrem(GEN x, GEN y, GEN T, GEN *ptr);
-GEN     RgXQX_pseudorem(GEN x, GEN y, GEN T);
-GEN     RgXQX_red(GEN P, GEN T);
-GEN     RgXQX_sqr(GEN x, GEN T);
-GEN     RgXQX_translate(GEN P, GEN c, GEN T);
-GEN     RgXQ_matrix_pow(GEN y, long n, long m, GEN P);
-GEN     RgXQ_norm(GEN x, GEN T);
-GEN     RgXQ_pow(GEN x, GEN n, GEN T);
-GEN     RgXQ_powu(GEN x, ulong n, GEN T);
-GEN     RgXQ_powers(GEN x, long l, GEN T);
-GEN     RgXV_to_RgM(GEN v, long n);
-GEN     RgXV_unscale(GEN v, GEN h);
-GEN     RgXX_to_RgM(GEN v, long n);
-GEN     RgXY_swap(GEN x, long n, long w);
-GEN     RgXY_swapspec(GEN x, long n, long w, long nx);
 GEN     RgX_RgXQ_eval(GEN f, GEN x, GEN T);
 GEN     RgX_RgXQV_eval(GEN P, GEN V, GEN T);
+GEN     RgX_RgXn_eval(GEN Q, GEN x, long n);
+GEN     RgX_RgXnV_eval(GEN Q, GEN x, long n);
 GEN     RgX_Rg_add(GEN y, GEN x);
 GEN     RgX_Rg_add_shallow(GEN y, GEN x);
 GEN     RgX_Rg_div(GEN y, GEN x);
@@ -780,15 +855,13 @@ void    RgX_even_odd(GEN p, GEN *pe, GEN *po);
 GEN     RgX_get_0(GEN x);
 GEN     RgX_get_1(GEN x);
 GEN     RgX_inflate(GEN x0, long d);
-GEN     RgX_modXn_shallow(GEN a, long n);
-GEN     RgX_modXn_eval(GEN Q, GEN x, long n);
 GEN     RgX_mul(GEN x,GEN y);
 GEN     RgX_mul_normalized(GEN A, long a, GEN B, long b);
 GEN     RgX_mulXn(GEN x, long d);
-GEN     RgX_mullow(GEN f, GEN g, long n);
 GEN     RgX_muls(GEN y, long x);
 GEN     RgX_mulspec(GEN a, GEN b, long na, long nb);
 GEN     RgX_neg(GEN x);
+GEN     RgX_normalize(GEN x);
 GEN     RgX_pseudodivrem(GEN x, GEN y, GEN *ptr);
 GEN     RgX_pseudorem(GEN x, GEN y);
 GEN     RgX_recip(GEN x);
@@ -800,14 +873,44 @@ GEN     RgX_shift(GEN a, long n);
 GEN     RgX_shift_shallow(GEN x, long n);
 GEN     RgX_splitting(GEN p, long k);
 GEN     RgX_sqr(GEN x);
-GEN     RgX_sqrlow(GEN f, long n);
 GEN     RgX_sqrspec(GEN a, long na);
 GEN     RgX_sub(GEN x, GEN y);
-GEN     RgX_to_RgV(GEN x, long N);
+GEN     RgX_to_RgC(GEN x, long N);
 GEN     RgX_translate(GEN P, GEN c);
 GEN     RgX_unscale(GEN P, GEN h);
-GEN     Rg_RgX_sub(GEN x, GEN y);
+GEN     RgXQ_matrix_pow(GEN y, long n, long m, GEN P);
+GEN     RgXQ_norm(GEN x, GEN T);
+GEN     RgXQ_pow(GEN x, GEN n, GEN T);
+GEN     RgXQ_powers(GEN x, long l, GEN T);
+GEN     RgXQ_powu(GEN x, ulong n, GEN T);
+GEN     RgXQC_red(GEN P, GEN T);
+GEN     RgXQV_RgXQ_mul(GEN v, GEN x, GEN T);
+GEN     RgXQV_red(GEN P, GEN T);
+GEN     RgXQX_RgXQ_mul(GEN x, GEN y, GEN T);
+GEN     RgXQX_divrem(GEN x,GEN y,GEN T,GEN *r);
+GEN     RgXQX_mul(GEN x,GEN y,GEN T);
+GEN     RgXQX_pseudodivrem(GEN x, GEN y, GEN T, GEN *ptr);
+GEN     RgXQX_pseudorem(GEN x, GEN y, GEN T);
+GEN     RgXQX_red(GEN P, GEN T);
+GEN     RgXQX_sqr(GEN x, GEN T);
+GEN     RgXQX_translate(GEN P, GEN c, GEN T);
+GEN     RgXV_to_RgM(GEN v, long n);
+GEN     RgXV_unscale(GEN v, GEN h);
+GEN     RgXX_to_RgM(GEN v, long n);
+long    RgXY_degreex(GEN bpol);
+GEN     RgXY_swap(GEN x, long n, long w);
+GEN     RgXY_swapspec(GEN x, long n, long w, long nx);
+GEN     RgXn_eval(GEN Q, GEN x, long n);
+GEN     RgXn_exp(GEN f, long e);
+GEN     RgXn_inv(GEN f, long e);
+GEN     RgXn_mul(GEN f, GEN g, long n);
+GEN     RgXn_powers(GEN f, long m, long n);
+GEN     RgXn_red_shallow(GEN a, long n);
+GEN     RgXn_reverse(GEN f, long e);
+GEN     RgXn_sqr(GEN f, long n);
+GEN     RgXnV_red_shallow(GEN P, long n);
 GEN     ZX_translate(GEN P, GEN c);
+GEN     ZX_unscale2n(GEN P, long n);
 GEN     ZX_unscale(GEN P, GEN h);
 GEN     ZX_unscale_div(GEN P, GEN h);
 int     ZXQX_dvd(GEN x, GEN y, GEN T);
@@ -817,11 +920,25 @@ GEN     gen_bkeval(GEN Q, long d, GEN x, int use_sqr, void *E,
 GEN     gen_bkeval_powers(GEN P, long d, GEN V, void *E,
           const struct bb_algebra *ff, GEN cmul(void *E, GEN P, long a, GEN x));
 
+/* ZG.c */
+GEN     G_ZGC_mul(GEN x, GEN v);
+GEN     G_ZG_mul(GEN x, GEN y);
+GEN     ZGC_G_mul(GEN v, GEN x);
+GEN     ZGC_Z_mul(GEN v, GEN x);
+GEN     ZG_G_mul(GEN x, GEN y);
+GEN     ZG_Z_mul(GEN x, GEN c);
+GEN     ZG_add(GEN x, GEN y);
+GEN     ZG_mul(GEN x, GEN y);
+GEN     ZG_neg(GEN x);
+GEN     ZG_normalize(GEN x);
+GEN     ZG_sub(GEN x, GEN y);
+
 /* ZV.c */
 
 void    Flc_lincomb1_inplace(GEN X, GEN Y, ulong v, ulong q);
 void    RgM_check_ZM(GEN A, const char *s);
 void    RgV_check_ZV(GEN A, const char *s);
+GEN     ZV_zc_mul(GEN x, GEN y);
 GEN     ZC_ZV_mul(GEN x, GEN y);
 GEN     ZC_Z_add(GEN x, GEN y);
 GEN     ZC_Z_divexact(GEN X, GEN c);
@@ -830,6 +947,7 @@ GEN     ZC_Z_sub(GEN x, GEN y);
 GEN     ZC_add(GEN x, GEN y);
 GEN     ZC_copy(GEN x);
 GEN     ZC_hnfremdiv(GEN x, GEN y, GEN *Q);
+long    ZC_is_ei(GEN x);
 GEN     ZC_lincomb(GEN u, GEN v, GEN X, GEN Y);
 void    ZC_lincomb1_inplace(GEN X, GEN Y, GEN v);
 GEN     ZC_neg(GEN M);
@@ -838,6 +956,7 @@ GEN     ZC_reducemodmatrix(GEN v, GEN y);
 GEN     ZC_sub(GEN x, GEN y);
 GEN     ZC_z_mul(GEN X, long c);
 GEN     ZM_ZC_mul(GEN x, GEN y);
+GEN     ZM_Z_div(GEN X, GEN c);
 GEN     ZM_Z_divexact(GEN X, GEN c);
 GEN     ZM_Z_mul(GEN X, GEN c);
 GEN     ZM_add(GEN x, GEN y);
@@ -856,10 +975,12 @@ GEN     ZM_pow(GEN x, GEN n);
 GEN     ZM_powu(GEN x, ulong n);
 GEN     ZM_reducemodlll(GEN x,GEN y);
 GEN     ZM_reducemodmatrix(GEN v, GEN y);
+GEN     ZM_sqr(GEN x);
 GEN     ZM_sub(GEN x, GEN y);
 GEN     ZM_supnorm(GEN x);
 GEN     ZM_to_Flm(GEN x, ulong p);
 GEN     ZM_to_zm(GEN z);
+GEN     ZM_transmul(GEN x, GEN y);
 GEN     ZM_transmultosym(GEN x, GEN y);
 GEN     ZMV_to_zmV(GEN z);
 void    ZM_togglesign(GEN M);
@@ -915,6 +1036,7 @@ GEN     ZX_Z_sub(GEN y, GEN x);
 GEN     ZX_add(GEN x, GEN y);
 GEN     ZX_copy(GEN x);
 GEN     ZX_deriv(GEN x);
+GEN     ZX_div_by_X_1(GEN a, GEN *r);
 int     ZX_equal(GEN V, GEN W);
 GEN     ZX_eval1(GEN x);
 long    ZX_max_lg(GEN x);
@@ -925,6 +1047,7 @@ GEN     ZX_mulu(GEN y, ulong x);
 GEN     ZX_neg(GEN x);
 GEN     ZX_rem(GEN x, GEN y);
 GEN     ZX_remi2n(GEN y, long n);
+GEN     ZX_rescale2n(GEN P, long n);
 GEN     ZX_rescale(GEN P, GEN h);
 GEN     ZX_rescale_lt(GEN P);
 GEN     ZX_shifti(GEN x, long n);
@@ -939,6 +1062,8 @@ GEN     ZXV_dotproduct(GEN V, GEN W);
 int     ZXV_equal(GEN V, GEN W);
 GEN     ZXV_remi2n(GEN x, long n);
 GEN     ZXX_Z_divexact(GEN y, GEN x);
+GEN     ZXX_Z_mul(GEN y, GEN x);
+GEN     ZXX_Z_add_shallow(GEN x, GEN y);
 long    ZXX_max_lg(GEN x);
 GEN     ZXX_renormalize(GEN x, long lx);
 GEN     ZXX_to_Kronecker(GEN P, long n);
@@ -947,6 +1072,121 @@ GEN     scalar_ZX(GEN x, long v);
 GEN     scalar_ZX_shallow(GEN x, long v);
 GEN     zx_to_ZX(GEN z);
 
+/* algebras.c */
+
+GEN alg_centralproj(GEN al, GEN z, int maps);
+GEN alg_change_overorder_shallow(GEN al, GEN ord);
+GEN alg_complete(GEN rnf, GEN aut, GEN hi, GEN hf, int maxord);
+GEN alg_csa_table(GEN nf, GEN mt, long v, int maxord);
+GEN alg_cyclic(GEN rnf, GEN aut, GEN b, int maxord);
+GEN alg_decomposition(GEN al);
+long alg_get_absdim(GEN al);
+long algabsdim(GEN al);
+GEN alg_get_abssplitting(GEN al);
+GEN alg_get_aut(GEN al);
+GEN algaut(GEN al);
+GEN alg_get_auts(GEN al);
+GEN alg_get_b(GEN al);
+GEN algb(GEN al);
+GEN alg_get_center(GEN al);
+GEN alggetcenter(GEN al);
+GEN alg_get_char(GEN al);
+GEN algchar(GEN al);
+long alg_get_degree(GEN al);
+long algdegree(GEN al);
+long alg_get_dim(GEN al);
+long algdim(GEN al);
+GEN alg_get_hasse_f(GEN al);
+GEN alghassef(GEN al);
+GEN alg_get_hasse_i(GEN al);
+GEN alghassei(GEN al);
+GEN alg_get_invord(GEN al);
+GEN alginvbasis(GEN al);
+GEN alg_get_multable(GEN al);
+GEN alggetmultable(GEN al);
+GEN alg_get_ord(GEN al);
+GEN algbasis(GEN al);
+GEN alg_get_relmultable(GEN al);
+GEN algrelmultable(GEN al);
+GEN alg_get_splitpol(GEN al);
+GEN alg_get_splitting(GEN al);
+GEN algsplittingfield(GEN al);
+GEN alg_get_splittingbasis(GEN al);
+GEN alg_get_splittingbasisinv(GEN al);
+GEN alg_get_splittingdata(GEN al);
+GEN algsplittingdata(GEN al);
+GEN alg_get_tracebasis(GEN al);
+GEN alg_hasse(GEN nf, long n, GEN hi, GEN hf, long var, long flag);
+GEN alg_hilbert(GEN nf, GEN a, GEN b, long v, long flag);
+GEN alg_matrix(GEN nf, long n, long v, GEN L, long flag);
+long alg_model(GEN al, GEN x);
+GEN alg_ordermodp(GEN al, GEN p);
+GEN alg_quotient(GEN al, GEN I, int maps);
+GEN algradical(GEN al);
+GEN algsimpledec(GEN al, int maps);
+GEN algsubalg(GEN al, GEN basis);
+long alg_type(GEN al);
+GEN algadd(GEN al, GEN x, GEN y);
+GEN algalgtobasis(GEN al, GEN x);
+GEN algbasischarpoly(GEN al, GEN x, long v);
+GEN algbasismul(GEN al, GEN x, GEN y);
+GEN algbasismultable(GEN al, GEN x);
+GEN algbasismultable_Flm(GEN mt, GEN x, ulong m);
+GEN algbasistoalg(GEN al, GEN x);
+GEN algcenter(GEN al);
+GEN algcharpoly(GEN al, GEN x, long v);
+GEN algdisc(GEN al);
+GEN algdivl(GEN al, GEN x, GEN y);
+GEN algdivr(GEN al, GEN x, GEN y);
+GEN alghasse(GEN al, GEN pl);
+GEN alginit(GEN A, GEN B, long v, long flag);
+long algindex(GEN al, GEN pl);
+GEN alginv(GEN al, GEN x);
+int algisassociative(GEN mt0, GEN p);
+int algiscommutative(GEN al);
+int algisdivision(GEN al, GEN pl);
+int algisramified(GEN al, GEN pl);
+int algissemisimple(GEN al);
+int algissimple(GEN al, long ss);
+int algissplit(GEN al, GEN pl);
+int algisdivl(GEN al, GEN x, GEN y, GEN* ptz);
+int algisinv(GEN al, GEN x, GEN* ptix);
+GEN algleftordermodp(GEN al, GEN Ip, GEN p);
+GEN algmul(GEN al, GEN x, GEN y);
+GEN algmultable(GEN al, GEN x);
+GEN algneg(GEN al, GEN x);
+GEN algnorm(GEN al, GEN x);
+GEN algpoleval(GEN al, GEN pol, GEN x);
+GEN algpow(GEN al, GEN x, GEN n);
+GEN algprimesubalg(GEN al);
+GEN algramifiedplaces(GEN al);
+GEN algrandom(GEN al, GEN b);
+GEN algsplittingmatrix(GEN al, GEN x);
+GEN algsqr(GEN al, GEN x);
+GEN algsub(GEN al, GEN x, GEN y);
+GEN algtableinit(GEN mt, GEN p);
+GEN algtensor(GEN al1, GEN al2, int maxord);
+GEN algtrace(GEN al, GEN x);
+long algtype(GEN al);
+GEN bnfgwgeneric(GEN bnf, GEN Lpr, GEN Ld, GEN pl, long var);
+GEN bnrconj(GEN bnr, long i);
+GEN bnrgwsearch(GEN bnr, GEN Lpr, GEN Ld, GEN pl);
+void checkalg(GEN x);
+void checkhasse(GEN nf, GEN hi, GEN hf, long n);
+long cyclicrelfrob(GEN rnf, GEN nf2, GEN auts, GEN pr);
+GEN gp_algcenter(GEN al);
+GEN gp_algmultable(GEN al, GEN x);
+GEN hassecoprime(GEN hi, GEN hf, long n);
+GEN hassedown(GEN nf, long n, GEN hi, GEN hf);
+GEN hassewedderburn(GEN hi, GEN hf, long n);
+long localhasse(GEN rnf, GEN nf2, GEN cnd, GEN pl, GEN auts, GEN b, long k);
+GEN nfgrunwaldwang(GEN nf0, GEN Lpr, GEN Ld, GEN pl, long var);
+GEN nfgwkummer(GEN nf, GEN Lpr, GEN Ld, GEN pl, long var);
+/*to be moved elsewhere*/
+GEN extchinese(GEN nf, GEN x, GEN y, GEN pl, GEN* red);
+GEN factoredextchinese(GEN nf, GEN x, GEN y, GEN pl, GEN* fa);
+GEN factoredextchinesetest(GEN nf, GEN x, GEN y, GEN pl, GEN* fa, GEN data, int (*test)(GEN,GEN,GEN));
+
 /* alglin1.c */
 
 GEN     F2m_F2c_gauss(GEN a, GEN b);
@@ -1033,6 +1273,7 @@ GEN     ZM_detmult(GEN A);
 GEN     ZM_gauss(GEN a, GEN b);
 GEN     ZM_imagecompl(GEN x);
 GEN     ZM_indeximage(GEN x);
+GEN     ZM_indexrank(GEN x);
 GEN     ZM_inv(GEN M, GEN dM);
 long    ZM_rank(GEN x);
 GEN     ZlM_gauss(GEN a, GEN b, ulong p, long e, GEN C);
@@ -1071,14 +1312,17 @@ GEN     suppl(GEN x);
 
 /* alglin2.c */
 
+GEN     Flm_charpoly(GEN x, ulong p);
+GEN     Flm_hess(GEN x, ulong p);
 GEN     FpM_charpoly(GEN x, GEN p);
 GEN     FpM_hess(GEN x, GEN p);
-GEN     Flm_charpoly(GEN x, long p);
-GEN     Flm_hess(GEN x, ulong p);
+GEN     Frobeniusform(GEN V, long n);
 GEN     QM_minors_coprime(GEN x, GEN pp);
 GEN     QM_ImZ_hnf(GEN x);
 GEN     QM_ImQ_hnf(GEN x);
-GEN     gnorml1_fake(GEN x);
+GEN     QM_charpoly_ZX(GEN M);
+GEN     QM_charpoly_ZX_bound(GEN M, long bit);
+GEN     QM_charpoly_ZX2_bound(GEN M, GEN M2, long bit);
 GEN     ZM_charpoly(GEN x);
 GEN     adj(GEN x);
 GEN     adjsafe(GEN x);
@@ -1090,6 +1334,7 @@ GEN     charpoly(GEN x, long v);
 GEN     charpoly0(GEN x, long v,long flag);
 GEN     gnorm(GEN x);
 GEN     gnorml1(GEN x,long prec);
+GEN     gnorml1_fake(GEN x);
 GEN     gnormlp(GEN x, GEN p, long prec);
 GEN     gnorml2(GEN x);
 GEN     gsupnorm(GEN x, long prec);
@@ -1112,7 +1357,9 @@ GEN     apply0(GEN f, GEN A);
 GEN     diagonal(GEN x);
 GEN     diagonal_shallow(GEN x);
 GEN     extract0(GEN x, GEN l1, GEN l2);
+GEN     fold0(GEN f, GEN A);
 GEN     genapply(void *E, GEN (*f)(void *E, GEN x), GEN A);
+GEN     genfold(void *E, GEN (*f)(void *E, GEN x, GEN y), GEN A);
 GEN     genindexselect(void *E, long (*f)(void *E, GEN x), GEN A);
 GEN     genselect(void *E, long (*f)(void *E, GEN x), GEN A);
 GEN     gtomat(GEN x);
@@ -1121,6 +1368,8 @@ GEN     matmuldiagonal(GEN x, GEN d);
 GEN     matmultodiagonal(GEN x, GEN y);
 GEN     matslice0(GEN A, long x1, long x2, long y1, long y2);
 GEN     parapply(GEN V, GEN C);
+void    parfor(GEN a, GEN b, GEN code, void *E, long call(void*, GEN, GEN));
+void    parforprime(GEN a, GEN b, GEN code, void *E, long call(void*, GEN, GEN));
 GEN     parselect(GEN C, GEN D, long flag);
 GEN     select0(GEN A, GEN f, long flag);
 GEN     shallowextract(GEN x, GEN L);
@@ -1144,19 +1393,19 @@ void    alias0(const char *s, const char *old);
 GEN     compile_str(const char *s);
 GEN     chartoGENstr(char c);
 long    delete_var(void);
-entree* fetch_named_var(const char *s);
 long    fetch_user_var(const char *s);
 long    fetch_var(void);
+long    fetch_var_higher(void);
 GEN     fetch_var_value(long vx, GEN t);
 GEN     gp_read_str(const char *t);
 entree* install(void *f, const char *name, const char *code);
 entree* is_entry(const char *s);
 void    kill0(const char *e);
-long    manage_var(long n, entree *ep);
+void    pari_var_close(void);
 void    pari_var_init(void);
 long    pari_var_next(void);
 long    pari_var_next_temp(void);
-void    pari_var_create(entree *ep);
+long    pari_var_create(entree *ep);
 void    name_var(long n, const char *s);
 GEN     readseq(char *t);
 GEN*    safegel(GEN x, long l);
@@ -1168,6 +1417,8 @@ GEN     strtoGENstr(const char *s);
 GEN     strtoi(const char *s);
 GEN     strtor(const char *s, long prec);
 GEN     type0(GEN x);
+GEN     varhigher(const char *s, long v);
+GEN     varlower(const char *s, long v);
 
 /* aprcl.c */
 
@@ -1189,6 +1440,7 @@ GEN     primeform_u(GEN x, ulong p);
 GEN     qfbcompraw(GEN x, GEN y);
 GEN     qfbpowraw(GEN x, long n);
 GEN     qfbred0(GEN x, long flag, GEN D, GEN isqrtD, GEN sqrtD);
+GEN     qfbredsl2(GEN q, GEN S);
 GEN     qfbsolve(GEN Q, GEN n);
 GEN     qfi(GEN x, GEN y, GEN z);
 GEN     qfi_1(GEN x);
@@ -1232,17 +1484,25 @@ GEN     rhorealnod(GEN x, GEN isqrtD);
 /* arith1.c */
 
 ulong   Fl_order(ulong a, ulong o, ulong p);
+GEN     Fl_powers(ulong x, long n, ulong p);
+GEN     Fl_powers_pre(ulong x, long n, ulong p, ulong pi);
 ulong   Fl_powu(ulong x, ulong n, ulong p);
+ulong   Fl_powu_pre(ulong x, ulong n, ulong p, ulong pi);
 ulong   Fl_sqrt(ulong a, ulong p);
+ulong   Fl_sqrt_pre(ulong a, ulong p, ulong pi);
+ulong   Fl_sqrtl(ulong a, ulong l, ulong p);
+ulong   Fl_sqrtl_pre(ulong a, ulong l, ulong p, ulong pi);
 GEN     Fp_factored_order(GEN a, GEN o, GEN p);
 int     Fp_ispower(GEN x, GEN K, GEN p);
 GEN     Fp_log(GEN a, GEN g, GEN ord, GEN p);
 GEN     Fp_order(GEN a, GEN o, GEN p);
 GEN     Fp_pow(GEN a, GEN n, GEN m);
+GEN     Fp_powers(GEN x, long n, GEN p);
 GEN     Fp_pows(GEN A, long k, GEN N);
 GEN     Fp_powu(GEN x, ulong k, GEN p);
 GEN     Fp_sqrt(GEN a, GEN p);
 GEN     Fp_sqrtn(GEN a, GEN n, GEN p, GEN *zetan);
+GEN     Z_ZV_mod(GEN P, GEN xa);
 GEN     Z_chinese(GEN a, GEN b, GEN A, GEN B);
 GEN     Z_chinese_all(GEN a, GEN b, GEN A, GEN B, GEN *pC);
 GEN     Z_chinese_coprime(GEN a, GEN b, GEN A, GEN B, GEN C);
@@ -1254,6 +1514,12 @@ long    Z_isfundamental(GEN x);
 long    Z_ispow2(GEN x);
 long    Z_ispowerall(GEN x, ulong k, GEN *pt);
 long    Z_issquareall(GEN x, GEN *pt);
+GEN     Z_nv_mod(GEN P, GEN xa);
+GEN     ZV_allpnqn(GEN x);
+GEN     ZV_chinese(GEN A, GEN P, GEN *pt_mod);
+GEN     ZV_chinese_tree(GEN A, GEN P, GEN tree, GEN *pt_mod);
+GEN     ZV_producttree(GEN xa);
+GEN     ZX_nv_mod_tree(GEN P, GEN xa, GEN T);
 long    Zp_issquare(GEN a, GEN p);
 GEN     bestappr(GEN x, GEN k);
 GEN     bestapprPade(GEN x, long B);
@@ -1287,6 +1553,7 @@ long    isfundamental(GEN x);
 long    ispolygonal(GEN x, GEN S, GEN *N);
 long    ispower(GEN x, GEN k, GEN *pty);
 long    isprimepower(GEN x, GEN *pty);
+long    ispseudoprimepower(GEN n, GEN *pt);
 long    issquare(GEN x);
 long    issquareall(GEN x, GEN *pt);
 long    krois(GEN x, long y);
@@ -1294,12 +1561,14 @@ long    kroiu(GEN x, ulong y);
 long    kronecker(GEN x, GEN y);
 long    krosi(long s, GEN x);
 long    kross(long x, long y);
+long    kroui(ulong x, GEN y);
 long    krouu(ulong x, ulong y);
 GEN     lcmii(GEN a, GEN b);
 long    logint(GEN B, GEN y, GEN *ptq);
 long    logint0(GEN B, GEN y, GEN *ptq);
 GEN     mpfact(long n);
 GEN     mulu_interval(ulong a, ulong b);
+GEN     nmV_chinese(GEN A, GEN P, GEN *pt_mod);
 GEN     odd_prime_divisors(GEN q);
 GEN     order(GEN x);
 GEN     pnqn(GEN x);
@@ -1337,12 +1606,18 @@ GEN     core2partial(GEN n, long l);
 GEN     coredisc(GEN n);
 GEN     coredisc0(GEN n,long flag);
 GEN     coredisc2(GEN n);
+long    corediscs(long D, ulong *f);
 GEN     digits(GEN N, GEN B);
 GEN     divisors(GEN n);
 GEN     divisorsu(ulong n);
 GEN     factor_pn_1(GEN p, ulong n);
 GEN     factor_pn_1_limit(GEN p, long n, ulong lim);
 GEN     factoru_pow(ulong n);
+GEN     fromdigits(GEN x, GEN B);
+GEN     fuse_Z_factor(GEN f, GEN B);
+GEN     gen_digits(GEN x, GEN B, long n, void *E, struct bb_ring *r,
+                          GEN (*div)(void *E, GEN x, GEN y, GEN *r));
+GEN     gen_fromdigits(GEN x, GEN B, void *E, struct bb_ring *r);
 byteptr initprimes(ulong maxnum, long *lenp, ulong *lastp);
 void    initprimetable(ulong maxnum);
 ulong   init_primepointer_geq(ulong a, byteptr *pd);
@@ -1355,6 +1630,7 @@ int     is_Z_factorpos(GEN f);
 ulong   maxprime(void);
 void    maxprime_check(ulong c);
 GEN     sumdigits(GEN n);
+GEN     sumdigits0(GEN n, GEN B);
 ulong   sumdigitsu(ulong n);
 
 /* DedekZeta.c */
@@ -1410,7 +1686,7 @@ long    nftyp(GEN x);
 GEN     polredord(GEN x);
 GEN     polgalois(GEN x, long prec);
 GEN     polred(GEN x);
-GEN     polred0(GEN x, long flag, GEN p);
+GEN     polred0(GEN x, long flag, GEN fa);
 GEN     polred2(GEN x);
 GEN     polredabs(GEN x);
 GEN     polredabs0(GEN x, long flag);
@@ -1446,6 +1722,7 @@ GEN     ZX_compositum_disjoint(GEN A, GEN B);
 GEN     compositum(GEN P, GEN Q);
 GEN     compositum2(GEN P, GEN Q);
 GEN     nfdisc(GEN x);
+GEN     get_modpr(GEN x);
 GEN     indexpartial(GEN P, GEN DP);
 GEN     modpr_genFq(GEN modpr);
 GEN     nf_to_Fq_init(GEN nf, GEN *pr, GEN *T, GEN *p);
@@ -1454,13 +1731,15 @@ GEN     nfM_to_FqM(GEN z, GEN nf,GEN modpr);
 GEN     nfV_to_FqV(GEN z, GEN nf,GEN modpr);
 GEN     nfX_to_FqX(GEN x, GEN nf,GEN modpr);
 GEN     nfbasis(GEN x, GEN *y,GEN p);
-GEN     nfbasis0(GEN x,long flag,GEN p);
-GEN     nfdisc0(GEN x,long flag, GEN p);
+GEN     nfcompositum(GEN nf, GEN A, GEN B, long flag);
 void    nfmaxord(nfmaxord_t *S, GEN T, long flag);
 GEN     nfmodprinit(GEN nf, GEN pr);
 GEN     nfreducemodpr(GEN nf, GEN x, GEN modpr);
+GEN     nfsplitting(GEN T, GEN D);
 GEN     polcompositum0(GEN P, GEN Q,long flag);
 GEN     idealprimedec(GEN nf,GEN p);
+GEN     idealprimedec_limit_f(GEN nf, GEN p, long f);
+GEN     idealprimedec_limit_norm(GEN nf, GEN p, GEN B);
 GEN     rnfbasis(GEN bnf, GEN order);
 GEN     rnfdedekind(GEN nf, GEN T, GEN pr, long flag);
 GEN     rnfdet(GEN nf, GEN order);
@@ -1491,6 +1770,7 @@ GEN     RgM_to_nfM(GEN nf,GEN x);
 GEN     RgX_to_nfX(GEN nf,GEN pol);
 GEN     algtobasis(GEN nf, GEN x);
 GEN     basistoalg(GEN nf, GEN x);
+GEN     gpnfvalrem(GEN nf, GEN x, GEN pr, GEN *py);
 GEN     ideallist(GEN nf,long bound);
 GEN     ideallist0(GEN nf,long bound, long flag);
 GEN     ideallistarch(GEN nf, GEN list, GEN arch);
@@ -1506,6 +1786,7 @@ GEN     nfarchstar(GEN nf,GEN x,GEN arch);
 GEN     nfdiv(GEN nf, GEN x, GEN y);
 GEN     nfdiveuc(GEN nf, GEN a, GEN b);
 GEN     nfdivrem(GEN nf, GEN a, GEN b);
+GEN     nfembed(GEN nf, GEN x, long k);
 GEN     nfinv(GEN nf, GEN x);
 GEN     nfinvmodideal(GEN nf, GEN x, GEN ideal);
 GEN     nfmod(GEN nf, GEN a, GEN b);
@@ -1522,6 +1803,7 @@ GEN     nfsqr(GEN nf,GEN x);
 GEN     nfsqri(GEN nf, GEN x);
 GEN     nftrace(GEN nf, GEN x);
 long    nfval(GEN nf, GEN x, GEN vp);
+long    nfvalrem(GEN nf, GEN x, GEN pr, GEN *py);
 GEN     polmod_nffix(const char *f, GEN rnf, GEN x,int lift);
 GEN     polmod_nffix2(const char *f, GEN T, GEN relpol, GEN x, int lift);
 int     pr_equal(GEN nf, GEN P, GEN Q);
@@ -1531,6 +1813,7 @@ GEN     rnfeltnorm(GEN rnf, GEN x);
 GEN     rnfelttrace(GEN rnf, GEN x);
 GEN     set_sign_mod_divisor(GEN nf, GEN x, GEN y, GEN idele, GEN sarch);
 GEN     vec01_to_indices(GEN arch);
+GEN     vecsmall01_to_indices(GEN v);
 GEN     vecmodii(GEN a, GEN b);
 GEN     ideallog(GEN nf,GEN x,GEN bigideal);
 
@@ -1551,6 +1834,7 @@ int     ZC_prdvd(GEN nf, GEN x, GEN P);
 
 GEN     RM_round_maxrank(GEN G);
 GEN     ZM_famat_limit(GEN fa, GEN limit);
+GEN     famat_Z_gcd(GEN M, GEN n);
 GEN     famat_inv(GEN f);
 GEN     famat_inv_shallow(GEN f);
 GEN     famat_makecoprime(GEN nf, GEN g, GEN e, GEN pr, GEN prk, GEN EX);
@@ -1562,6 +1846,7 @@ GEN     famat_to_nf(GEN nf, GEN f);
 GEN     famat_to_nf_modideal_coprime(GEN nf, GEN g, GEN e, GEN id, GEN EX);
 GEN     famat_to_nf_moddivisor(GEN nf, GEN g, GEN e, GEN bid);
 GEN     famatsmall_reduce(GEN fa);
+GEN     gpidealval(GEN nf, GEN ix, GEN P);
 GEN     idealtwoelt(GEN nf, GEN ix);
 GEN     idealtwoelt0(GEN nf, GEN ix, GEN a);
 GEN     idealtwoelt2(GEN nf, GEN x, GEN a);
@@ -1589,6 +1874,7 @@ GEN     idealhnf_two(GEN nf, GEN vp);
 GEN     idealhnf0(GEN nf, GEN a, GEN b);
 GEN     idealintersect(GEN nf, GEN x, GEN y);
 GEN     idealinv(GEN nf, GEN ix);
+GEN     idealinv_HNF(GEN nf, GEN I);
 GEN     idealred0(GEN nf, GEN I,GEN vdir);
 GEN     idealmul(GEN nf, GEN ix, GEN iy);
 GEN     idealmul0(GEN nf, GEN ix, GEN iy, long flag);
@@ -1612,12 +1898,14 @@ GEN     nfC_nf_mul(GEN nf, GEN v, GEN x);
 GEN     nfdetint(GEN nf,GEN pseudo);
 GEN     nfdivmodpr(GEN nf, GEN x, GEN y, GEN modpr);
 GEN     nfhnf(GEN nf, GEN x);
+GEN     nfhnf0(GEN nf, GEN x, long flag);
 GEN     nfhnfmod(GEN nf, GEN x, GEN d);
 GEN     nfkermodpr(GEN nf, GEN x, GEN modpr);
 GEN     nfmulmodpr(GEN nf, GEN x, GEN y, GEN modpr);
 GEN     nfpowmodpr(GEN nf, GEN x, GEN k, GEN modpr);
 GEN     nfreduce(GEN nf, GEN x, GEN ideal);
 GEN     nfsnf(GEN nf, GEN x);
+GEN     nfsnf0(GEN nf, GEN x, long flag);
 GEN     nfsolvemodpr(GEN nf, GEN a, GEN b, GEN modpr);
 GEN     to_famat(GEN x, GEN y);
 GEN     to_famat_shallow(GEN x, GEN y);
@@ -1653,6 +1941,8 @@ GEN     rnfinit(GEN nf,GEN pol);
 GEN dlog_get_ordfa(GEN o);
 GEN dlog_get_ord(GEN o);
 GEN gen_PH_log(GEN a, GEN g, GEN ord, void *E, const struct bb_group *grp);
+GEN gen_Shanks_init(GEN g, long n, void *E, const struct bb_group *grp);
+GEN gen_Shanks(GEN T, GEN x, ulong N, void *E, const struct bb_group *grp);
 GEN gen_Shanks_sqrtn(GEN a, GEN n, GEN q, GEN *zetan, void *E, const struct bb_group *grp);
 GEN gen_gener(GEN o, void *E, const struct bb_group *grp);
 GEN gen_ellgens(GEN d1, GEN d2, GEN m, void *E, const struct bb_group *grp,
@@ -1684,6 +1974,7 @@ GEN     algdep(GEN x, long n);
 GEN     algdep0(GEN x, long n, long bit);
 void    forqfvec0(GEN a, GEN BORNE, GEN code);
 GEN     gaussred_from_QR(GEN x, long prec);
+GEN     gram_schmidt(GEN e, GEN *ptB);
 GEN     lindep0(GEN x, long flag);
 GEN     lindep(GEN x);
 GEN     lindep2(GEN x, long bit);
@@ -1732,6 +2023,7 @@ GEN     gen_sort_uniq(GEN x, void *E, int (*cmp)(void*,GEN,GEN));
 long    getstack(void);
 long    gettime(void);
 long    getabstime(void);
+GEN     getwalltime(void);
 GEN     gprec(GEN x, long l);
 GEN     gprec_wtrunc(GEN x, long pr);
 GEN     gprec_w(GEN x, long pr);
@@ -1778,7 +2070,12 @@ long    zv_search(GEN x, long y);
 
 /* bit.c */
 
+GEN     bits_to_int(GEN x, long l);
+ulong   bits_to_u(GEN v, long l);
 GEN     binaire(GEN x);
+GEN     binary_zv(GEN x);
+GEN     binary_2k(GEN x, long k);
+GEN     binary_2k_zv(GEN x, long k);
 long    bittest(GEN x, long n);
 GEN     gbitand(GEN x, GEN y);
 GEN     gbitneg(GEN x, long n);
@@ -1821,6 +2118,7 @@ GEN     nfsign_units(GEN bnf, GEN archp, int add_zu);
 
 GEN     ABC_to_bnr(GEN A, GEN B, GEN C, GEN *H, int gen);
 GEN     Buchray(GEN bnf, GEN module, long flag);
+GEN     bnrautmatrix(GEN bnr, GEN aut);
 GEN     bnrclassno(GEN bignf,GEN ideal);
 GEN     bnrclassno0(GEN A,GEN B,GEN C);
 GEN     bnrclassnolist(GEN bnf,GEN listes);
@@ -1830,9 +2128,12 @@ GEN     bnrconductorofchar(GEN bnr,GEN chi);
 GEN     bnrdisc0(GEN A, GEN B, GEN C, long flag);
 GEN     bnrdisc(GEN bnr, GEN H, long flag);
 GEN     bnrdisclist0(GEN bnf,GEN borne, GEN arch);
+GEN     bnrgaloismatrix(GEN bnr, GEN aut);
+GEN     bnrgaloisapply(GEN bnr, GEN mat, GEN x);
 GEN     bnrinit0(GEN bignf,GEN ideal,long flag);
 long    bnrisconductor0(GEN A, GEN B, GEN C);
 long    bnrisconductor(GEN bnr, GEN H);
+long    bnrisgalois(GEN bnr, GEN M, GEN H);
 GEN     bnrisprincipal(GEN bnf, GEN x,long flag);
 GEN     bnrsurjection(GEN bnr1, GEN bnr2);
 GEN     buchnarrow(GEN bignf);
@@ -1862,6 +2163,10 @@ long    nfhilbert0(GEN bnf,GEN a,GEN b,GEN p);
 long    hyperell_locally_soluble(GEN pol,GEN p);
 long    nf_hyperell_locally_soluble(GEN nf,GEN pol,GEN p);
 
+/* classpoly.c */
+
+GEN     polclass(GEN D, long xvar);
+
 /* compile.c */
 
 GEN     closure_deriv(GEN G);
@@ -1886,7 +2191,7 @@ enum { d_SILENT = 0, d_ACKNOWLEDGE, d_INITRC, d_RETURN };
 
 GEN default0(const char *a, const char *b);
 long getrealprecision(void);
-int pari_is_default(const char *s);
+entree *pari_is_default(const char *s);
 GEN sd_TeXstyle(const char *v, long flag);
 GEN sd_colors(const char *v, long flag);
 GEN sd_compatible(const char *v, long flag);
@@ -1904,6 +2209,7 @@ GEN sd_nbthreads(const char *v, long flag);
 GEN sd_new_galois_format(const char *v, long flag);
 GEN sd_output(const char *v, long flag);
 GEN sd_parisize(const char *v, long flag);
+GEN sd_parisizemax(const char *v, long flag);
 GEN sd_path(const char *v, long flag);
 GEN sd_prettyprinter(const char *v, long flag);
 GEN sd_primelimit(const char *v, long flag);
@@ -1916,14 +2222,51 @@ GEN sd_strictargs(const char *v, long flag);
 GEN sd_strictmatch(const char *v, long flag);
 GEN sd_string(const char *v, long flag, const char *s, char **f);
 GEN sd_threadsize(const char *v, long flag);
+GEN sd_threadsizemax(const char *v, long flag);
 GEN sd_toggle(const char *v, long flag, const char *s, int *ptn);
 GEN sd_ulong(const char *v, long flag, const char *s, ulong *ptn, ulong Min, ulong Max, const char **msg);
 GEN setdefault(const char *s, const char *v, long flag);
 long setrealprecision(long n, long *prec);
 
+/* gplib.c */
+GEN sd_breakloop(const char *v, long flag);
+GEN sd_echo(const char *v, long flag);
+GEN sd_graphcolormap(const char *v, long flag);
+GEN sd_graphcolors(const char *v, long flag);
+GEN sd_help(const char *v, long flag);
+GEN sd_histfile(const char *v, long flag);
+GEN sd_lines(const char *v, long flag);
+GEN sd_linewrap(const char *v, long flag);
+GEN sd_prompt(const char *v, long flag);
+GEN sd_prompt_cont(const char *v, long flag);
+GEN sd_psfile(const char *v, long flag);
+GEN sd_readline(const char *v, long flag);
+GEN sd_recover(const char *v, long flag);
+GEN sd_timer(const char *v, long flag);
+void pari_hit_return(void);
+void gp_load_gprc(void);
+int  gp_meta(const char *buf, int ismain);
+void pari_center(const char *s);
+void pari_print_version(void);
+const char *gp_format_time(long delay);
+const char *gp_format_prompt(const char *p);
+void pari_alarm(long s);
+GEN  gp_alarm(long s, GEN code);
+GEN  gp_input(void);
+void gp_allocatemem(GEN z);
+int  gp_handle_exception(long numerr);
+void gp_alarm_handler(int sig);
+void gp_sigint_fun(void);
+enum { h_REGULAR=0, h_LONG=1, h_APROPOS=2, h_RL=4 };
+void gp_help(const char *s, long flag);
+void gp_echo_and_log(const char *prompt, const char *s);
+void print_fun_list(char **list, long nbli);
+
 /* ellanal.c */
 
 GEN     ellanalyticrank(GEN e, GEN eps, long prec);
+GEN     ellanal_globalred_all(GEN e, GEN *N, GEN *cb, GEN *tam);
+GEN     ellheegner(GEN e);
 GEN     ellL1(GEN e, long r, long prec);
 
 /* elldata.c */
@@ -1936,7 +2279,10 @@ GEN     ellsearchcurve(GEN name);
 void    forell(void *E, long call(void*, GEN), long a, long b);
 
 /* elliptic.c */
-enum { t_ELL_Rg = 0, t_ELL_Q = 1, t_ELL_Qp = 2, t_ELL_Fp = 3, t_ELL_Fq = 4};
+enum { t_ELL_Rg = 0, t_ELL_Q, t_ELL_Qp, t_ELL_Fp, t_ELL_Fq, t_ELL_NF };
+long    ellQ_get_CM(GEN e);
+int     ell_is_integral(GEN E);
+GEN     ellbasechar(GEN E);
 GEN     akell(GEN e, GEN n);
 GEN     anell(GEN e, long n);
 GEN     anellsmall(GEN e, long n);
@@ -1945,8 +2291,17 @@ void    checkell(GEN e);
 void    checkell_Fq(GEN e);
 void    checkell_Q(GEN e);
 void    checkell_Qp(GEN e);
+void    checkellisog(GEN v);
 void    checkellpt(GEN z);
 void    checkell5(GEN e);
+GEN     ec_bmodel(GEN e);
+GEN     ec_f_evalx(GEN E, GEN x);
+GEN     ec_h_evalx(GEN e, GEN x);
+GEN     ec_dFdx_evalQ(GEN E, GEN Q);
+GEN     ec_dFdy_evalQ(GEN E, GEN Q);
+GEN     ec_dmFdy_evalQ(GEN e, GEN Q);
+GEN     ec_2divpol_evalx(GEN E, GEN x);
+GEN     ec_half_deriv_2divpol_evalx(GEN E, GEN x);
 GEN     ellanal_globalred(GEN e, GEN *gr);
 GEN     ellQ_get_N(GEN e);
 void    ellQ_get_Nfa(GEN e, GEN *N, GEN *faN);
@@ -1962,6 +2317,7 @@ GEN     ellR_omega(GEN x, long prec);
 GEN     ellR_roots(GEN E, long prec);
 GEN     elladd(GEN e, GEN z1, GEN z2);
 GEN     ellap(GEN e, GEN p);
+long    ellap_CM_fast(GEN E, ulong p, long CM);
 GEN     ellcard(GEN E, GEN p);
 GEN     ellchangecurve(GEN e, GEN ch);
 GEN     ellchangeinvert(GEN w);
@@ -1976,22 +2332,40 @@ GEN     ellff_get_group(GEN E);
 GEN     ellff_get_o(GEN x);
 GEN     ellff_get_p(GEN E);
 GEN     ellfromj(GEN j);
+GEN     ellformaldifferential(GEN e, long n, long v);
+GEN     ellformalexp(GEN e, long n, long v);
+GEN     ellformallog(GEN e, long n, long v);
+GEN     ellformalpoint(GEN e, long n, long v);
+GEN     ellformalw(GEN e, long n, long v);
 GEN     ellgenerators(GEN E);
 GEN     ellglobalred(GEN e1);
 GEN     ellgroup(GEN E, GEN p);
 GEN     ellgroup0(GEN E, GEN p, long flag);
-GEN     ellheight0(GEN e, GEN a, long flag,long prec);
-GEN     ellheegner(GEN e);
+GEN     ellheight0(GEN e, GEN a, GEN b, long prec);
+GEN     ellheight(GEN e, GEN a, long prec);
+GEN     ellheightmatrix(GEN E, GEN x, long n);
+GEN     ellheightoo(GEN e, GEN z, long prec);
 GEN     ellinit(GEN x, GEN p, long prec);
+GEN     ellintegralmodel(GEN e, GEN *pv);
 GEN     ellisoncurve(GEN e, GEN z);
+int     ellissupersingular(GEN x, GEN p);
+int     elljissupersingular(GEN x);
 GEN     elllseries(GEN e, GEN s, GEN A, long prec);
 GEN     elllocalred(GEN e, GEN p1);
 GEN     elllog(GEN e, GEN a, GEN g, GEN o);
 GEN     ellminimalmodel(GEN E, GEN *ptv);
 GEN     ellmul(GEN e, GEN z, GEN n);
+GEN     ellnonsingularmultiple(GEN e, GEN P);
 GEN     ellneg(GEN e, GEN z);
 GEN     ellorder(GEN e, GEN p, GEN o);
+long    ellorder_Q(GEN E, GEN P);
 GEN     ellordinate(GEN e, GEN x, long prec);
+GEN     ellpadicfrobenius(GEN E, ulong p, long n);
+GEN     ellpadicheight(GEN e, GEN p, long n, GEN P);
+GEN     ellpadicheight0(GEN e, GEN p, long n, GEN P, GEN Q);
+GEN     ellpadicheightmatrix(GEN e, GEN p, long n, GEN P);
+GEN     ellpadiclog(GEN E, GEN p, long n, GEN P);
+GEN     ellpadics2(GEN E, GEN p, long n);
 GEN     ellperiods(GEN w, long flag, long prec);
 GEN     ellrandom(GEN e);
 long    ellrootno(GEN e, GEN p);
@@ -2006,15 +2380,27 @@ GEN     ellweilpairing(GEN E, GEN t, GEN s, GEN m);
 GEN     ellwp(GEN w, GEN z, long prec);
 GEN     ellwp0(GEN w, GEN z, long flag, long prec);
 GEN     ellwpseries(GEN e, long v, long PRECDL);
+GEN     ellxn(GEN e, long n, long v);
 GEN     ellzeta(GEN om, GEN z, long prec);
 GEN     expIxy(GEN x, GEN y, long prec);
-GEN     ghell(GEN e, GEN a, long prec);
-GEN     mathell(GEN e, GEN x, long prec);
 int     oncurve(GEN e, GEN z);
 GEN     orderell(GEN e, GEN p);
 GEN     pointell(GEN e, GEN z, long prec);
+GEN     point_to_a4a6(GEN E, GEN P, GEN p, GEN *pa4);
+GEN     point_to_a4a6_Fl(GEN E, GEN P, ulong p, ulong *pa4);
 GEN     zell(GEN e, GEN z, long prec);
 
+/* elltors.c */
+long    ellisdivisible(GEN E, GEN P, GEN n, GEN *Q);
+
+/* ellpadicL.c */
+GEN ellpadicL(GEN E, GEN p, long n, long r, GEN D, GEN C);
+
+/* ellisogeny.c */
+
+GEN     ellisogenyapply(GEN f, GEN P);
+GEN     ellisogeny(GEN e, GEN G, long only_image, long vx, long vy);
+
 /* ellsea.c */
 
 GEN     Fp_ellcard_SEA(GEN a4, GEN a6, GEN p, long early_abort);
@@ -2024,6 +2410,11 @@ GEN     ellsea(GEN E, GEN p, long early_abort);
 
 /* es.c */
 
+GEN     externstr(const char *cmd);
+char    *gp_filter(const char *s);
+GEN     gpextern(const char *cmd);
+void    gpsystem(const char *s);
+GEN     readstr(const char *s);
 GEN     GENtoGENstr_nospace(GEN x);
 GEN     GENtoGENstr(GEN x);
 char*   GENtoTeXstr(GEN x);
@@ -2041,7 +2432,7 @@ int     file_is_binary(FILE *f);
 void    err_flush(void);
 void    err_printf(const char* pat, ...);
 GEN     gp_getenv(const char *s);
-GEN     gp_read_file(char *s);
+GEN     gp_read_file(const char *s);
 GEN     gp_read_stream(FILE *f);
 GEN     gp_readvec_file(char *s);
 GEN     gp_readvec_stream(FILE *f);
@@ -2141,20 +2532,26 @@ void    closure_evalvoid(GEN C);
 GEN     closure_trapgen(GEN C, long numerr);
 GEN     copybin_unlink(GEN C);
 GEN     get_lex(long vn);
+long    get_localprec(void);
 GEN     gp_call(void *E, GEN x);
+GEN     gp_call2(void *E, GEN x, GEN y);
 long    gp_callbool(void *E, GEN x);
 long    gp_callvoid(void *E, GEN x);
 GEN     gp_eval(void *E, GEN x);
 long    gp_evalbool(void *E, GEN x);
 GEN     gp_evalupto(void *E, GEN x);
 long    gp_evalvoid(void *E, GEN x);
+void    localprec(long p);
 long    loop_break(void);
 GEN     next0(long n);
 GEN     pareval(GEN C);
+GEN     pari_self(void);
 GEN     parsum(GEN a, GEN b, GEN code, GEN x);
 GEN     parvector(long n, GEN code);
 void    pop_lex(long n);
+void    pop_localprec(void);
 void    push_lex(GEN a, GEN C);
+void    push_localprec(long p);
 GEN     return0(GEN x);
 void    set_lex(long vn, GEN x);
 
@@ -2233,6 +2630,7 @@ int     Rg_is_FF(GEN c, GEN *ff);
 int     RgC_is_FFC(GEN x, GEN *ff);
 int     RgM_is_FFM(GEN x, GEN *ff);
 GEN     p_to_FF(GEN p, long v);
+GEN     Tp_to_FF(GEN T, GEN p);
 
 /* galconj.c */
 
@@ -2322,6 +2720,7 @@ GEN     gcvtop(GEN x, GEN p, long r);
 int     gequal(GEN x, GEN y);
 int     gequalsg(long s, GEN x);
 long    gexpo(GEN x);
+GEN     gpvaluation(GEN x, GEN p);
 long    gvaluation(GEN x, GEN p);
 int     gidentical(GEN x, GEN y);
 long    glength(GEN x);
@@ -2424,6 +2823,7 @@ GEN     gmodulss(long x, long y);
 GEN     gne(GEN x, GEN y);
 GEN     gnot(GEN x);
 GEN     gpolvar(GEN y);
+GEN     gppoldegree(GEN x, long v);
 long    gprecision(GEN x);
 GEN     greal(GEN x);
 GEN     grndtoi(GEN x, long *e);
@@ -2506,10 +2906,14 @@ GEN     tayl(GEN x, long v, long precdl);
 GEN     toser_i(GEN x);
 GEN     trunc0(GEN x, GEN *pte);
 GEN     uu32toi(ulong a, ulong b);
+GEN     vars_sort_inplace(GEN z);
+GEN     vars_to_RgXV(GEN h);
+GEN     variables_vecsmall(GEN x);
+GEN     variables_vec(GEN x);
 
 /* genus2red.c */
 
-GEN     genus2red(GEN Q, GEN P, GEN p);
+GEN     genus2red(GEN PQ, GEN p);
 
 /* groupid.c */
 
@@ -2518,24 +2922,36 @@ long    group_ident_trans(GEN G, GEN S);
 
 /* hash.c */
 
+hashtable *hash_create_ulong(ulong s, long stack);
+hashtable *hash_create_str(ulong s, long stack);
 hashtable *hash_create(ulong minsize, ulong (*hash)(void*), int (*eq)(void*,void*), int use_stack);
 void hash_insert(hashtable *h, void *k, void *v);
+GEN hash_keys(hashtable *h);
+GEN hash_values(hashtable *h);
 hashentry *hash_search(hashtable *h, void *k);
+hashentry *hash_search2(hashtable *h, void *k, ulong hash);
+hashentry *hash_select(hashtable *h, void *k, void *E,int(*select)(void *,hashentry *));
 hashentry *hash_remove(hashtable *h, void *k);
+hashentry *hash_remove_select(hashtable *h, void *k, void *E, int (*select)(void*,hashentry*));
 void hash_destroy(hashtable *h);
 ulong hash_str(const char *str);
 ulong hash_str2(const char *s);
 ulong hash_GEN(GEN x);
 
+/* hyperell.c */
+
+GEN     hyperellpadicfrobenius(GEN x, ulong p, long e);
+GEN     hyperellcharpoly(GEN x);
+GEN     nfhyperellpadicfrobenius(GEN H, GEN T, ulong p, long n);
+
 /* hnf_snf.c */
 
-GEN     Frobeniusform(GEN V, long n);
 GEN     RgM_hnfall(GEN A, GEN *pB, long remove);
 GEN     ZM_hnf(GEN x);
 GEN     ZM_hnfall(GEN A, GEN *ptB, long remove);
 GEN     ZM_hnfcenter(GEN M);
 GEN     ZM_hnflll(GEN A, GEN *ptB, int remove);
-GEN     ZV_gcdext(GEN A);
+GEN     ZV_extgcd(GEN A);
 GEN     ZM_hnfmod(GEN x, GEN d);
 GEN     ZM_hnfmodall(GEN x, GEN dm, long flag);
 GEN     ZM_hnfmodid(GEN x, GEN d);
@@ -2614,7 +3030,6 @@ GEN     usumdivkvec(ulong n, GEN K);
 
 /* init.c */
 
-void    allocatemem(ulong newsize);
 long    timer_delay(pari_timer *T);
 long    timer_get(pari_timer *T);
 void    timer_start(pari_timer *T);
@@ -2645,12 +3060,14 @@ GEN     listcopy(GEN x);
 void    timer_printf(pari_timer *T, const char *format, ...);
 void    msgtimer(const char *format, ...);
 long    name_numerr(const char *s);
+void    new_chunk_resize(size_t x);
 GEN     newblock(size_t n);
 const char * numerr_name(long errnum);
 GEN     obj_check(GEN S, long K);
 GEN     obj_checkbuild(GEN S, long tag, GEN (*build)(GEN));
 GEN     obj_checkbuild_padicprec(GEN S, long tag, GEN (*build)(GEN,long), long prec);
-GEN     obj_checkbuild_prec(GEN S, long tag, GEN (*build)(GEN,long), long prec);
+GEN     obj_checkbuild_realprec(GEN S, long tag, GEN (*build)(GEN,long), long prec);
+GEN     obj_checkbuild_prec(GEN S, long tag, GEN (*build)(GEN,long), long (*pr)(GEN), long prec);
 void    obj_free(GEN S);
 GEN     obj_init(long d, long n);
 GEN     obj_insert(GEN S, long K, GEN O);
@@ -2658,9 +3075,9 @@ GEN     obj_insert_shallow(GEN S, long K, GEN O);
 void    pari_add_function(entree *ep);
 void    pari_add_module(entree *ep);
 void    pari_add_defaults_module(entree *ep);
-void    pari_add_oldmodule(entree *ep);
 void    pari_close(void);
 void    pari_close_opts(ulong init_opts);
+GEN     pari_compile_str(const char *lex);
 int     pari_daemon(void);
 void    pari_err(int numerr, ...);
 GEN     pari_err_last(void);
@@ -2674,8 +3091,15 @@ void    pari_thread_close(void);
 void    pari_thread_free(struct pari_thread *t);
 void    pari_thread_init(void);
 GEN     pari_thread_start(struct pari_thread *t);
+void    pari_thread_valloc(struct pari_thread *t, size_t s, size_t v, GEN arg);
 GEN     pari_version(void);
 void    pari_warn(int numerr, ...);
+void    paristack_alloc(size_t rsize, size_t vsize);
+void    paristack_newrsize(ulong newsize);
+void    paristack_resize(ulong newsize);
+void    paristack_setsize(size_t rsize, size_t vsize);
+void    parivstack_resize(ulong newsize);
+void    parivstack_reset(void);
 GEN     trap0(const char *e, GEN f, GEN r);
 void    shiftaddress(GEN x, long dec);
 void    shiftaddress_canon(GEN x, long dec);
@@ -2781,11 +3205,20 @@ GEN     member_tu(GEN x);
 GEN     member_zk(GEN x);
 GEN     member_zkst(GEN bid);
 
+/* modpoly.c */
+
+GEN     Flm_Fl_polmodular_evalx(GEN phi, long L, ulong j, ulong p, ulong pi);
+GEN     Fp_polmodular_evalx(long L, GEN J, GEN P, long v, int compute_derivs);
+GEN     polmodular_ZM(long L);
+GEN     polmodular_ZXX(long L, long xvar, long yvar);
+GEN     polmodular(long L, GEN x, long yvar, int compute_derivs);
+
 /* mp.c */
 
 GEN     addmulii(GEN x, GEN y, GEN z);
 GEN     addmulii_inplace(GEN x, GEN y, GEN z);
 ulong   Fl_inv(ulong x, ulong p);
+ulong   Fl_invgen(ulong x, ulong p, ulong *pg);
 ulong   Fl_invsafe(ulong x, ulong p);
 int     Fp_ratlift(GEN x, GEN m, GEN amax, GEN bmax, GEN *a, GEN *b);
 int     absi_cmp(GEN x, GEN y);
@@ -2802,6 +3235,7 @@ void    affir(GEN x, GEN y);
 void    affrr(GEN x, GEN y);
 GEN     bezout(GEN a, GEN b, GEN *u, GEN *v);
 long    cbezout(long a,long b,long *uu,long *vv);
+GEN     cbrtr_abs(GEN x);
 int     cmpii(GEN x, GEN y);
 int     cmprr(GEN x, GEN y);
 long    dblexpo(double x);
@@ -2873,6 +3307,7 @@ GEN     nffactor(GEN nf,GEN x);
 GEN     nffactormod(GEN nf,GEN pol,GEN pr);
 GEN     nfgcd(GEN P, GEN Q, GEN nf, GEN den);
 GEN     nfgcd_all(GEN P, GEN Q, GEN T, GEN den, GEN *Pnew);
+int     nfissquarefree(GEN nf, GEN x);
 GEN     nfroots(GEN nf,GEN pol);
 GEN     polfnf(GEN a, GEN t);
 GEN     rootsof1(GEN x);
@@ -2963,14 +3398,12 @@ void    pari_mt_close(void);
 
 GEN     ZX_Zp_root(GEN f, GEN a, GEN p, long prec);
 GEN     Zp_appr(GEN f, GEN a);
-GEN     factorpadic0(GEN f,GEN p,long r,long flag);
 GEN     factorpadic(GEN x, GEN p, long r);
 GEN     gdeuc(GEN x, GEN y);
 GEN     grem(GEN x, GEN y);
 GEN     padicappr(GEN f, GEN a);
 GEN     poldivrem(GEN x, GEN y, GEN *pr);
 GEN     rootpadic(GEN f, GEN p, long r);
-GEN     rootpadicfast(GEN f, GEN p, long e);
 
 /* polarit2.c */
 
@@ -2992,6 +3425,7 @@ GEN     RgX_gcd(GEN x, GEN y);
 GEN     RgX_gcd_simple(GEN x, GEN y);
 int     RgXQ_ratlift(GEN y, GEN x, long amax, long bmax, GEN *P, GEN *Q);
 GEN     RgX_resultant_all(GEN P, GEN Q, GEN *sol);
+long    RgX_sturmpart(GEN x, GEN ab);
 long    RgX_type(GEN x, GEN *ptp, GEN *ptpol, long *ptpa);
 void    RgX_type_decode(long x, long *t1, long *t2);
 int     RgX_type_is_composite(long t);
@@ -3064,6 +3498,7 @@ GEN     FpXY_Fq_evaly(GEN Q, GEN y, GEN T, GEN p, long vx);
 GEN     Fq_Fp_mul(GEN x, GEN y, GEN T, GEN p);
 GEN     Fq_add(GEN x, GEN y, GEN T/*unused*/, GEN p);
 GEN     Fq_div(GEN x, GEN y, GEN T, GEN p);
+GEN     Fq_halve(GEN x, GEN T/*unused*/, GEN p);
 GEN     Fq_inv(GEN x, GEN T, GEN p);
 GEN     Fq_invsafe(GEN x, GEN T, GEN p);
 GEN     Fq_mul(GEN x, GEN y, GEN T, GEN p);
@@ -3177,6 +3612,10 @@ GEN     qfisom0(GEN g, GEN h, GEN flags);
 GEN     qfisominit(GEN g, GEN flags);
 GEN     qfisominit0(GEN g, GEN flags);
 
+/* qfparam.c */
+GEN qfsolve(GEN G);
+GEN qfparam(GEN G, GEN sol, long fl);
+
 /* random.c */
 
 GEN     genrand(GEN N);
@@ -3185,6 +3624,7 @@ ulong   pari_rand(void);
 GEN     randomi(GEN x);
 GEN     randomr(long prec);
 ulong   random_Fl(ulong n);
+long    random_bits(long k);
 void    setrand(GEN seed);
 
 /* rootpol.c */
@@ -3192,10 +3632,16 @@ void    setrand(GEN seed);
 GEN     QX_complex_roots(GEN p, long l);
 GEN     ZX_graeffe(GEN p);
 GEN     cleanroots(GEN x,long l);
+double  fujiwara_bound(GEN p);
+double  fujiwara_bound_real(GEN p, long sign);
 int     isrealappr(GEN x, long l);
 GEN     polgraeffe(GEN p);
 GEN     polmod_to_embed(GEN x, long prec);
 GEN     roots(GEN x,long l);
+GEN     realroots(GEN P, GEN ab, long prec);
+long    ZX_sturm(GEN P);
+long    ZX_sturmpart(GEN P, GEN ab);
+GEN     ZX_uspensky(GEN P, GEN ab, long flag, long prec);
 
 /* subcyclo.c */
 
@@ -3279,6 +3725,7 @@ GEN     gexp(GEN x, long prec);
 GEN     gexpm1(GEN x, long prec);
 GEN     glog(GEN x, long prec);
 GEN     gpow(GEN x, GEN n, long prec);
+GEN     gpowers(GEN x, long n);
 GEN     gpowgs(GEN x, long n);
 GEN     gsin(GEN x, long prec);
 void    gsincos(GEN x, GEN *s, GEN *c, long prec);
@@ -3297,6 +3744,7 @@ GEN     mplog2(long prec);
 GEN     mppi(long prec);
 GEN     mpsin(GEN x);
 void    mpsincos(GEN x, GEN *s, GEN *c);
+GEN     powersr(GEN a, long n);
 GEN     powis(GEN x, long n);
 GEN     powiu(GEN p, ulong k);
 GEN     powrfrac(GEN x, long n, long d);
@@ -3345,27 +3793,27 @@ GEN     eint1(GEN x, long prec);
 GEN     eta(GEN x, long prec);
 GEN     eta0(GEN x, long flag,long prec);
 GEN     gerfc(GEN x, long prec);
+GEN     glambertW(GEN y, long prec);
 GEN     gpolylog(long m, GEN x, long prec);
 GEN     gzeta(GEN x, long prec);
+GEN     hbessel1(GEN n, GEN z, long prec);
+GEN     hbessel2(GEN n, GEN z, long prec);
 GEN     hyperu(GEN a, GEN b, GEN gx, long prec);
+GEN     ibessel(GEN n, GEN z, long prec);
 GEN     incgam(GEN a, GEN x, long prec);
 GEN     incgam0(GEN a, GEN x, GEN z,long prec);
 GEN     incgamc(GEN a, GEN x, long prec);
-GEN     hbessel1(GEN n, GEN z, long prec);
-GEN     hbessel2(GEN n, GEN z, long prec);
-GEN     ibessel(GEN n, GEN z, long prec);
 GEN     jbessel(GEN n, GEN z, long prec);
 GEN     jbesselh(GEN n, GEN z, long prec);
+GEN     jell(GEN x, long prec);
+GEN     kbessel(GEN nu, GEN gx, long prec);
 GEN     mpeint1(GEN x, GEN expx);
 GEN     mplambertW(GEN y);
 GEN     mpveceint1(GEN C, GEN eC, long n);
-GEN     powruvec(GEN e, ulong n);
 GEN     nbessel(GEN n, GEN z, long prec);
-GEN     jell(GEN x, long prec);
-GEN     kbessel(GEN nu, GEN gx, long prec);
 GEN     polylog0(long m, GEN x, long flag, long prec);
-GEN     sumdedekind_coprime(GEN h, GEN k);
 GEN     sumdedekind(GEN h, GEN k);
+GEN     sumdedekind_coprime(GEN h, GEN k);
 GEN     szeta(long x, long prec);
 GEN     theta(GEN q, GEN z, long prec);
 GEN     thetanullk(GEN q, long k, long prec);
@@ -3378,7 +3826,31 @@ GEN     weber0(GEN x, long flag,long prec);
 GEN     weberf(GEN x, long prec);
 GEN     weberf1(GEN x, long prec);
 GEN     weberf2(GEN x, long prec);
-GEN     glambertW(GEN y, long prec);
+GEN     zetaBorweinRecycled(long s, long h, long N, long prec);
+
+/* modsym.c */
+GEN     Eisenstein_symbol(GEN W, GEN c);
+GEN     Q_xpm(GEN W, GEN xpm, GEN c);
+GEN     Qevproj_apply(GEN T, GEN pro);
+GEN     Qevproj_apply_vecei(GEN T, GEN pro, long k);
+GEN     Qevproj_init(GEN M);
+GEN     RgX_act_Gl2Q(GEN g, long k);
+GEN     RgX_act_ZGl2Q(GEN z, long k);
+void    checkms(GEN W);
+GEN     msfromell(GEN E, long signe);
+GEN     msatkinlehner(GEN W, long Q, GEN);
+GEN     mscuspidal(GEN W, long flag);
+GEN     mseisenstein(GEN W);
+GEN     mseval(GEN W, GEN s, GEN p);
+GEN     mshecke(GEN W, long p, GEN H);
+GEN     msinit(GEN N, GEN k, long sign);
+long    msissymbol(GEN W, GEN s);
+GEN     mspathgens(GEN W);
+GEN     mspathlog(GEN W, GEN path);
+GEN     msnew(GEN W);
+GEN     msstar(GEN W, GEN);
+GEN     msqexpansion(GEN W, GEN proV, ulong B);
+GEN     mssplit(GEN W, GEN H);
 
 /* level1.h */
 
@@ -3386,9 +3858,13 @@ INLINE ulong  Fl_add(ulong a, ulong b, ulong p);
 INLINE long   Fl_center(ulong u, ulong p, ulong ps2);
 INLINE ulong  Fl_div(ulong a, ulong b, ulong p);
 INLINE ulong  Fl_double(ulong a, ulong p);
+INLINE ulong  Fl_ellj_pre(ulong a4, ulong a6, ulong p, ulong pi);
+INLINE ulong  Fl_halve(ulong y, ulong p);
 INLINE ulong  Fl_mul(ulong a, ulong b, ulong p);
+INLINE ulong  Fl_mul_pre(ulong a, ulong b, ulong p, ulong pi);
 INLINE ulong  Fl_neg(ulong x, ulong p);
 INLINE ulong  Fl_sqr(ulong a, ulong p);
+INLINE ulong  Fl_sqr_pre(ulong a, ulong p, ulong pi);
 INLINE ulong  Fl_sub(ulong a, ulong b, ulong p);
 INLINE ulong  Fl_triple(ulong a, ulong p);
 INLINE GEN    absi(GEN x);
@@ -3562,6 +4038,7 @@ INLINE GEN    remii(GEN a, GEN b);
 INLINE void   remiiz(GEN x, GEN y, GEN z);
 INLINE GEN    remis(GEN x, long y);
 INLINE void   remisz(GEN y, long s, GEN z);
+INLINE ulong  remlll_pre(ulong u2, ulong u1, ulong u0, ulong p, ulong pi);
 INLINE GEN    remsi(long x, GEN y);
 INLINE void   remsiz(long s, GEN y, GEN z);
 INLINE GEN    remss(long x, long y);
@@ -3612,6 +4089,7 @@ INLINE GEN    truedivii(GEN a,GEN b);
 INLINE GEN    truedivis(GEN a, long b);
 INLINE GEN    truedivsi(long a, GEN b);
 INLINE ulong  udivui_rem(ulong x, GEN y, ulong *rem);
+INLINE ulong  umodsu(long x, ulong y);
 INLINE ulong  umodui(ulong x, GEN y);
 INLINE GEN    utoi(ulong x);
 INLINE GEN    utoineg(ulong x);
@@ -3620,6 +4098,7 @@ INLINE GEN    utor(ulong s, long prec);
 INLINE GEN    uutoi(ulong x, ulong y);
 INLINE GEN    uutoineg(ulong x, ulong y);
 INLINE long   vali(GEN x);
+INLINE int    varncmp(long x, long y);
 
 /* pariinl.h */
 INLINE GEN    abgrp_get_cyc(GEN x);
@@ -3671,6 +4150,7 @@ INLINE int    ell_is_inf(GEN z);
 INLINE GEN    ellinf(void);
 INLINE GEN    ellff_get_field(GEN x);
 INLINE GEN    ellff_get_a4a6(GEN x);
+INLINE GEN    ellnf_get_nf(GEN x);
 INLINE GEN    ellQp_get_p(GEN E);
 INLINE long   ellQp_get_prec(GEN E);
 INLINE GEN    ellQp_get_zero(GEN x);
@@ -3691,6 +4171,9 @@ INLINE GEN    idealpseudomin(GEN I, GEN G);
 INLINE GEN    idealpseudomin_nonscalar(GEN I, GEN G);
 INLINE GEN    idealred_elt(GEN nf, GEN I);
 INLINE GEN    idealred(GEN nf, GEN I);
+INLINE GEN    modpr_get_pr(GEN x);
+INLINE GEN    modpr_get_p(GEN x);
+INLINE GEN    modpr_get_T(GEN x);
 INLINE GEN    nf_get_M(GEN nf);
 INLINE GEN    nf_get_G(GEN nf);
 INLINE GEN    nf_get_Tr(GEN nf);
@@ -3702,6 +4185,7 @@ INLINE GEN    nf_get_invzk(GEN nf);
 INLINE GEN    nf_get_pol(GEN nf);
 INLINE long   nf_get_r1(GEN nf);
 INLINE long   nf_get_r2(GEN nf);
+INLINE GEN    nf_get_ramified_primes(GEN nf);
 INLINE GEN    nf_get_roots(GEN nf);
 INLINE GEN    nf_get_roundG(GEN nf);
 INLINE void   nf_get_sign(GEN nf, long *r1, long *r2);
@@ -3714,9 +4198,12 @@ INLINE GEN    pr_get_p(GEN pr);
 INLINE GEN    pr_get_tau(GEN pr);
 INLINE int    pr_is_inert(GEN P);
 INLINE GEN    pr_norm(GEN pr);
+INLINE GEN    rnf_get_alpha(GEN rnf);
 INLINE long   rnf_get_absdegree(GEN rnf);
 INLINE long   rnf_get_degree(GEN rnf);
+INLINE GEN    rnf_get_idealdisc(GEN rnf);
 INLINE GEN    rnf_get_invzk(GEN rnf);
+INLINE GEN    rnf_get_k(GEN rnf);
 INLINE GEN    rnf_get_map(GEN rnf);
 INLINE GEN    rnf_get_nf(GEN rnf);
 INLINE long   rnf_get_nfdegree(GEN rnf);
@@ -3736,6 +4223,7 @@ INLINE GEN    closure_get_data(GEN C);
 INLINE GEN    closure_get_dbg(GEN C);
 INLINE GEN    closure_get_text(GEN C);
 INLINE GEN    closure_get_frame(GEN C);
+INLINE long   closure_is_variadic(GEN C);
 
 INLINE GEN    addmuliu(GEN x, GEN y, ulong u);
 INLINE GEN    addmuliu_inplace(GEN x, GEN y, ulong u);
@@ -3755,16 +4243,20 @@ INLINE GEN    FlxqX_div(GEN x, GEN y, GEN T, ulong p);
 INLINE GEN    FlxqX_rem(GEN x, GEN y, GEN T, ulong p);
 
 INLINE GEN    Fq_red(GEN x, GEN T, GEN p);
+INLINE GEN    Fq_to_FpXQ(GEN x, GEN T, GEN p);
+INLINE GEN    gener_Fq_local(GEN T, GEN p, GEN L);
 INLINE GEN    FqX_Fp_mul(GEN P, GEN U, GEN T, GEN p);
 INLINE GEN    FqX_Fq_mul(GEN P, GEN U, GEN T, GEN p);
 INLINE GEN    FqX_add(GEN x,GEN y,GEN T,GEN p);
 INLINE GEN    FqX_div(GEN x, GEN y, GEN T, GEN p);
+INLINE GEN    FqX_div_by_X_x(GEN x, GEN y, GEN T, GEN p, GEN *z);
 INLINE GEN    FqX_divrem(GEN x, GEN y, GEN T, GEN p, GEN *z);
 INLINE GEN    FqX_extgcd(GEN P,GEN Q,GEN T,GEN p, GEN *U, GEN *V);
 INLINE GEN    FqX_gcd(GEN P, GEN Q, GEN T, GEN p);
 INLINE GEN    FqX_mul(GEN x, GEN y, GEN T, GEN p);
 INLINE GEN    FqX_mulu(GEN x, ulong y, GEN T, GEN p);
-INLINE GEN    FqX_neg(GEN x,GEN T,GEN p);
+INLINE GEN    FqX_neg(GEN x, GEN T, GEN p);
+INLINE GEN    FqX_powu(GEN x, ulong n, GEN T, GEN p);
 INLINE GEN    FqX_red(GEN z, GEN T, GEN p);
 INLINE GEN    FqX_rem(GEN x, GEN y, GEN T, GEN p);
 INLINE GEN    FqX_sqr(GEN x, GEN T, GEN p);
@@ -3815,6 +4307,7 @@ INLINE GEN    Fp_add(GEN a, GEN b, GEN m);
 INLINE GEN    Fp_addmul(GEN x, GEN y, GEN z, GEN p);
 INLINE GEN    Fp_center(GEN u, GEN p, GEN ps2);
 INLINE GEN    Fp_div(GEN a, GEN b, GEN m);
+INLINE GEN    Fp_halve(GEN y, GEN p);
 INLINE GEN    Fp_inv(GEN a, GEN m);
 INLINE GEN    Fp_invsafe(GEN a, GEN m);
 INLINE GEN    Fp_mul(GEN a, GEN b, GEN m);
@@ -3853,6 +4346,7 @@ INLINE GEN    RgXQ_mul(GEN x,GEN y,GEN T);
 INLINE GEN    RgXQ_sqr(GEN x,GEN T);
 INLINE GEN    RgXQX_div(GEN x, GEN y, GEN T);
 INLINE GEN    RgXQX_rem(GEN x, GEN y, GEN T);
+INLINE GEN    RgX_coeff(GEN x, long n);
 INLINE GEN    RgX_copy(GEN x);
 INLINE GEN    RgX_div(GEN x, GEN y);
 INLINE GEN    RgX_fpnorml2(GEN x, long prec);
@@ -3881,6 +4375,7 @@ INLINE long   bit_accuracy(long x);
 INLINE double bit_accuracy_mul(long x, double y);
 INLINE long   bit_prec(GEN x);
 INLINE int    both_odd(long x, long y);
+INLINE GEN    cbrtr(GEN x);
 INLINE GEN    cgetc(long x);
 INLINE GEN    cgetalloc(long t, size_t l);
 INLINE GEN    cxcompotor(GEN z, long prec);
@@ -3929,6 +4424,7 @@ INLINE long   gval(GEN x, long v);
 INLINE GEN    identity_perm(long l);
 INLINE int    equali1(GEN n);
 INLINE int    equalim1(GEN n);
+INLINE long   inf_get_sign(GEN x);
 INLINE int    is_bigint(GEN n);
 INLINE int    is_const_t(long t);
 INLINE int    is_extscalar_t(long t);
@@ -3959,10 +4455,13 @@ INLINE GEN    mkcol3s(long x, long y, long z);
 INLINE GEN    mkcol4(GEN x, GEN y, GEN z, GEN t);
 INLINE GEN    mkcol4s(long x, long y, long z, long t);
 INLINE GEN    mkcol5(GEN x, GEN y, GEN z, GEN t, GEN u);
+INLINE GEN    mkcol6(GEN x, GEN y, GEN z, GEN t, GEN u, GEN v);
 INLINE GEN    mkcolcopy(GEN x);
 INLINE GEN    mkcols(long x);
 INLINE GEN    mkcomplex(GEN x, GEN y);
 INLINE GEN    mkerr(long n);
+INLINE GEN    mkmoo();
+INLINE GEN    mkoo();
 INLINE GEN    mkfrac(GEN x, GEN y);
 INLINE GEN    mkfraccopy(GEN x, GEN y);
 INLINE GEN    mkintmod(GEN x, GEN y);
@@ -4036,7 +4535,6 @@ INLINE GEN    quad_disc(GEN x);
 INLINE GEN    qfb_disc(GEN x);
 INLINE GEN    qfb_disc3(GEN x, GEN y, GEN z);
 INLINE GEN    quadnorm(GEN q);
-INLINE long   random_bits(long k);
 INLINE long   remsBIL(long n);
 INLINE GEN    resultant(GEN x, GEN y);
 INLINE GEN    row(GEN A, long x1);
@@ -4047,6 +4545,7 @@ INLINE GEN    rowcopy(GEN A, long x0);
 INLINE GEN    rowpermute(GEN A, GEN p);
 INLINE GEN    rowslice(GEN A, long x1, long x2);
 INLINE GEN    rowslicepermute(GEN A, GEN p, long x1, long x2);
+INLINE int    ser_isexactzero(GEN x);
 INLINE GEN    shallowcopy(GEN x);
 INLINE GEN    sqrfrac(GEN x);
 INLINE GEN    sqrti(GEN x);
@@ -4062,12 +4561,15 @@ INLINE long   sturm(GEN x);
 INLINE GEN    truecoeff(GEN x, long n);
 INLINE GEN    trunc_safe(GEN x);
 INLINE GEN    vec_ei(long n, long i);
+INLINE GEN    vec_append(GEN v, GEN s);
 INLINE GEN    vec_lengthen(GEN v, long n);
 INLINE GEN    vec_setconst(GEN v, GEN x);
 INLINE GEN    vec_shorten(GEN v, long n);
 INLINE GEN    vec_to_vecsmall(GEN z);
 INLINE GEN    vecpermute(GEN A, GEN p);
 INLINE GEN    vecreverse(GEN A);
+INLINE void   vecreverse_inplace(GEN y);
+INLINE GEN    vecsmallpermute(GEN A, GEN p);
 INLINE GEN    vecslice(GEN A, long y1, long y2);
 INLINE GEN    vecslicepermute(GEN A, GEN p, long y1, long y2);
 INLINE GEN    vecsplice(GEN a, long j);
diff --git a/src/headers/parierr.h b/src/headers/parierr.h
index 6d6966a..b20b566 100644
--- a/src/headers/parierr.h
+++ b/src/headers/parierr.h
@@ -21,7 +21,7 @@ enum err_list {
 
   e_PREC, e_TYPE, e_DIM, e_VAR, e_PRIORITY, e_USER,
 
-  e_STACK, e_OVERFLOW, e_DOMAIN, e_COMPONENT,
+  e_STACK, e_STACKTHREAD, e_OVERFLOW, e_DOMAIN, e_COMPONENT,
 
   e_MAXPRIME,
 
diff --git a/src/headers/parigen.h b/src/headers/parigen.h
index 5d86649..68db00c 100644
--- a/src/headers/parigen.h
+++ b/src/headers/parigen.h
@@ -80,7 +80,9 @@ typedef unsigned long pari_ulong;
 #define VALPBITS    ((1UL<<VALPnumBITS)-1)
 #define VARNBITS    (MAXVARN<<VARNSHIFT)
 #define MAXVARN     ((1UL<<VARNnumBITS)-1)
-#define NO_VARIABLE (2147483647L) /* > MAXVARN */
+#define NO_VARIABLE (-1)
+#define VARARGBITS  HIGHBIT
+#define ARITYBITS   (~VARARGBITS)
 
 #define HIGHEXPOBIT (1UL<<(EXPOnumBITS-1))
 #define HIGHVALPBIT (1UL<<(VALPnumBITS-1))
@@ -121,26 +123,24 @@ typedef unsigned long pari_ulong;
                       (((ulong*)(x))[0]&(~LGBITS)) | evallg(s))
 #define incrprec(x)   ((x)++)
 
-#define expo(x)       ((long) ((((ulong*)(x))[1] & EXPOBITS) - HIGHEXPOBIT))
+#define expo(x)       ((long) ((((ulong)((x)[1])) & EXPOBITS) - HIGHEXPOBIT))
 #define setexpo(x,s)  (((ulong*)(x))[1]=\
                        (((ulong*)(x))[1]&(~EXPOBITS)) | (ulong)evalexpo(s))
 
-#define valp(x)       ((long) ((((ulong*)(x))[1] & VALPBITS) - HIGHVALPBIT))
+#define valp(x)       ((long) ((((ulong)((x)[1])) & VALPBITS) - HIGHVALPBIT))
 #define setvalp(x,s)  (((ulong*)(x))[1]=\
                        (((ulong*)(x))[1]&(~VALPBITS)) | (ulong)evalvalp(s))
 
-#define precp(x)      ((long) (((ulong*)(x))[1] >> PRECPSHIFT))
+#define precp(x)      ((long) (((ulong)((x)[1])) >> PRECPSHIFT))
 #define setprecp(x,s) (((ulong*)(x))[1]=\
                        (((ulong*)(x))[1]&(~PRECPBITS)) | (ulong)evalprecp(s))
 
-#define varn(x)       ((long)((((ulong*)(x))[1]&VARNBITS) >> VARNSHIFT))
+#define varn(x)       ((long)((((ulong)((x)[1]))&VARNBITS) >> VARNSHIFT))
 #define setvarn(x,s)  (((ulong*)(x))[1]=\
                        (((ulong*)(x))[1]&(~VARNBITS)) | (ulong)evalvarn(s))
 
-#define varncmp(x,y)  ((x)-(y))
-
 /* t_LIST */
-#define list_nmax(x) ((GEN)x)[1]
+#define list_nmax(x) x[1]
 #define list_data(x) ((GEN*)x)[2]
 
 /* DO NOT REORDER THESE
@@ -167,5 +167,6 @@ enum {
   t_STR    =  21,
   t_VECSMALL= 22,
   t_CLOSURE = 23,
-  t_ERROR   = 24
+  t_ERROR   = 24,
+  t_INFINITY= 25
 };
diff --git a/src/headers/pariinl.h b/src/headers/pariinl.h
index d1c929d..d4d5a00 100644
--- a/src/headers/pariinl.h
+++ b/src/headers/pariinl.h
@@ -98,6 +98,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
        gel(_v,3) = (z);\
        gel(_v,4) = (t);\
        gel(_v,5) = (u); return _v; } while(0)
+#define retmkcol6(x,y,z,t,u,v)\
+  do { GEN _v = cgetg(7, t_COL);\
+       gel(_v,1) = (x);\
+       gel(_v,2) = (y);\
+       gel(_v,3) = (z);\
+       gel(_v,4) = (t);\
+       gel(_v,5) = (u);\
+       gel(_v,6) = (v); return _v; } while(0)
 #define retmkmat(x)\
   do { GEN _v = cgetg(2, t_MAT);\
        gel(_v,1) = (x); return _v; } while(0)
@@ -165,6 +173,9 @@ mkvecsmall3(long x,long y,long z) { GEN v = cgetg(4, t_VECSMALL);
 INLINE GEN
 mkvecsmall4(long x,long y,long z,long t) { GEN v = cgetg(5, t_VECSMALL);
   v[1]=x; v[2]=y; v[3]=z; v[4]=t; return v; }
+INLINE GEN
+mkvecsmall5(long x,long y,long z,long t,long u) { GEN v = cgetg(6, t_VECSMALL);
+  v[1]=x; v[2]=y; v[3]=z; v[4]=t; v[5]=u; return v; }
 
 INLINE GEN
 mkqfi(GEN x, GEN y, GEN z) { retmkqfi(x,y,z); }
@@ -204,6 +215,8 @@ mkcol4(GEN x, GEN y, GEN z, GEN t) { retmkcol4(x,y,z,t); }
 INLINE GEN
 mkcol5(GEN x, GEN y, GEN z, GEN t, GEN u) { retmkcol5(x,y,z,t,u); }
 INLINE GEN
+mkcol6(GEN x, GEN y, GEN z, GEN t, GEN u, GEN v) { retmkcol6(x,y,z,t,u,v); }
+INLINE GEN
 mkcols(long x) { retmkcol(stoi(x)); }
 INLINE GEN
 mkcol2s(long x, long y) { retmkcol2(stoi(x),stoi(y)); }
@@ -228,6 +241,12 @@ INLINE GEN
 mkmatcopy(GEN x) { GEN v = cgetg(2, t_MAT); gel(v,1) = gcopy(x); return v; }
 INLINE GEN
 mkerr(long x) { GEN v = cgetg(2, t_ERROR); v[1] = x; return v; }
+INLINE GEN
+mkoo() { GEN v = cgetg(2, t_INFINITY); gel(v,1) = gen_1; return v; }
+INLINE GEN
+mkmoo() { GEN v = cgetg(2, t_INFINITY); gel(v,1) = gen_m1; return v; }
+INLINE long
+inf_get_sign(GEN x) { return signe(gel(x,1)); }
 /* pol */
 INLINE GEN
 pol_x(long v) {
@@ -300,6 +319,16 @@ zeroser(long v, long e)
   GEN x = cgetg(2, t_SER);
   x[1] = evalvalp(e) | evalvarn(v); return x;
 }
+INLINE int
+ser_isexactzero(GEN x)
+{
+  if (!signe(x)) switch(lg(x))
+  {
+    case 2: return 1;
+    case 3: return isexactzero(gel(x,2));
+  }
+  return 0;
+}
 /* 0 * pol_x(v) */
 INLINE GEN
 zeropol(long v) { return pol_0(v); }
@@ -466,6 +495,15 @@ vec_lengthen(GEN v, long n)
 }
 /* shallow*/
 INLINE GEN
+vec_append(GEN V, GEN s)
+{
+  long i, l2 = lg(V);
+  GEN res = cgetg(l2+1, typ(V));
+  for (i = 1; i < l2; ++i) gel(res, i) = gel(V,i);
+  gel(res,l2) = s; return res;
+}
+/* shallow*/
+INLINE GEN
 vec_setconst(GEN v, GEN x)
 {
   long i, l = lg(v);
@@ -546,12 +584,11 @@ vecsmall_prepend(GEN V, long s)
   return res;
 }
 
-/*Can be used on t_VEC, but coeffs not gcopy-ed*/
 INLINE GEN
 vecsmall_append(GEN V, long s)
 {
   long i, l2 = lg(V);
-  GEN res = cgetg(l2+1, typ(V));
+  GEN res = cgetg(l2+1, t_VECSMALL);
   for (i = 1; i < l2; ++i) res[i] = V[i];
   res[l2] = s; return res;
 }
@@ -865,12 +902,27 @@ row_i(GEN A, long x0, long x1, long x2)
 INLINE GEN
 vecreverse(GEN A)
 {
-  long i,l = lg(A);
-  GEN B = cgetg(l, typ(A));
+  long i, l;
+  GEN B = cgetg_copy(A, &l);
   for (i=1; i<l; i++) gel(B, i) = gel(A, l-i);
   return B;
 }
 
+INLINE void
+vecreverse_inplace(GEN y)
+{
+  long ly = lg(y), lim = ly>>1, i;
+  for (i = 1; i <= lim; i++)
+  {
+    GEN z = gel(y,i);
+    gel(y,i)    = gel(y,ly-i);
+    gel(y,ly-i) = z;
+  }
+}
+
+INLINE GEN
+vecsmallpermute(GEN A, GEN p) { return perm_mul(A, p); }
+
 INLINE GEN
 vecpermute(GEN A, GEN p)
 {
@@ -884,7 +936,9 @@ rowpermute(GEN A, GEN p)
 {
   long i, lB = lg(A);
   GEN B = cgetg(lB, typ(A));
-  for (i=1; i<lB; i++) gel(B, i) = vecpermute(gel(A, i), p);
+  for (i=1; i<lB; i++)
+    gel(B, i) = typ(gel(A,i)) == t_VECSMALL ? vecsmallpermute(gel(A, i), p):
+                                                    vecpermute(gel(A, i), p);
   return B;
 }
 /*******************************************************************/
@@ -1089,7 +1143,7 @@ gerepilecopy(pari_sp av, GEN x)
   {
     avma = av;
     if (x < (GEN)av) {
-      if (x < (GEN)bot) new_chunk(lg(x));
+      if (x < (GEN)pari_mainstack->bot) new_chunk(lg(x));
       x = leafcopy_avma(x, av);
       avma = (pari_sp)x;
     } else
@@ -1217,6 +1271,13 @@ gtos(GEN x) {
   return itos(x);
 }
 
+INLINE ulong
+gtou(GEN x) {
+  if (typ(x) != t_INT || signe(x)<0)
+    pari_err_TYPE("gtou [integer >=0 expected]",x);
+  return itou(x);
+}
+
 INLINE GEN
 absfrac(GEN x)
 {
@@ -1430,7 +1491,6 @@ remsBIL(long n) { return n & (BITS_IN_LONG-1); }
 
 INLINE GEN
 Fp_red(GEN a, GEN m) { return modii(a, m); }
-
 INLINE GEN
 Fp_add(GEN a, GEN b, GEN m)
 {
@@ -1488,6 +1548,14 @@ Fp_neg(GEN b, GEN m)
     p = remii(negi(b), m);
   return gerepileuptoint(av, p);
 }
+
+INLINE GEN
+Fp_halve(GEN a, GEN p)
+{
+  if (mpodd(a)) a = addii(a,p);
+  return shifti(a,-1);
+}
+
 /* assume 0 <= u < p and ps2 = p>>1 */
 INLINE GEN
 Fp_center(GEN u, GEN p, GEN ps2)
@@ -1725,9 +1793,26 @@ sqrtr(GEN x) {
   if (s >= 0) return sqrtr_abs(x);
   retmkcomplex(gen_0, sqrtr_abs(x));
 }
+INLINE GEN
+cbrtr(GEN x) {
+  long s = signe(x);
+  GEN r;
+  if (s == 0) return real_0_bit(expo(x) / 3);
+  r = cbrtr_abs(x);
+  if (s < 0) togglesign(r);
+  return r;
+}
 /* x^(1/n) */
 INLINE GEN
-sqrtnr(GEN x, long n) { return mpexp(divrs(mplog(x), n)); }
+sqrtnr(GEN x, long n) {
+  switch(n)
+  {
+    case 1: return rcopy(x);
+    case 2: return sqrtr(x);
+    case 3: return cbrtr(x);
+  }
+  return mpexp(divrs(mplog(x), n));
+}
 
 /*******************************************************************/
 /*                                                                 */
@@ -1752,11 +1837,9 @@ INLINE int odd(long x) { return x & 1; }
 INLINE int both_odd(long x, long y) { return x & y & 1; }
 
 INLINE int
-isonstack(GEN x) { return ((pari_sp)x >= bot && (pari_sp)x < top); }
-
-/* assume 0 <= k <= BITS_IN_LONG. Return uniform random 0 <= x < (1<<k) */
-INLINE long
-random_bits(long k) { return pari_rand() >> (BITS_IN_LONG - k); }
+isonstack(GEN x)
+{ return ((pari_sp)x >= pari_mainstack->bot
+       && (pari_sp)x <  pari_mainstack->top); }
 
 /* assume x != 0 and x t_REAL, return an approximation to log2(|x|) */
 INLINE double
@@ -1814,6 +1897,14 @@ RgX_copy(GEN x)
   for (i = 2; i<lx; i++) gel(y,i) = gcopy(gel(x,i));
   return y;
 }
+/* have to use ulong to avoid silly warnings from gcc "assuming signed
+ * overflow does not occur" */
+INLINE GEN
+RgX_coeff(GEN x, long n)
+{
+  ulong l = lg(x);
+  return (n < 0 || ((ulong)n+3) > l)? gen_0: gel(x,n+2);
+}
 INLINE GEN
 RgX_renormalize(GEN x) { return RgX_renormalize_lg(x, lg(x)); }
 INLINE GEN
@@ -1989,6 +2080,17 @@ ZV_dvd(GEN x, GEN y)
 INLINE GEN
 Fq_red(GEN x, GEN T, GEN p)
 { return typ(x)==t_INT? Fp_red(x,p): FpXQ_red(x,T,p); }
+INLINE GEN
+Fq_to_FpXQ(GEN x, GEN T, GEN p /*unused*/)
+{
+  (void) p;
+  return typ(x)==t_INT ? scalarpol(x, get_FpX_var(T)): x;
+}
+
+INLINE GEN
+gener_Fq_local(GEN T, GEN p, GEN L)
+{ return T? gener_FpXQ_local(T,p, L)
+          : pgener_Fp_local(p, L); }
 
 /* FpXQX */
 INLINE GEN
@@ -2023,6 +2125,9 @@ INLINE GEN
 FqX_sqr(GEN x, GEN T, GEN p)
 { return T? FpXQX_sqr(x, T, p): FpX_sqr(x, p); }
 INLINE GEN
+FqX_powu(GEN x, ulong n, GEN T, GEN p)
+{ return T? FpXQX_powu(x, n, T, p): FpX_powu(x, n, p); }
+INLINE GEN
 FqX_div(GEN x, GEN y, GEN T, GEN p)
 { return T? FpXQX_divrem(x,y,T,p,NULL): FpX_divrem(x,y,p,NULL); }
 INLINE GEN
@@ -2032,6 +2137,9 @@ INLINE GEN
 FqX_divrem(GEN x, GEN y, GEN T, GEN p, GEN *z)
 { return T? FpXQX_divrem(x,y,T,p,z): FpX_divrem(x,y,p,z); }
 INLINE GEN
+FqX_div_by_X_x(GEN x, GEN y, GEN T, GEN p, GEN *z)
+{ return T? FpXQX_div_by_X_x(x,y,T,p,z): FpX_div_by_X_x(x,y,p,z); }
+INLINE GEN
 FqX_gcd(GEN P,GEN Q,GEN T,GEN p)
 {return T? FpXQX_gcd(P,Q,T,p): FpX_gcd(P,Q,p);}
 INLINE GEN
@@ -2301,6 +2409,7 @@ INLINE long ellQp_get_prec(GEN E) { GEN z = ellQp_get_zero(E); return valp(z); }
 INLINE GEN ellQp_get_p(GEN E) { GEN z = ellQp_get_zero(E); return gel(z,2); }
 INLINE long ellR_get_prec(GEN x) { return nbits2prec(mael3(x, 15, 1, 1)); }
 INLINE long ellR_get_sign(GEN x) { return mael3(x, 15, 1, 2); }
+INLINE GEN ellnf_get_nf(GEN x) { return gmael(x, 15, 1); }
 
 INLINE int ell_is_inf(GEN z) { return lg(z) == 2; }
 INLINE GEN ellinf(void) { return mkvec(gen_0); }
@@ -2310,6 +2419,10 @@ INLINE GEN ellinf(void) { return mkvec(gen_0); }
 /*                    ALGEBRAIC NUMBER THEORY                      */
 /*                                                                 */
 /*******************************************************************/
+INLINE GEN modpr_get_pr(GEN x)  { return gel(x,3); }
+INLINE GEN modpr_get_p(GEN x)  { return pr_get_p(modpr_get_pr(x)); }
+INLINE GEN modpr_get_T(GEN x)  { return lg(x) == 4? NULL: gel(x,4); }
+
 INLINE GEN pr_get_p(GEN pr)  { return gel(pr,1); }
 INLINE GEN pr_get_gen(GEN pr){ return gel(pr,2); }
 /* .[2] instead of itos works: e and f are small positive integers */
@@ -2347,6 +2460,8 @@ nf_get_Tr(GEN nf) { return gmael(nf,5,4); }
 INLINE GEN
 nf_get_diff(GEN nf) { return gmael(nf,5,5); }
 INLINE GEN
+nf_get_ramified_primes(GEN nf) { return gmael(nf,5,8); }
+INLINE GEN
 nf_get_roots(GEN nf) { return gel(nf,6); }
 INLINE GEN
 nf_get_zk(GEN nf) { return gel(nf,7); }
@@ -2466,6 +2581,12 @@ rnf_get_nfdegree(GEN rnf) { return degpol(nf_get_pol(rnf_get_nf(rnf))); }
 INLINE long
 rnf_get_absdegree(GEN rnf) { return degpol(gmael(rnf,11,1)); }
 INLINE GEN
+rnf_get_idealdisc(GEN rnf) { return gmael(rnf,3,1); }
+INLINE GEN
+rnf_get_k(GEN rnf) { return gmael(rnf,11,3); }
+INLINE GEN
+rnf_get_alpha(GEN rnf) { return gmael(rnf, 11, 2); }
+INLINE GEN
 rnf_get_nf(GEN rnf) { return gel(rnf,10); }
 INLINE void
 rnf_get_nfzk(GEN rnf, GEN *b, GEN *cb) {*b=gmael(rnf,2,1); *cb=gmael(rnf,2,2);}
@@ -2522,7 +2643,8 @@ idealred(GEN nf, GEN I) { return idealred0(nf, I, NULL); }
 /*                              CLOSURES                           */
 /*                                                                 */
 /*******************************************************************/
-INLINE long closure_arity(GEN C)    { return C[1]; }
+INLINE long closure_arity(GEN C)          { return ((ulong)C[1])&ARITYBITS; }
+INLINE long closure_is_variadic(GEN C) { return !!(((ulong)C[1])&VARARGBITS); }
 INLINE const char *closure_codestr(GEN C)  { return GSTR(gel(C,2))-1; }
 INLINE GEN closure_get_code(GEN C)  { return gel(C,2); }
 INLINE GEN closure_get_oper(GEN C)  { return gel(C,3); }
diff --git a/src/headers/parinf.h b/src/headers/parinf.h
index 171eab9..d8b35f2 100644
--- a/src/headers/parinf.h
+++ b/src/headers/parinf.h
@@ -28,6 +28,23 @@ enum {
   typ_RNF
 };
 
+/* types of algebras */
+enum  {
+  al_NULL = 0,
+  al_TABLE,
+  al_CSA,
+  al_CYCLIC
+};
+
+/* models for elements of algebras */
+enum {
+  al_INVALID = 0,
+  al_TRIVIAL,
+  al_ALGEBRAIC,
+  al_BASIS,
+  al_MATRIX
+};
+
 /* idealtyp */
 enum {
   id_PRINCIPAL = 0,
@@ -106,7 +123,8 @@ enum {
   LLL_ALL  = 4, /* kernel & image */
   LLL_GRAM       = 0x100,
   LLL_KEEP_FIRST = 0x200,
-  LLL_INPLACE    = 0x400
+  LLL_INPLACE    = 0x400,
+  LLL_COMPATIBLE = 0x800 /* attempt same behaviour on 32/64bit kernels */
 };
 
 /* HNF */
@@ -161,9 +179,11 @@ GEN    coltoalg(GEN nf,GEN x);
 GEN    archstar_full_rk(GEN x, GEN bas, GEN v, GEN gen);
 GEN    check_and_build_cycgen(GEN bnf);
 long   check_LIMC(long LIMC, long LIMCMAX);
+int    checkal_i(GEN x);
 GEN    checkbid_i(GEN bid);
 GEN    checkbnf_i(GEN bnf);
 GEN    checknf_i(GEN nf);
+int    checkrnf_i(GEN rnf);
 GEN    pow_ei_mod_p(GEN nf, long I, GEN n, GEN p);
 GEN    galoisbig(GEN x, long prec);
 GEN    get_arch_real(GEN nf,GEN x,GEN *emb,long prec);
@@ -190,6 +210,7 @@ GEN    special_anti_uniformizer(GEN nf, GEN pr);
 GEN    subgroupcondlist(GEN cyc, GEN bound, GEN listKer);
 void   testprimes(GEN bnf, GEN bound);
 GEN    to_Fp_simple(GEN nf, GEN x, GEN ffproj);
+GEN    to_Fq_simple(GEN nf, GEN x, GEN pr);
 GEN    unif_mod_fZ(GEN pr, GEN F);
 GEN    unnf_minus_x(GEN x);
 GEN    ideallog_sgn(GEN nf, GEN x, GEN sgn, GEN bid);
diff --git a/src/headers/pariold.h b/src/headers/pariold.h
index 13d0ad4..e2a7daf 100644
--- a/src/headers/pariold.h
+++ b/src/headers/pariold.h
@@ -11,8 +11,10 @@ Check the License for details. You should have received a copy of it, along
 with the package; see the file 'COPYING'. If not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 
-/* For compatibility with 1.x.x */
+/* For compatibility with older PARI versions */
 /*functions renamed*/
+#define mathell ellheightmatrix
+#define ghell ellheight
 #define mpexp1 mpexpm1
 #define ggamd ggammah
 #define gach gacosh
@@ -97,6 +99,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 #define pariflush pari_flush
 #define ellap0(e,p,flag) ellap(e,p)
 #define apell2(e,p) ellap(e,p)
+
+/* Following deprecated for a long time now, obsoleted in 2.3.* (2007) */
+#ifdef PARI_OLD_NAMES
 #define apell ellap
 #define gscalsmat scalarmat_s
 #define sqred qfgaussred
@@ -224,9 +229,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 #define absrz(x,z)  mpabsz((x),(z))
 #define negrz(x,z)  mpnegz((x),(z))
 
-/* Following deprecated for a long time now. Or really, really bad, e.g
- * un, init, er. */
-#ifdef PARI_OLD_NAMES
 #define err pari_err
 #define init pari_init
 
diff --git a/src/headers/paripriv.h b/src/headers/paripriv.h
index 93fadcd..b820ea6 100644
--- a/src/headers/paripriv.h
+++ b/src/headers/paripriv.h
@@ -44,7 +44,6 @@ clone_unlock(GEN C) { if (isclone(C)) gunclone(C); }
 #define swapspec(x,y, nx,ny) {swap(x,y); lswap(nx,ny);}
 
 /* unused */
-GEN ellheightoo(GEN e, GEN z, long prec);
 void ellprint(GEN e);
 
 /* binary splitting */
@@ -106,7 +105,6 @@ GEN  intfuncinit0(GEN a, GEN b, GEN code, long flag, long m, long prec);
 GEN  intlaplaceinv0(GEN sig, GEN x, GEN code, GEN tab, long prec);
 GEN  intmellininv0(GEN sig, GEN x, GEN code, GEN tab, long prec);
 GEN  intnum0(GEN a, GEN b, GEN code, GEN tab, long prec);
-GEN  intnuminit0(GEN a, GEN b, GEN tab, long prec);
 GEN  intnuminitgen0(GEN a, GEN b, GEN code, long m, long flag, long prec);
 GEN  intnumromb0(GEN a, GEN b, GEN code, long flag, long prec);
 GEN  matrice(GEN nlig, GEN ncol, GEN code);
@@ -120,7 +118,6 @@ GEN  sumdivmultexpr(GEN num, GEN code);
 GEN  suminf0(GEN a, GEN code, long prec);
 GEN  sumnum0(GEN a, GEN sig, GEN code, GEN tab, long flag, long prec);
 GEN  sumnumalt0(GEN a, GEN sig, GEN code, GEN tab, long flag, long prec);
-GEN  sumnuminit0(GEN a, GEN tab, long sgn, long prec);
 GEN  sumpos0(GEN a, GEN code, long flag,long prec);
 GEN  vecexpr0(GEN nmax, GEN code, GEN pred);
 GEN  vecexpr1(GEN nmax, GEN code, GEN pred);
@@ -136,9 +133,9 @@ void mt_init_stack(size_t s);
 int  mt_is_thread(void);
 GEN  parapply_worker(GEN d, GEN code);
 GEN  pareval_worker(GEN code);
-void parfor(GEN a, GEN b, GEN code, GEN code2);
+void parfor0(GEN a, GEN b, GEN code, GEN code2);
 GEN  parfor_worker(GEN i, GEN C);
-void parforprime(GEN a, GEN b, GEN code, GEN code2);
+void parforprime0(GEN a, GEN b, GEN code, GEN code2);
 GEN  parvector_worker(GEN i, GEN C);
 
 /* multiprecision */
@@ -230,7 +227,6 @@ GEN  RgXQ_minpoly_naive(GEN y, GEN P);
 GEN lift_intern(GEN x);
 
 /* c) factorization */
-double cauchy_bound(GEN p);
 GEN chk_factors_get(GEN lt, GEN famod, GEN c, GEN T, GEN N);
 long cmbf_maxK(long nb);
 GEN ZX_DDF(GEN x);
@@ -262,6 +258,54 @@ enum { FF_CARD = 1, FF_GROUP, FF_GROUPGEN, FF_O };
 /* for Buchall_param */
 enum { fupb_NONE, fupb_RELAT, fupb_LARGE, fupb_PRECI };
 
+/*
+ * Represents the data in the equation(s)
+ *
+ *   4p = t^2 - v^2 D = t^2 - v^2 u^2 D_K = w^2 D_K.
+ *
+ * t is the absolute trace, so always > 0.
+ * T is a twisting parameter, which satisfies (T|p) == -1.
+ * factw is the factorisation of w
+ * u_levels[i] is the valuation of u at the ith factor of w,
+ * i.e. the level of D in the ith volcano.
+ * vdepths[i] is the depth of the ith volcano.
+ */
+typedef struct {
+  long D;
+  long t, u, v, w;
+  ulong p, pi;
+  ulong T;
+  GEN factw;
+  GEN u_levels;
+  GEN vdepths;
+} norm_eqn_struct;
+typedef norm_eqn_struct norm_eqn_t[1];
+
+/* Isogeny volcanos */
+long j_level_in_volcano(
+  GEN phi, ulong j, ulong p, ulong pi, long L, long depth);
+ulong ascend_volcano(
+  GEN phi, ulong j, ulong p, ulong pi, long level, long L, long depth,
+  long steps);
+ulong descend_volcano(
+  GEN phi, ulong j, ulong p, ulong pi, long level, long L, long depth,
+  long steps);
+long walk_surface_path(
+  ulong path[], GEN phi, ulong p, ulong pi, long L, long depth,
+  long max_len);
+GEN enum_j_with_endo_ring(
+  ulong j0, norm_eqn_t ne, GEN *mpdb, GEN pcp, long max_elts);
+
+/* Polmodular database maintenance */
+GEN polmodular_db_init(GEN levels);
+void polmodular_db_clear(GEN db);
+GEN polmodular_db_get(GEN *db, long L);
+GEN polmodular_db_getp(GEN *db, long L, ulong p);
+
+void random_curves_with_m_torsion(
+  ulong *a4, ulong *a6, ulong *tx, ulong *ty,
+  long ncurves, long m, ulong p);
+
 /* Allocation / gerepile */
 void   setdebugvar(long n);
 void   debug_stack(void);
@@ -285,13 +329,12 @@ is_keyword_char(char c) { return (isalnum((int)c) || c=='_'); }
 /* Interfaces (GP, etc.) */
 hashtable *hash_from_link(GEN e, GEN names, int use_stack);
 void gen_relink(GEN x, hashtable *table);
-entree* is_entry_intern(const char *s, entree **table, long *hash);
 entree* do_alias(entree *ep);
 char* get_sep(const char *t);
 long get_int(const char *s, long dflt);
 ulong get_uint(const char *s);
 int  gp_init_functions(void);
-GEN  pari_compile_str(char *lex, int strict);
+void gp_initrc(pari_stack *p_A);
 
 void pari_sigint(const char *s);
 pariFILE *pari_last_tmp_file(void);
@@ -311,44 +354,12 @@ int   term_width(void);
 void  whatnow_new_syntax(const char *f, long n);
 /* gp_colors */
 void decode_color(long n, long *c);
-extern GEN pari_colormap, pari_graphcolors;
 
 /* defaults */
-extern ulong precreal;
-
-/* history */
-typedef struct {
-  GEN z; /* result */
-  time_t t; /* time to obtain result */
-} gp_hist_cell;
-typedef struct {
-  gp_hist_cell *v; /* array of previous results, FIFO */
-  size_t size; /* # res */
-  ulong total; /* # of results computed since big bang */
-} gp_hist;
-
-/* prettyprinter */
-typedef struct {
-  pariFILE *file;
-  char *cmd;
-} gp_pp;
-
-/* path */
-typedef struct {
-  char *PATH;
-  char **dirs;
-} gp_path;
-
-/* for output */
-typedef struct {
-  char format; /* e,f,g */
-  long sigd;   /* -1 (all) or number of significant digits printed */
-  int sp;      /* 0 = suppress whitespace from output */
-  int prettyp; /* output style: raw, prettyprint, etc */
-  int TeXstyle;
-} pariout_t;
+extern long precreal;
 
 void lim_lines_output(char *s, long n, long max);
+int tex2mail_output(GEN z, long n);
 void gen_output(GEN x, pariout_t *T);
 void fputGEN_pariout(GEN x, pariout_t *T, FILE *out);
 
@@ -365,6 +376,8 @@ void evalstate_reset(void);
 void evalstate_restore(struct pari_evalstate *state);
 GEN  evalstate_restore_err(struct pari_evalstate *state);
 void evalstate_save(struct pari_evalstate *state);
+void varstate_save(struct pari_varstate *s);
+void varstate_restore(struct pari_varstate *s);
 
 void mtstate_save(long *pending);
 void mtstate_reset(void);
@@ -372,23 +385,6 @@ void mtstate_restore(long *pending);
 
 void debug_context(void);
 
-/* GP_DATA */
-typedef struct {
-  gp_hist *hist;
-  gp_pp *pp;
-  gp_path *path, *sopath;
-  pariout_t *fmt;
-  ulong lim_lines, flags, linewrap;
-  int echo, breakloop, recover, use_readline; /* GP-specific */
-  int secure, simplify, strictmatch, strictargs, chrono; /* libpari ? */
-  pari_timer *T;
-  ulong primelimit; /* deprecated */
-  ulong threadsize;
-} gp_data;
-extern gp_data *GP_DATA;
-  /* GP_DATA->flags */
-enum { gpd_QUIET=1, gpd_TEST=2, gpd_EMACS=256, gpd_TEXMACS=512};
-
 typedef struct {
   const char *s;
   size_t ls;
@@ -405,11 +401,6 @@ extern char *current_logfile;
 extern long    gp_colors[];
 extern int     disable_color;
 
-/* backward compatibility */
-extern ulong compatible;
-enum { NONE, WARN, OLDFUN, OLDALL };
-#define new_fun_set (compatible == NONE || compatible == WARN)
-
 /* entrees */
 #define EpVALENCE(ep) ((ep)->valence & 0xFF)
 #define EpSTATIC(ep) ((ep)->valence & 0x100)
@@ -421,7 +412,6 @@ enum { EpNEW = 100, EpALIAS, EpVAR, EpINSTALL };
 extern const long functions_tblsz;  /* hashcodes table size */
 extern entree **functions_hash;   /* functions hashtable */
 extern entree **defaults_hash;    /* defaults hashtable */
-extern entree oldfonctions[];
 
 /* buffers */
 typedef struct Buffer {
@@ -436,15 +426,26 @@ void fix_buffer(Buffer *b, long newlbuf);
 typedef struct {
   const char *s; /* source */
   char *t, *end; /* target, last char read */
-  int in_string, in_comment, more_input, wait_for_brace, downcase;
+  int in_string, in_comment, more_input, wait_for_brace;
   Buffer *buf;
 } filtre_t;
 void init_filtre(filtre_t *F, Buffer *buf);
-char *filtre(const char *s, int flag);
-void check_filtre(filtre_t *F);
+Buffer *filtered_buffer(filtre_t *F);
+const char *break_loop_prompt(long n);
+void kill_buffers_upto_including(Buffer *B);
+void pop_buffer(void);
+void kill_buffers_upto(Buffer *B);
+int gp_read_line(filtre_t *F, const char *PROMPT);
+void parse_key_val(char *src, char **ps, char **pt);
+void pari_init_buffers(void);
+extern int (*cb_pari_get_line_interactive)(const char*, const char*, filtre_t *F);
+extern char *(*cb_pari_fgets_interactive)(char *s, int n, FILE *f);
+int get_line_from_file(const char *prompt, filtre_t *F, FILE *file);
+void pari_skip_space(char **s);
+void pari_skip_alpha(char **s);
+char *pari_translate_string(const char *src, char *s, char *entry);
 
 gp_data *default_gp_data(void);
-GEN  gp_history(gp_hist *H, long p, char *old, char *entry);
 
 void delete_dirs(gp_path *p);
 void gp_expand_path(gp_path *p);
@@ -468,9 +469,6 @@ char *file_getline(Buffer *b, char **s0, input_method *IM);
 
 /* By files */
 
-/* FpE.c */
-long Fl_elltrace_CM(int CM, ulong a4, ulong a6, ulong p);
-
 /* Qfb.c */
 
 GEN     redimagsl2(GEN q, GEN *U);
@@ -496,15 +494,12 @@ long    set_optimize(long what, GEN g);
 /* base2.c */
 
 GEN     gen_if_principal(GEN bnf, GEN x);
-int     nfissquarefree(GEN nf, GEN x);
 GEN     polsymmodp(GEN g, GEN p);
-GEN     nfbasis_gp(GEN T, GEN P, GEN junk);
-GEN     nfdisc_gp(GEN T, GEN P, GEN junk);
+GEN     nfbasis_gp(GEN T);
 
 /* base3.c */
 
 void    check_nfelt(GEN x, GEN *den);
-long    nfvalrem(GEN nf, GEN x, GEN pr, GEN *py);
 GEN     zk_ei_mul(GEN nf, GEN x, long i);
 
 /* base4.c */
@@ -517,8 +512,7 @@ long    val_norm(GEN x, GEN p, long *vz);
 
 /* base5.c */
 
-GEN     check_and_build_nfabs(GEN rnf);
-GEN     check_and_build_norms(GEN rnf);
+GEN     check_and_build_nfabs(GEN rnf, long prec);
 
 /* buch1.c */
 
@@ -565,9 +559,14 @@ void    pari_close_files(void);
 int     popinfile(void);
 pariFILE* try_pipe(const char *cmd, int flag);
 
+/* Flx.c */
+
+GEN FlxqM_mul_Kronecker(GEN A, GEN B, GEN T, ulong p);
+
 /* Flxq_log.c */
 
 GEN Flxq_log_index(GEN a0, GEN b0, GEN m, GEN T0, ulong p);
+int Flxq_log_use_index(GEN m, GEN T0, ulong p);
 
 /* FlxqE.c */
 
@@ -581,7 +580,6 @@ long    intheadlong(GEN x, GEN mod);
 GEN     listznstarelts(long m, long p);
 GEN     matheadlong(GEN W, GEN mod);
 GEN     matrixnorm(GEN M, long prec);
-GEN     monomorphismlift(GEN P, GEN S, GEN Q, GEN p, long e);
 long    polheadlong(GEN P, long n, GEN mod);
 GEN     vandermondeinverseprep(GEN L);
 
@@ -603,6 +601,10 @@ GEN     gsubst_expr(GEN pol, GEN from, GEN to);
 GEN     poltoser(GEN x, long v, long prec);
 GEN     rfractoser(GEN x, long v, long prec);
 
+/* hyperell.c */
+
+GEN     ZlXQX_hyperellpadicfrobenius(GEN H, GEN T, ulong p, long n);
+
 /* ifactor1.c */
 
 GEN     ellfacteur(GEN n, int insist);
@@ -623,7 +625,6 @@ int     uisprime_661(ulong n);
 /* init.c */
 
 void    pari_init_defaults(void);
-void    pari_init_stack(size_t size, size_t old);
 
 /* nffactor.c */
 
@@ -662,6 +663,10 @@ void    factor_quad(GEN x, GEN res, long *ptcnt);
 
 /* FpX.c */
 
+ulong   Flj_order_ufact(GEN P, ulong n, GEN F, ulong a4, ulong p, ulong pi);
+
+/* FpX.c */
+
 GEN     FpX_gcd_check(GEN x, GEN y, GEN p);
 
 /* polarit3.c */
diff --git a/src/headers/paristio.h b/src/headers/paristio.h
index 824d3d3..5ff7bdf 100644
--- a/src/headers/paristio.h
+++ b/src/headers/paristio.h
@@ -77,10 +77,12 @@ typedef struct GENbin {
 
 struct pari_mainstack
 {
-  pari_sp top, bot, avma;
-  size_t memused;
+  pari_sp top, bot, vbot;
+  size_t size, rsize, vsize, memused;
 };
 
+extern THREAD struct pari_mainstack *pari_mainstack;
+
 struct pari_thread
 {
   struct pari_mainstack st;
@@ -106,6 +108,7 @@ typedef struct entree {
   const char *help;
   void *pvalue;
   long arity;
+  ulong hash;
   struct entree *next;
 } entree;
 
@@ -114,7 +117,7 @@ struct pari_parsestate
   long node;
   int once;
   long discarded;
-  const char *lex_start, *unused_chars;
+  const char *lex_start;
   GEN lasterror;
 };
 
@@ -132,15 +135,22 @@ struct pari_evalstate
   long rp;
   long var;
   long lvars;
+  long prec;
   long trace;
   long pending_threads;
   struct pari_compilestate comp;
 };
 
+struct pari_varstate
+{
+  long nvar, max_avail, min_priority, max_priority;
+};
+
 struct gp_context
 {
   long listloc;
   long prettyp;
+  struct pari_varstate var;
   struct pari_evalstate eval;
   struct pari_parsestate parse;
   pariFILE *file;
@@ -193,6 +203,53 @@ typedef struct {
   size_t size;
 } pari_stack;
 
+/* GP_DATA */
+typedef struct {
+  GEN z; /* result */
+  time_t t; /* time to obtain result */
+} gp_hist_cell;
+typedef struct {
+  gp_hist_cell *v; /* array of previous results, FIFO */
+  size_t size; /* # res */
+  ulong total; /* # of results computed since big bang */
+} gp_hist; /* history */
+
+typedef struct {
+  pariFILE *file;
+  char *cmd;
+} gp_pp; /* prettyprinter */
+
+typedef struct {
+  char *PATH;
+  char **dirs;
+} gp_path; /* path */
+typedef struct {
+  char format; /* e,f,g */
+  long sigd;   /* -1 (all) or number of significant digits printed */
+  int sp;      /* 0 = suppress whitespace from output */
+  int prettyp; /* output style: raw, prettyprint, etc */
+  int TeXstyle;
+} pariout_t; /* output format */
+
+enum { gpd_QUIET=1, gpd_TEST=2, gpd_EMACS=256, gpd_TEXMACS=512};
+enum { DO_MATCHED_INSERT = 2, DO_ARGS_COMPLETE = 4 };
+typedef struct {
+  gp_hist *hist;
+  gp_pp *pp;
+  gp_path *path, *sopath;
+  pariout_t *fmt;
+  ulong lim_lines, flags, linewrap, readline_state;
+  int echo, breakloop, recover, use_readline;
+  char *help, *histfile, *prompt, *prompt_cont, *prompt_comment;
+  GEN colormap, graphcolors;
+
+  int secure, simplify, strictmatch, strictargs, chrono;
+  pari_timer *T;
+  ulong primelimit; /* deprecated */
+  ulong threadsizemax, threadsize;
+} gp_data;
+extern gp_data *GP_DATA;
+
 /* Common global variables: */
 
 extern PariOUT *pariOut, *pariErr;
@@ -211,32 +268,31 @@ enum { c_ERR, c_HIST, c_PROMPT, c_INPUT, c_OUTPUT, c_HELP, c_TIME, c_LAST,
 
 enum { TEXSTYLE_PAREN=2, TEXSTYLE_BREAK=4 };
 
-extern THREAD pari_sp avma, bot, top;
+extern THREAD pari_sp avma;
 #define DISABLE_MEMUSED (size_t)-1
-extern THREAD size_t memused;
 extern byteptr diffptr;
 extern char *current_psfile, *pari_datadir;
 
 #define gcopyifstack(x,y)  STMT_START {pari_sp _t=(pari_sp)(x); \
-  (y)=(_t>=bot &&_t<top)? gcopy((GEN)_t): (GEN)_t;} STMT_END
+  (y)=(_t>=pari_mainstack->bot &&_t<pari_mainstack->top)? \
+      gcopy((GEN)_t): (GEN)_t;} STMT_END
 #define copyifstack(x,y)  STMT_START {pari_sp _t=(pari_sp)(x); \
-  (y)=(_t>=bot &&_t<top)? gcopy((GEN)_t): (GEN)_t;} STMT_END
+  (y)=(_t>=pari_mainstack->bot &&_t<pari_mainstack->top)? \
+      gcopy((GEN)_t): (GEN)_t;} STMT_END
 #define icopyifstack(x,y) STMT_START {pari_sp _t=(pari_sp)(x); \
-  (y)=(_t>=bot &&_t<top)? icopy((GEN)_t): (GEN)_t;} STMT_END
+  (y)=(_t>=pari_mainstack->bot &&_t<pari_mainstack->top)? \
+      icopy((GEN)_t): (GEN)_t;} STMT_END
 
-/* Define this to (1) locally (in a given file, NOT here) to check
- * "random" garbage collecting */
+/* Define this to thoroughly check "random" garbage collecting */
 #ifdef DEBUG_LOWSTACK
 #  define low_stack(x,l) 1
+#  define gc_needed(av,n) 1
 #else
-#ifdef DYNAMIC_STACK
-#  define low_stack(x,l) (avma < (pari_sp)(l))
-#else
-#  define low_stack(x,l) (avma < (pari_sp)(x))
-#endif
+#  define low_stack(x,l) ((void)(x),avma < (pari_sp)(l))
+#  define gc_needed(av,n) (avma < (pari_sp)stack_lim(av,n))
 #endif
 
-#define stack_lim(av,n) (bot + (((av)-bot)>>(n)))
+#define stack_lim(av,n) (pari_mainstack->bot+(((av)-pari_mainstack->bot)>>(n)))
 
 #ifndef SIG_IGN
 #  define SIG_IGN (void(*)())1
diff --git a/src/headers/parisys.h b/src/headers/parisys.h
index 5b68599..a21fe4c 100644
--- a/src/headers/parisys.h
+++ b/src/headers/parisys.h
@@ -73,7 +73,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  * longjmp'ing into another thread's stack will utterly confuse the system.
  * Instead, we check whether win32ctrlc is set in new_chunk(). */
 BEGINEXTERN
-  extern int win32ctrlc;
+  extern int win32ctrlc, win32alrm;
   void dowin32ctrlc(void);
 ENDEXTERN
 #define CHECK_CTRLC if (win32ctrlc) dowin32ctrlc();
diff --git a/src/headers/paritune.h b/src/headers/paritune.h
index 025cc3c..acb0d02 100644
--- a/src/headers/paritune.h
+++ b/src/headers/paritune.h
@@ -1,81 +1,93 @@
 #define PARI_TUNE
 
 #ifdef PARI_TUNE
-extern long SQRI_KARATSUBA_LIMIT;
-extern long MULII_KARATSUBA_LIMIT;
-extern long MULRR_MULII_LIMIT;
-extern long SQRI_FFT_LIMIT;
-extern long MULII_FFT_LIMIT;
-extern long Fp_POW_REDC_LIMIT;
-extern long Fp_POW_BARRETT_LIMIT;
-extern long INVMOD_GMP_LIMIT;
+extern long AGM_ATAN_LIMIT;
 extern long DIVRR_GMP_LIMIT;
-extern long Flx_MUL_KARATSUBA_LIMIT;
-extern long Flx_SQR_KARATSUBA_LIMIT;
+extern long EXPNEWTON_LIMIT;
+extern long Flx_BARRETT_HALFMULII_LIMIT;
+extern long Flx_BARRETT_KARATSUBA_LIMIT;
+extern long Flx_BARRETT_MULII2_LIMIT;
+extern long Flx_BARRETT_MULII_LIMIT;
+extern long Flx_DIVREM_BARRETT_LIMIT;
+extern long Flx_EXTGCD_LIMIT;
+extern long Flx_GCD_LIMIT;
+extern long Flx_HALFGCD_LIMIT;
+extern long Flx_INVBARRETT_HALFMULII_LIMIT;
+extern long Flx_INVBARRETT_KARATSUBA_LIMIT;
+extern long Flx_INVBARRETT_MULII2_LIMIT;
+extern long Flx_INVBARRETT_MULII_LIMIT;
 extern long Flx_MUL_HALFMULII_LIMIT;
-extern long Flx_SQR_HALFSQRI_LIMIT;
-extern long Flx_MUL_MULII_LIMIT;
-extern long Flx_SQR_SQRI_LIMIT;
+extern long Flx_MUL_KARATSUBA_LIMIT;
 extern long Flx_MUL_MULII2_LIMIT;
-extern long Flx_SQR_SQRI2_LIMIT;
-extern long Flx_INVBARRETT_LIMIT;
-extern long Flx_DIVREM_BARRETT_LIMIT;
+extern long Flx_MUL_MULII_LIMIT;
 extern long Flx_REM_BARRETT_LIMIT;
-extern long Flx_BARRETT_LIMIT;
-extern long Flx_HALFGCD_LIMIT;
-extern long Flx_GCD_LIMIT;
-extern long Flx_EXTGCD_LIMIT;
-extern long FpX_INVBARRETT_LIMIT;
-extern long FpX_DIVREM_BARRETT_LIMIT;
-extern long FpX_REM_BARRETT_LIMIT;
+extern long Flx_SQR_HALFSQRI_LIMIT;
+extern long Flx_SQR_KARATSUBA_LIMIT;
+extern long Flx_SQR_SQRI2_LIMIT;
+extern long Flx_SQR_SQRI_LIMIT;
 extern long FpX_BARRETT_LIMIT;
-extern long FpX_HALFGCD_LIMIT;
-extern long FpX_GCD_LIMIT;
+extern long FpX_DIVREM_BARRETT_LIMIT;
 extern long FpX_EXTGCD_LIMIT;
-extern long EXPNEWTON_LIMIT;
+extern long FpX_GCD_LIMIT;
+extern long FpX_HALFGCD_LIMIT;
+extern long FpX_INVBARRETT_LIMIT;
+extern long FpX_REM_BARRETT_LIMIT;
+extern long Fp_POW_BARRETT_LIMIT;
+extern long Fp_POW_REDC_LIMIT;
+extern long INVMOD_GMP_LIMIT;
 extern long INVNEWTON_LIMIT;
-extern long LOGAGM_LIMIT;
 extern long LOGAGMCX_LIMIT;
-extern long AGM_ATAN_LIMIT;
-extern long RgX_SQR_LIMIT;
+extern long LOGAGM_LIMIT;
+extern long MULII_FFT_LIMIT;
+extern long MULII_KARATSUBA_LIMIT;
+extern long MULRR_MULII_LIMIT;
 extern long RgX_MUL_LIMIT;
+extern long RgX_SQR_LIMIT;
+extern long SQRI_FFT_LIMIT;
+extern long SQRI_KARATSUBA_LIMIT;
 #else
-#  define SQRI_KARATSUBA_LIMIT     __SQRI_KARATSUBA_LIMIT
-#  define MULII_KARATSUBA_LIMIT    __MULII_KARATSUBA_LIMIT
-#  define MULRR_MULII_LIMIT        __MULRR_MULII_LIMIT
-#  define SQRI_FFT_LIMIT           __SQRI_FFT_LIMIT
-#  define MULII_FFT_LIMIT          __MULII_FFT_LIMIT
-#  define Fp_POW_REDC_LIMIT        __Fp_POW_REDC_LIMIT
-#  define Fp_POW_BARRETT_LIMIT     __Fp_POW_BARRETT_LIMIT
-#  define INVMOD_GMP_LIMIT         __INVMOD_GMP_LIMIT
-#  define DIVRR_GMP_LIMIT          __DIVRR_GMP_LIMIT
-#  define EXPNEWTON_LIMIT          __EXPNEWTON_LIMIT
-#  define INVNEWTON_LIMIT          __INVNEWTON_LIMIT
-#  define LOGAGM_LIMIT             __LOGAGM_LIMIT
-#  define LOGAGMCX_LIMIT           __LOGAGMCX_LIMIT
-#  define AGM_ATAN_LIMIT           __AGM_ATAN_LIMIT
-#  define Flx_MUL_KARATSUBA_LIMIT  __Flx_MUL_KARATSUBA_LIMIT
-#  define Flx_SQR_KARATSUBA_LIMIT  __Flx_SQR_KARATSUBA_LIMIT
-#  define Flx_MUL_HALFMULII_LIMIT  __Flx_MUL_HALFMULII_LIMIT
-#  define Flx_SQR_HALFSQRI_LIMIT   __Flx_SQR_HALFSQRI_LIMIT
-#  define Flx_MUL_MULII_LIMIT      __Flx_MUL_MULII_LIMIT
-#  define Flx_SQR_SQRI_LIMIT       __Flx_SQR_SQRI_LIMIT
-#  define Flx_MUL_MULII2_LIMIT     __Flx_MUL_MULII2_LIMIT
-#  define Flx_SQR_SQRI2_LIMIT      __Flx_SQR_SQRI2_LIMIT
-#  define Flx_INVBARRETT_LIMIT     __Flx_INVBARRETT_LIMIT
-#  define Flx_DIVREM_BARRETT_LIMIT __Flx_DIVREM_BARRETT_LIMIT
-#  define Flx_REM_BARRETT_LIMIT    __Flx_REM_BARRETT_LIMIT
-#  define Flx_BARRETT_LIMIT        __Flx_BARRETT_LIMIT
-#  define Flx_HALFGCD_LIMIT        __Flx_HALFGCD_LIMIT
-#  define Flx_GCD_LIMIT            __Flx_GCD_LIMIT
-#  define Flx_EXTGCD_LIMIT         __Flx_EXTGCD_LIMIT
-#  define FpX_INVBARRETT_LIMIT     __FpX_INVBARRETT_LIMIT
-#  define FpX_DIVREM_BARRETT_LIMIT __FpX_DIVREM_BARRETT_LIMIT
-#  define FpX_REM_BARRETT_LIMIT    __FpX_REM_BARRETT_LIMIT
-#  define FpX_BARRETT_LIMIT        __FpX_BARRETT_LIMIT
-#  define FpX_HALFGCD_LIMIT        __FpX_HALFGCD_LIMIT
-#  define FpX_GCD_LIMIT            __FpX_GCD_LIMIT
-#  define FpX_EXTGCD_LIMIT         __FpX_EXTGCD_LIMIT
-#  define RgX_SQR_LIMIT            __RgX_SQR_LIMIT
-#  define RgX_MUL_LIMIT            __RgX_MUL_LIMIT
+#  define AGM_ATAN_LIMIT                 __AGM_ATAN_LIMIT
+#  define DIVRR_GMP_LIMIT                __DIVRR_GMP_LIMIT
+#  define EXPNEWTON_LIMIT                __EXPNEWTON_LIMIT
+#  define Flx_BARRETT_HALFMULII_LIMIT    __Flx_BARRETT_HALFMULII_LIMIT
+#  define Flx_BARRETT_KARATSUBA_LIMIT    __Flx_BARRETT_KARATSUBA_LIMIT
+#  define Flx_BARRETT_MULII2_LIMIT       __Flx_BARRETT_MULII2_LIMIT
+#  define Flx_BARRETT_MULII_LIMIT        __Flx_BARRETT_MULII_LIMIT
+#  define Flx_DIVREM_BARRETT_LIMIT       __Flx_DIVREM_BARRETT_LIMIT
+#  define Flx_EXTGCD_LIMIT               __Flx_EXTGCD_LIMIT
+#  define Flx_GCD_LIMIT                  __Flx_GCD_LIMIT
+#  define Flx_HALFGCD_LIMIT              __Flx_HALFGCD_LIMIT
+#  define Flx_INVBARRETT_HALFMULII_LIMIT __Flx_INVBARRETT_HALFMULII_LIMIT
+#  define Flx_INVBARRETT_KARATSUBA_LIMIT __Flx_INVBARRETT_KARATSUBA_LIMIT
+#  define Flx_INVBARRETT_MULII2_LIMIT    __Flx_INVBARRETT_MULII2_LIMIT
+#  define Flx_INVBARRETT_MULII_LIMIT     __Flx_INVBARRETT_MULII_LIMIT
+#  define Flx_MUL_HALFMULII_LIMIT        __Flx_MUL_HALFMULII_LIMIT
+#  define Flx_MUL_KARATSUBA_LIMIT        __Flx_MUL_KARATSUBA_LIMIT
+#  define Flx_MUL_MULII2_LIMIT           __Flx_MUL_MULII2_LIMIT
+#  define Flx_MUL_MULII_LIMIT            __Flx_MUL_MULII_LIMIT
+#  define Flx_REM_BARRETT_LIMIT          __Flx_REM_BARRETT_LIMIT
+#  define Flx_SQR_HALFSQRI_LIMIT         __Flx_SQR_HALFSQRI_LIMIT
+#  define Flx_SQR_KARATSUBA_LIMIT        __Flx_SQR_KARATSUBA_LIMIT
+#  define Flx_SQR_SQRI2_LIMIT            __Flx_SQR_SQRI2_LIMIT
+#  define Flx_SQR_SQRI_LIMIT             __Flx_SQR_SQRI_LIMIT
+#  define FpX_BARRETT_LIMIT              __FpX_BARRETT_LIMIT
+#  define FpX_DIVREM_BARRETT_LIMIT       __FpX_DIVREM_BARRETT_LIMIT
+#  define FpX_EXTGCD_LIMIT               __FpX_EXTGCD_LIMIT
+#  define FpX_GCD_LIMIT                  __FpX_GCD_LIMIT
+#  define FpX_HALFGCD_LIMIT              __FpX_HALFGCD_LIMIT
+#  define FpX_INVBARRETT_LIMIT           __FpX_INVBARRETT_LIMIT
+#  define FpX_REM_BARRETT_LIMIT          __FpX_REM_BARRETT_LIMIT
+#  define Fp_POW_BARRETT_LIMIT           __Fp_POW_BARRETT_LIMIT
+#  define Fp_POW_REDC_LIMIT              __Fp_POW_REDC_LIMIT
+#  define INVMOD_GMP_LIMIT               __INVMOD_GMP_LIMIT
+#  define INVNEWTON_LIMIT                __INVNEWTON_LIMIT
+#  define LOGAGMCX_LIMIT                 __LOGAGMCX_LIMIT
+#  define LOGAGM_LIMIT                   __LOGAGM_LIMIT
+#  define MULII_FFT_LIMIT                __MULII_FFT_LIMIT
+#  define MULII_KARATSUBA_LIMIT          __MULII_KARATSUBA_LIMIT
+#  define MULRR_MULII_LIMIT              __MULRR_MULII_LIMIT
+#  define RgX_MUL_LIMIT                  __RgX_MUL_LIMIT
+#  define RgX_SQR_LIMIT                  __RgX_SQR_LIMIT
+#  define SQRI_FFT_LIMIT                 __SQRI_FFT_LIMIT
+#  define SQRI_KARATSUBA_LIMIT           __SQRI_KARATSUBA_LIMIT
 #endif
diff --git a/src/kernel/alpha/asm1.h b/src/kernel/alpha/asm1.h
index 7f6eda0..a363769 100644
--- a/src/kernel/alpha/asm1.h
+++ b/src/kernel/alpha/asm1.h
@@ -12,7 +12,7 @@ with the package; see the file 'COPYING'. If not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 
 /* This file is a slight adaptation of source code extracted from gmp-3.1.1
-  (from T. Granlund), files longlong.h and gmp-e_IMPL.h
+  (from T. Granlund), files longlong.h and gmp-impl.h
 
   Copyright (C) 2000 Free Software Foundation, Inc.
 
diff --git a/src/kernel/gmp/mp.c b/src/kernel/gmp/mp.c
index eff7751..16d703a 100644
--- a/src/kernel/gmp/mp.c
+++ b/src/kernel/gmp/mp.c
@@ -209,7 +209,7 @@ adduispec(ulong s, GEN x, long nx)
   GEN  zd;
   long lz;
 
-  if (nx == 1) return adduu((ulong)x[0], s);
+  if (nx == 1) return adduu(uel(x,0), s);
   lz = nx+3; zd = cgeti(lz);
   if (mpn_add_1(LIMBS(zd),(mp_limb_t *)x,nx,s))
     zd[lz-1]=1;
@@ -313,7 +313,7 @@ affir(GEN x, GEN y)
       return;
     }
     mpn_lshift(LIMBS(y),LIMBS(x)+lx-ly,ly-2,sh);
-    y[2]|=((ulong) x[lx-ly+1])>>(BITS_IN_LONG-sh);
+    y[2] |= uel(x,lx-ly+1) >> (BITS_IN_LONG-sh);
     xmpn_mirror(LIMBS(y),ly-2);
     /* lx > ly: round properly */
     if ((x[lx-ly+1]<<sh) & HIGHBIT) roundr_up_ip(y, ly);
@@ -405,7 +405,7 @@ mantissa2nr(GEN x, long n)
     {
       register const ulong sh = BITS_IN_LONG - m;
       shift_left(y,x, 2,lx-1, 0,m);
-      i = ((ulong)x[2]) >> sh;
+      i = uel(x,2) >> sh;
       /* Extend y on the left? */
       if (i) { ly++; y = new_chunk(1); y[2] = i; }
     }
@@ -572,7 +572,7 @@ diviu_rem(GEN y, ulong x, ulong *rem)
   if (!signe(y)) { *rem = 0; return gen_0; }
 
   ly = lgefint(y);
-  if (ly == 3 && (ulong)x > (ulong)y[2]) { *rem = (ulong)y[2]; return gen_0; }
+  if (ly == 3 && (ulong)x > uel(y,2)) { *rem = uel(y,2); return gen_0; }
 
   z = cgeti(ly);
   *rem = mpn_divrem_1(LIMBS(z), 0, LIMBS(y), NLIMBS(y), x);
@@ -592,7 +592,7 @@ divis_rem(GEN y, long x, long *rem)
   if (x<0) { s = -sy; x = -x; } else s = sy;
 
   ly = lgefint(y);
-  if (ly == 3 && (ulong)x > (ulong)y[2]) { *rem = itos(y); return gen_0; }
+  if (ly == 3 && (ulong)x > uel(y,2)) { *rem = itos(y); return gen_0; }
 
   z = cgeti(ly);
   *rem = mpn_divrem_1(LIMBS(z), 0, LIMBS(y), NLIMBS(y), x);
@@ -613,7 +613,7 @@ divis(GEN y, long x)
   if (x<0) { s = -sy; x = -x; } else s=sy;
 
   ly = lgefint(y);
-  if (ly == 3 && (ulong)x > (ulong)y[2]) return gen_0;
+  if (ly == 3 && (ulong)x > uel(y,2)) return gen_0;
 
   z = cgeti(ly);
   (void)mpn_divrem_1(LIMBS(z), 0, LIMBS(y), NLIMBS(y), x);
@@ -646,7 +646,7 @@ divrr_with_gmp(GEN x, GEN y)
   mpn_tdiv_qr(q,r,0,u,lu,z,lly);
 
   /*Round up: This is not exactly correct we should test 2*r>z*/
-  if ((ulong)r[lly-1] > ((ulong)z[lly-1]>>1))
+  if (uel(r,lly-1) > (uel(z,lly-1)>>1))
     mpn_add_1(q,q,lw+1,1);
 
   xmpn_mirrorcopy(RLIMBS(w),q,lw);
@@ -684,7 +684,7 @@ divri_with_gmp(GEN x, GEN y)
   mpn_tdiv_qr(q,r,0,u,lu,z,lly);
 
   /*Round up: This is not exactly correct we should test 2*r>z*/
-  if ((ulong)r[lly-1] > ((ulong)z[lly-1]>>1))
+  if (uel(r,lly-1) > (uel(z,lly-1)>>1))
     mpn_add_1(q,q,llx+1,1);
 
   xmpn_mirrorcopy(RLIMBS(w),q,llx);
@@ -730,7 +730,7 @@ divrr(GEN x, GEN y)
   {
     ulong k = x[2], l = (lx>3)? x[3]: 0;
     LOCAL_HIREMAINDER;
-    if (k < (ulong)y[2]) e--;
+    if (k < uel(y,2)) e--;
     else
     {
       l >>= 1; if (k&1) l |= HIGHBIT;
@@ -761,13 +761,13 @@ divrr(GEN x, GEN y)
     LOCAL_HIREMAINDER;
     LOCAL_OVERFLOW;
 
-    if ((ulong)r1[1] == y0)
+    if (uel(r1,1) == y0)
     {
       qp = ULONG_MAX; k = addll(y0,r1[2]);
     }
     else
     {
-      if ((ulong)r1[1] > y0) /* can't happen if i=0 */
+      if (uel(r1,1) > y0) /* can't happen if i=0 */
       {
         GEN y1 = y+1;
         j = lr-i; r1[j] = subll(r1[j],y1[j]);
@@ -797,9 +797,9 @@ divrr(GEN x, GEN y)
       r1[j] = subll(r1[j], addmul(qp,y[j]));
       hiremainder += overflow;
     }
-    if ((ulong)r1[1] != hiremainder)
+    if (uel(r1,1) != hiremainder)
     {
-      if ((ulong)r1[1] < hiremainder)
+      if (uel(r1,1) < hiremainder)
       {
         qp--;
         j = lr-i-(lr-i>=ly); r1[j] = addll(r1[j], y[j]);
@@ -821,7 +821,7 @@ divrr(GEN x, GEN y)
   }
   /* i = lr-1 */
   /* round correctly */
-  if ((ulong)r1[1] > (y0>>1))
+  if (uel(r1,1) > (y0>>1))
   {
     j=i; do r[--j]++; while (j && !r[j]);
   }
@@ -852,11 +852,7 @@ dvmdii(GEN x, GEN y, GEN *z)
   pari_sp av;
   GEN r,q;
 
-  if (!sy)
-  {
-    if (z == ONLY_REM && !sx) return gen_0;
-    pari_err_INV("dvmdii",y);
-  }
+  if (!sy) pari_err_INV("dvmdii",y);
   if (!sx)
   {
     if (!z || z == ONLY_REM) return gen_0;
@@ -962,17 +958,17 @@ red_montgomery(GEN T, GEN N, ulong inv)
 #endif
   if (k == 1)
   { /* as below, special cased for efficiency */
-    ulong n = (ulong)N[2];
+    ulong n = uel(N,2);
     if (d == 1) {
-      hiremainder = (ulong)T[2];
+      hiremainder = uel(T,2);
       m = hiremainder * inv;
       (void)addmul(m, n); /* t + m*n = 0 */
       return utoi(hiremainder);
     } else { /* d = 2 */
-      hiremainder = (ulong)T[2];
+      hiremainder = uel(T,2);
       m = hiremainder * inv;
       (void)addmul(m, n); /* t + m*n = 0 */
-      t = addll(hiremainder, (ulong)T[3]);
+      t = addll(hiremainder, uel(T,3));
       if (overflow) t -= n; /* t > n doesn't fit in 1 word */
       return utoi(t);
     }
@@ -1333,7 +1329,7 @@ sqrtr_abs(GEN a)
   {
     ulong u;
     b = (mp_limb_t *) mantissa2nr(a,-1);
-    b[1] = ((ulong)a[l+1])<<(BITS_IN_LONG-1);
+    b[1] = uel(a,l+1)<<(BITS_IN_LONG-1);
     b = (mp_limb_t *) new_chunk(l);
     xmpn_zero(b,l+1); /* overwrites the former b[0] */
     c = (mp_limb_t *) new_chunk(l + 1);
diff --git a/src/kernel/gmp/tune.h b/src/kernel/gmp/tune.h
index 849aeec..89d037c 100644
--- a/src/kernel/gmp/tune.h
+++ b/src/kernel/gmp/tune.h
@@ -1,79 +1,91 @@
 #ifdef LONG_IS_64BIT
-#define __MULII_KARATSUBA_LIMIT         -1
-#define __SQRI_KARATSUBA_LIMIT          -1
-#define __MULII_FFT_LIMIT               -1
-#define __SQRI_FFT_LIMIT                -1
-#define __MULRR_MULII_LIMIT             74
-#define __Fp_POW_REDC_LIMIT             17
-#define __Fp_POW_BARRETT_LIMIT         127
-#define __INVNEWTON_LIMIT              520
+#define __AGM_ATAN_LIMIT                 60
 #define __DIVRR_GMP_LIMIT                4
-#define __EXPNEWTON_LIMIT               66
-#define __LOGAGM_LIMIT                   6
-#define __LOGAGMCX_LIMIT                22
-#define __AGM_ATAN_LIMIT                60
-#define __INVMOD_GMP_LIMIT               3
-#define __Flx_MUL_KARATSUBA_LIMIT      142
-#define __Flx_SQR_KARATSUBA_LIMIT      316
+#define __EXPNEWTON_LIMIT                66
+#define __Flx_BARRETT_HALFMULII_LIMIT    21
+#define __Flx_BARRETT_KARATSUBA_LIMIT    1172
+#define __Flx_BARRETT_MULII2_LIMIT       16
+#define __Flx_BARRETT_MULII_LIMIT        448
+#define __Flx_DIVREM_BARRETT_LIMIT       768
+#define __Flx_EXTGCD_LIMIT               241
+#define __Flx_GCD_LIMIT                  1017
+#define __Flx_HALFGCD_LIMIT              81
+#define __Flx_INVBARRETT_HALFMULII_LIMIT 231
+#define __Flx_INVBARRETT_KARATSUBA_LIMIT 5067
+#define __Flx_INVBARRETT_MULII2_LIMIT    26
+#define __Flx_INVBARRETT_MULII_LIMIT     1154
 #define __Flx_MUL_HALFMULII_LIMIT        5
-#define __Flx_SQR_HALFSQRI_LIMIT         3
-#define __Flx_MUL_MULII_LIMIT            7
-#define __Flx_SQR_SQRI_LIMIT             5
+#define __Flx_MUL_KARATSUBA_LIMIT        142
 #define __Flx_MUL_MULII2_LIMIT           5
+#define __Flx_MUL_MULII_LIMIT            7
+#define __Flx_REM_BARRETT_LIMIT          1266
+#define __Flx_SQR_HALFSQRI_LIMIT         3
+#define __Flx_SQR_KARATSUBA_LIMIT        316
 #define __Flx_SQR_SQRI2_LIMIT            7
-#define __Flx_INVBARRETT_LIMIT        1142
-#define __Flx_DIVREM_BARRETT_LIMIT     768
-#define __Flx_REM_BARRETT_LIMIT       1266
-#define __Flx_BARRETT_LIMIT            398
-#define __Flx_HALFGCD_LIMIT             81
-#define __Flx_GCD_LIMIT               1017
-#define __Flx_EXTGCD_LIMIT             241
-#define __FpX_INVBARRETT_LIMIT         111
-#define __FpX_DIVREM_BARRETT_LIMIT     113
-#define __FpX_REM_BARRETT_LIMIT        111
-#define __FpX_BARRETT_LIMIT             38
-#define __FpX_HALFGCD_LIMIT             58
-#define __FpX_GCD_LIMIT                406
-#define __FpX_EXTGCD_LIMIT              87
+#define __Flx_SQR_SQRI_LIMIT             5
+#define __FpX_BARRETT_LIMIT              38
+#define __FpX_DIVREM_BARRETT_LIMIT       113
+#define __FpX_EXTGCD_LIMIT               87
+#define __FpX_GCD_LIMIT                  406
+#define __FpX_HALFGCD_LIMIT              58
+#define __FpX_INVBARRETT_LIMIT           111
+#define __FpX_REM_BARRETT_LIMIT          111
+#define __Fp_POW_BARRETT_LIMIT           127
+#define __Fp_POW_REDC_LIMIT              17
+#define __INVMOD_GMP_LIMIT               3
+#define __INVNEWTON_LIMIT                520
+#define __LOGAGMCX_LIMIT                 22
+#define __LOGAGM_LIMIT                   6
+#define __MULII_FFT_LIMIT                -1
+#define __MULII_KARATSUBA_LIMIT          -1
+#define __MULRR_MULII_LIMIT              74
 #define __RgX_MUL_LIMIT                  9
-#define __RgX_SQR_LIMIT                 38
+#define __RgX_SQR_LIMIT                  38
+#define __SQRI_FFT_LIMIT                 -1
+#define __SQRI_KARATSUBA_LIMIT           -1
 #else
-#define __MULII_KARATSUBA_LIMIT         -1
-#define __SQRI_KARATSUBA_LIMIT          -1
-#define __MULII_FFT_LIMIT               -1
-#define __SQRI_FFT_LIMIT                -1
-#define __MULRR_MULII_LIMIT              8
-#define __Fp_POW_REDC_LIMIT              3
-#define __Fp_POW_BARRETT_LIMIT          11
-#define __INVNEWTON_LIMIT               66
+#define __AGM_ATAN_LIMIT                 89
 #define __DIVRR_GMP_LIMIT                4
-#define __EXPNEWTON_LIMIT              197
-#define __LOGAGM_LIMIT                  45
-#define __LOGAGMCX_LIMIT                32
-#define __AGM_ATAN_LIMIT                89
-#define __INVMOD_GMP_LIMIT               3
-#define __Flx_MUL_KARATSUBA_LIMIT       90
-#define __Flx_SQR_KARATSUBA_LIMIT      159
+#define __EXPNEWTON_LIMIT                197
+#define __Flx_BARRETT_HALFMULII_LIMIT    23
+#define __Flx_BARRETT_KARATSUBA_LIMIT    905
+#define __Flx_BARRETT_MULII2_LIMIT       647
+#define __Flx_BARRETT_MULII_LIMIT        433
+#define __Flx_DIVREM_BARRETT_LIMIT       1289
+#define __Flx_EXTGCD_LIMIT               632
+#define __Flx_GCD_LIMIT                  2514
+#define __Flx_HALFGCD_LIMIT              321
+#define __Flx_INVBARRETT_HALFMULII_LIMIT 240
+#define __Flx_INVBARRETT_KARATSUBA_LIMIT 3600
+#define __Flx_INVBARRETT_MULII2_LIMIT    1815
+#define __Flx_INVBARRETT_MULII_LIMIT     1293
 #define __Flx_MUL_HALFMULII_LIMIT        7
-#define __Flx_SQR_HALFSQRI_LIMIT         4
+#define __Flx_MUL_KARATSUBA_LIMIT        90
+#define __Flx_MUL_MULII2_LIMIT           152
 #define __Flx_MUL_MULII_LIMIT            8
+#define __Flx_REM_BARRETT_LIMIT          689
+#define __Flx_SQR_HALFSQRI_LIMIT         4
+#define __Flx_SQR_KARATSUBA_LIMIT        159
+#define __Flx_SQR_SQRI2_LIMIT            470
 #define __Flx_SQR_SQRI_LIMIT             5
-#define __Flx_MUL_MULII2_LIMIT         152
-#define __Flx_SQR_SQRI2_LIMIT          470
-#define __Flx_INVBARRETT_LIMIT        1115
-#define __Flx_DIVREM_BARRETT_LIMIT    1289
-#define __Flx_REM_BARRETT_LIMIT        689
-#define __Flx_BARRETT_LIMIT            327
-#define __Flx_HALFGCD_LIMIT            321
-#define __Flx_GCD_LIMIT               2514
-#define __Flx_EXTGCD_LIMIT             632
-#define __FpX_INVBARRETT_LIMIT         121
-#define __FpX_DIVREM_BARRETT_LIMIT     116
-#define __FpX_REM_BARRETT_LIMIT        127
-#define __FpX_BARRETT_LIMIT             44
-#define __FpX_HALFGCD_LIMIT             55
-#define __FpX_GCD_LIMIT                414
-#define __FpX_EXTGCD_LIMIT              81
+#define __FpX_BARRETT_LIMIT              44
+#define __FpX_DIVREM_BARRETT_LIMIT       116
+#define __FpX_EXTGCD_LIMIT               81
+#define __FpX_GCD_LIMIT                  414
+#define __FpX_HALFGCD_LIMIT              55
+#define __FpX_INVBARRETT_LIMIT           121
+#define __FpX_REM_BARRETT_LIMIT          127
+#define __Fp_POW_BARRETT_LIMIT           11
+#define __Fp_POW_REDC_LIMIT              3
+#define __INVMOD_GMP_LIMIT               3
+#define __INVNEWTON_LIMIT                66
+#define __LOGAGMCX_LIMIT                 32
+#define __LOGAGM_LIMIT                   45
+#define __MULII_FFT_LIMIT                -1
+#define __MULII_KARATSUBA_LIMIT          -1
+#define __MULRR_MULII_LIMIT              8
 #define __RgX_MUL_LIMIT                  7
-#define __RgX_SQR_LIMIT                 34
+#define __RgX_SQR_LIMIT                  34
+#define __SQRI_FFT_LIMIT                 -1
+#define __SQRI_KARATSUBA_LIMIT           -1
 #endif
diff --git a/src/kernel/none/add.c b/src/kernel/none/add.c
index d76c3e5..cc3314e 100644
--- a/src/kernel/none/add.c
+++ b/src/kernel/none/add.c
@@ -183,7 +183,7 @@ addrex01(GEN x)
   long l = lg(x);
   GEN y = cgetr(l);
   y[1] = evalsigne(1) | _evalexpo(1);
-  y[2] = HIGHBIT | (((ulong)x[2] & ~HIGHBIT) >> 1);
+  y[2] = HIGHBIT | ((uel(x,2) & ~HIGHBIT) >> 1);
   shift_right(y, x, 3,l, x[2], 1);
   return y;
 }
@@ -197,7 +197,7 @@ subrex01(GEN x)
   ulong u;
   GEN y;
   k = 2;
-  u = (ulong)x[2] & (~HIGHBIT);
+  u = uel(x,2) & (~HIGHBIT);
   while (!u) u = x[++k]; /* terminates: x not a power of 2 */
   ly = (k == 2)? lx: lx - k+3; /* NB: +3, not +2: 1 extra word */
   y = cgetr(ly);
@@ -298,7 +298,7 @@ addrr_sign(GEN x, long sx, GEN y, long sy)
     if (overflow)
     {
       z[1] = 1; /* stops since z[1] != 0 */
-      for (;;) { z[i] = (ulong) y[i]+1; if (z[i--]) break; }
+      for (;;) { z[i] = uel(y,i)+1; if (z[i--]) break; }
       if (i <= 0)
       {
         shift_right(z,z, 2,lz, 1,1);
@@ -315,7 +315,7 @@ addrr_sign(GEN x, long sx, GEN y, long sy)
   {
     i = 2; while (i < lx && x[i] == y[i]) i++;
     if (i==lx) return real_0_bit(ey+1 - bit_accuracy(lx));
-    f2 = ((ulong)y[i] > (ulong)x[i]);
+    f2 = (uel(y,i) > uel(x,i));
   }
   /* result is non-zero. f2 = (y > x) */
   i = lz-1; z = cgetr(lz);
@@ -326,7 +326,7 @@ addrr_sign(GEN x, long sx, GEN y, long sy)
     else        z[i] = subll(y[i], x[j--]);
     for (i--; j>=2; i--) z[i] = subllx(y[i], x[j--]);
     if (overflow) /* stops since y[1] != 0 */
-      for (;;) { z[i] = (ulong) y[i]-1; if (y[i--]) break; }
+      for (;;) { z[i] = uel(y,i)-1; if (y[i--]) break; }
     for (; i>=2; i--) z[i] = y[i];
     sx = sy;
   }
diff --git a/src/kernel/none/addll.h b/src/kernel/none/addll.h
index 7e8082a..72b545d 100644
--- a/src/kernel/none/addll.h
+++ b/src/kernel/none/addll.h
@@ -13,7 +13,7 @@ with the package; see the file 'COPYING'. If not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 
 /* This file originally adapted from gmp-3.1.1 (from T. Granlund), files
- * longlong.h and gmp-e_IMPL.h
+ * longlong.h and gmp-impl.h
 
   Copyright (C) 2000 Free Software Foundation, Inc. */
 
diff --git a/src/kernel/none/cmp.c b/src/kernel/none/cmp.c
index 3e11ca0..3d9dfa1 100644
--- a/src/kernel/none/cmp.c
+++ b/src/kernel/none/cmp.c
@@ -46,8 +46,14 @@ equalrr(GEN x, GEN y)
 {
   long lx, ly, i;
 
-  if (!signe(x)) return signe(y) == 0; /* all zeroes are equal */
-  if (x[1] != y[1]) return 0; /* includes signe(y) = 0 */
+  if (!signe(x)) {
+    if (!signe(y)) return 1; /* all zeroes are equal */
+    return expo(x) >= expo(y);
+  }
+  if (!signe(y))
+    return expo(y) >= expo(x);
+
+  if (x[1] != y[1]) return 0;
 
   lx = lg(x);
   ly = lg(y);
@@ -72,9 +78,16 @@ cmprr(GEN x, GEN y)
   const long sx = signe(x), sy = signe(y);
   long ex,ey,lx,ly,lz,i;
 
+  if (!sx) {
+    if (!sy || expo(x) >= expo(y)) return 0;
+    return sy > 0? -1: 1;
+  }
+  if (!sy) {
+    if (expo(y) >= expo(x)) return 0;
+    return sx > 0? 1: -1;
+  }
   if (sx<sy) return -1;
   if (sx>sy) return 1;
-  if (!sx) return 0;
 
   ex=expo(x); ey=expo(y);
   if (ex>ey) return sx;
diff --git a/src/kernel/none/divll.h b/src/kernel/none/divll.h
index 1c896bc..c3e5f54 100644
--- a/src/kernel/none/divll.h
+++ b/src/kernel/none/divll.h
@@ -13,7 +13,7 @@ with the package; see the file 'COPYING'. If not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 
 /* This file originally adapted from gmp-3.1.1 (from T. Granlund), files
- * longlong.h and gmp-e_IMPL.h
+ * longlong.h and gmp-impl.h
 
   Copyright (C) 2000 Free Software Foundation, Inc. */
 
diff --git a/src/kernel/none/divll_pre.h b/src/kernel/none/divll_pre.h
new file mode 100644
index 0000000..0cef7ed
--- /dev/null
+++ b/src/kernel/none/divll_pre.h
@@ -0,0 +1,133 @@
+#line 2 "../src/kernel/none/divll_pre.h"
+/* Copyright (C) 2014  The PARI group.
+
+This file is part of the PARI/GP package.
+
+PARI/GP 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. It is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY WHATSOEVER.
+
+Check the License for details. You should have received a copy of it, along
+with the package; see the file 'COPYING'. If not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+
+#undef  LOCAL_HIREMAINDER
+extern ulong hiremainder;
+#if defined(INLINE) && defined(__GNUC__) && !defined(DISABLE_INLINE)
+#define LOCAL_HIREMAINDER register ulong hiremainder
+#else
+#define LOCAL_HIREMAINDER
+#endif
+
+#if defined(INLINE) && defined(__GNUC__) && !defined(DISABLE_INLINE)
+INLINE ulong /* precompute inverse of n */
+get_Fl_red(ulong n)
+{
+  LOCAL_HIREMAINDER;
+  n <<= bfffo(n);
+  hiremainder = ~n;
+  return divll(~0UL, n);
+}
+#else
+INLINE ulong /* precompute inverse of n */
+get_Fl_red(ulong n)
+{
+  ulong q, oldhi = hiremainder;
+  n <<= bfffo(n);
+  hiremainder = ~n;
+  q = divll(~0UL, n);
+  hiremainder = oldhi;
+  return q;
+}
+#endif
+
+INLINE ulong /* requires u1 <= n, n normalised */
+divll_pre_normalized(ulong u1, ulong u0, ulong n, ulong ninv, ulong *pt_r)
+{
+  ulong q0, q1, r;
+  LOCAL_HIREMAINDER;
+  LOCAL_OVERFLOW;
+  q0 = mulll(ninv, u1); q1 = hiremainder;
+  q0 = addll(q0, u0);
+  q1 = addllx(q1+1, u1);
+  r = u0 - q1 * n;
+  if (r > q0)
+  {
+    r += n; q1--;
+  }
+  if (r >= n)
+  {
+    r -= n; q1++;
+  }
+  *pt_r = r; return q1;
+}
+
+INLINE ulong /* requires u1 <= n, n normalised */
+remll_pre_normalized(ulong u1, ulong u0, ulong n, ulong ninv)
+{
+  ulong q0, q1, r;
+  LOCAL_HIREMAINDER;
+  LOCAL_OVERFLOW;
+  q0 = mulll(ninv, u1); q1 = hiremainder;
+  q0 = addll(q0, u0);
+  q1 = addllx(q1, u1);
+  r = u0 - (q1 + 1) * n;
+  if (r >= q0)
+    r += n;
+  return r < n ? r : r - n;
+}
+
+INLINE ulong /* reduce <a_hi, a_lo> mod n */
+remll_pre(ulong a_hi, ulong a_lo, ulong n, ulong ninv)
+{
+  int norm = bfffo(n);
+  int bits = BITS_IN_LONG - norm;
+  ulong sn = n << norm;
+  if (a_hi >= n) /* reduce a_hi first */
+  {
+    const ulong u1 = norm ? a_hi >> bits : 0;
+    const ulong u0 = a_hi << norm;
+    a_hi = remll_pre_normalized(u1, u0, sn, ninv) >> norm;
+  }
+  /* now reduce <a_hi, a_lo> */
+  {
+    const ulong u1 = ((a_hi << norm) | (norm ? a_lo >> bits: 0));
+    const ulong u0 =   a_lo << norm;
+    return remll_pre_normalized(u1, u0, sn, ninv) >> norm;
+  }
+}
+
+#if !defined(INLINE)
+extern ulong divll_pre(ulong a_lo, ulong n, ulong ninv);
+#else
+
+#if defined(__GNUC__) && !defined(DISABLE_INLINE)
+#define divll_pre(a, n, ninv)                                           \
+__extension__ ({                                                        \
+  ulong __a = (a);                                                      \
+  ulong __n = (n);                                                      \
+  int norm = bfffo(__n);                                                \
+  int bits = BITS_IN_LONG - norm;                                       \
+  ulong r, sn = __n << norm;                                            \
+  const ulong u1 = ((hiremainder << norm) | (norm ? __a >> bits: 0));   \
+  const ulong u0 = __a << norm;                                         \
+  const ulong q = divll_pre_normalized(u1, u0, sn, ninv, &r);           \
+  hiremainder = r>>norm; q;                                             \
+              })
+
+#else /* __GNUC__ */
+INLINE ulong
+divll_pre(ulong a_lo, ulong n, ulong ninv)
+{
+  int norm = bfffo(n);
+  int bits = BITS_IN_LONG - norm;
+  ulong r, sn = n << norm;
+  const ulong u1 = ((hiremainder << norm) | (norm ? a_lo >> bits: 0));
+  const ulong u0 = a_lo << norm;
+  const ulong q  = divll_pre_normalized(u1, u0, sn, ninv, &r);
+  hiremainder = r>>norm; return q;
+}
+#endif /* __GNUC__ */
+
+#endif
diff --git a/src/kernel/none/gcd.c b/src/kernel/none/gcd.c
index 19dd756..c18d863 100644
--- a/src/kernel/none/gcd.c
+++ b/src/kernel/none/gcd.c
@@ -17,10 +17,11 @@ static ulong
 resiu(GEN y, ulong x)
 {
   long i, ly = lgefint(y);
+  ulong xi = get_Fl_red(x);
   LOCAL_HIREMAINDER;
 
   hiremainder = 0;
-  for (i=2; i<ly; i++) (void)divll(y[i],x);
+  for (i=2; i<ly; i++) (void)divll_pre(y[i],x,xi);
   return hiremainder;
 }
 
diff --git a/src/kernel/none/gcdext.c b/src/kernel/none/gcdext.c
index 0926980..3cf4cda 100644
--- a/src/kernel/none/gcdext.c
+++ b/src/kernel/none/gcdext.c
@@ -31,7 +31,7 @@ bezout(GEN a, GEN b, GEN *pu, GEN *pv)
 {
   GEN t,u,u1,v,v1,d,d1,q,r;
   GEN *pt;
-  pari_sp av, av1, lim;
+  pari_sp av, av1;
   long s, sa, sb;
   ulong g;
   ulong xu,xu1,xv,xv1;                /* Lehmer stage recurrence matrix */
@@ -68,7 +68,7 @@ bezout(GEN a, GEN b, GEN *pu, GEN *pv)
 
   if (lgefint(a) == 3)                /* single-word affair */
   {
-    g = xxgcduu((ulong)a[2], (ulong)b[2], 0, &xu, &xu1, &xv, &xv1, &s);
+    g = xxgcduu(uel(a,2), uel(b,2), 0, &xu, &xu1, &xv, &xv1, &s);
     sa = s > 0 ? sa : -sa;
     sb = s > 0 ? -sb : sb;
     if (pu)
@@ -128,7 +128,7 @@ bezout(GEN a, GEN b, GEN *pu, GEN *pv)
     d = absi(a); d1 = absi(b);
     u = v1 = gen_1; u1 = v = gen_0;
   }
-  av1 = avma; lim = stack_lim(av, 1);
+  av1 = avma;
 
   /* main loop is almost identical to that of invmod() */
   while (lgefint(d) > 3 && signe(d1))
@@ -176,7 +176,7 @@ bezout(GEN a, GEN b, GEN *pu, GEN *pv)
       v=v1; v1=a;
       d=d1; d1=r;
     }
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"bezout");
       gerepileall(av1,6, &d,&d1,&u,&u1,&v,&v1);
@@ -189,7 +189,7 @@ bezout(GEN a, GEN b, GEN *pu, GEN *pv)
     /* Assertions: lgefint(d)==lgefint(d1)==3, and
      * gcd(d,d1) is nonzero and fits into one word
      */
-    g = xxgcduu((ulong)(d[2]), (ulong)(d1[2]), 0, &xu, &xu1, &xv, &xv1, &s);
+    g = xxgcduu(uel(d,2), uel(d1,2), 0, &xu, &xu1, &xv, &xv1, &s);
     u = subii(muliu(u,xu), muliu(u1, xv));
     v = subii(muliu(v,xu), muliu(v1, xv));
     if (s < 0) { sa = -sa; sb = -sb; }
diff --git a/src/kernel/none/gcdll.c b/src/kernel/none/gcdll.c
index b6f31f1..8a78f02 100644
--- a/src/kernel/none/gcdll.c
+++ b/src/kernel/none/gcdll.c
@@ -1074,6 +1074,18 @@ Fl_invsafe(ulong x, ulong p)
   return xv;
 }
 
+/* assume 0 < x < p; return u such that u x = gcd(x,p) (mod p);
+ * set *pg = gcd(x,p) */
+ulong
+Fl_invgen(ulong x, ulong p, ulong *pg)
+{
+  ulong v, v1;
+  long s;
+  *pg = xgcduu(p, x, 0, &v, &v1, &s);
+  if (s > 0) v = p - v;
+  return v;
+}
+
 /* 1 / Mod(x,p). Assume x < p */
 ulong
 Fl_inv(ulong x, ulong p)
diff --git a/src/kernel/none/invmod.c b/src/kernel/none/invmod.c
index 6fce136..c261eb9 100644
--- a/src/kernel/none/invmod.c
+++ b/src/kernel/none/invmod.c
@@ -32,7 +32,7 @@ invmod(GEN a, GEN b, GEN *res)
 #endif
 {
   GEN v,v1,d,d1,q,r;
-  pari_sp av, av1, lim;
+  pari_sp av, av1;
   long s;
   ulong g;
   ulong xu,xu1,xv,xv1; /* Lehmer stage recurrence matrix */
@@ -42,7 +42,7 @@ invmod(GEN a, GEN b, GEN *res)
   av = avma;
   if (lgefint(b) == 3) /* single-word affair */
   {
-    ulong d1 = umodiu(a, (ulong)(b[2]));
+    ulong d1 = umodiu(a, uel(b,2));
     if (d1 == 0)
     {
       if (b[2] == 1L)
@@ -50,14 +50,14 @@ invmod(GEN a, GEN b, GEN *res)
       else
         { *res = absi(b); return 0; }
     }
-    g = xgcduu((ulong)(b[2]), d1, 1, &xv, &xv1, &s);
+    g = xgcduu(uel(b,2), d1, 1, &xv, &xv1, &s);
 #ifdef DEBUG_LEHMER
-    err_printf(" <- %lu,%lu\n", (ulong)(b[2]), (ulong)(d1[2]));
+    err_printf(" <- %lu,%lu\n", uel(b,2), uel(d1,2));
     err_printf(" -> %lu,%ld,%lu; %lx\n", g,s,xv1,avma);
 #endif
     avma = av;
     if (g != 1UL) { *res = utoipos(g); return 0; }
-    xv = xv1 % (ulong)(b[2]); if (s < 0) xv = ((ulong)(b[2])) - xv;
+    xv = xv1 % uel(b,2); if (s < 0) xv = uel(b,2) - xv;
     *res = utoipos(xv); return 1;
   }
 
@@ -69,7 +69,7 @@ invmod(GEN a, GEN b, GEN *res)
   err_printf("INVERT: -------------------------\n");
   output(d1);
 #endif
-  av1 = avma; lim = stack_lim(av,1);
+  av1 = avma;
 
   while (lgefint(d) > 3 && signe(d1))
   {
@@ -124,7 +124,7 @@ invmod(GEN a, GEN b, GEN *res)
       v=v1; v1=a;
       d=d1; d1=r;
     }
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"invmod");
       gerepileall(av1, 4, &d,&d1,&v,&v1);
@@ -137,10 +137,10 @@ invmod(GEN a, GEN b, GEN *res)
     /* Assertions: lgefint(d)==lgefint(d1)==3, and
      * gcd(d,d1) is nonzero and fits into one word
      */
-    g = xxgcduu((ulong)d[2], (ulong)d1[2], 1, &xu, &xu1, &xv, &xv1, &s);
+    g = xxgcduu(uel(d,2), uel(d1,2), 1, &xu, &xu1, &xv, &xv1, &s);
 #ifdef DEBUG_LEHMER
     output(d);output(d1);output(v);output(v1);
-    err_printf(" <- %lu,%lu\n", (ulong)d[2], (ulong)d1[2]);
+    err_printf(" <- %lu,%lu\n", uel(d,2), uel(d1,2));
     err_printf(" -> %lu,%ld,%lu; %lx\n", g,s,xv1,avma);
 #endif
     if (g != 1UL) { avma = av; *res = utoipos(g); return 0; }
diff --git a/src/kernel/none/level1.h b/src/kernel/none/level1.h
index 0f8d21b..ca40aa6 100644
--- a/src/kernel/none/level1.h
+++ b/src/kernel/none/level1.h
@@ -44,6 +44,14 @@ evalprecp(long x)
   return v;
 }
 
+INLINE int
+varncmp(long x, long y)
+{
+  if (varpriority[x] < varpriority[y]) return  1;
+  if (varpriority[x] > varpriority[y]) return -1;
+  return 0;
+}
+
 /* Inhibit some area gerepile-wise: declare it to be a non recursive
  * type, of length l. Thus gerepile won't inspect the zone, just copy it.
  * For the following situation:
@@ -88,17 +96,18 @@ INLINE GEN
 new_chunk(size_t x) /* x is a number of longs */
 {
   GEN z = ((GEN) avma) - x;
-  if (x > (avma-bot) / sizeof(long)) pari_err(e_STACK);
   CHECK_CTRLC
+  if (x > (avma-pari_mainstack->bot) / sizeof(long))
+    new_chunk_resize(x);
   avma = (pari_sp)z;
-
 #ifdef MEMSTEP
-  if (DEBUGMEM && memused != DISABLE_MEMUSED) {
-    long d = (long)memused - (long)z;
-    if (d > 4*MEMSTEP || d < -4*MEMSTEP)
+  if (DEBUGMEM && pari_mainstack->memused != DISABLE_MEMUSED) {
+    long d = (long)pari_mainstack->memused - (long)z;
+    if (labs(d) > 4*MEMSTEP)
     {
-      memused = (pari_sp)z;
-      err_printf("...%4.0lf Mbytes used\n",(top-memused)/1048576.);
+      pari_mainstack->memused = (pari_sp)z;
+      err_printf("...%4.0lf Mbytes used\n",
+                (pari_mainstack->top-pari_mainstack->memused)/1048576.);
     }
   }
 #endif
@@ -387,7 +396,11 @@ cmpir(GEN x, GEN y)
   GEN z;
 
   if (!signe(x)) return -signe(y);
-  if (!signe(y)) return  signe(x);
+  if (!signe(y))
+  {
+    if (expo(y) >= expi(x)) return 0;
+    return signe(x);
+  }
   av=avma; z = itor(x, realprec(y)); avma=av;
   return cmprr(z,y); /* cmprr does no memory adjustment */
 }
@@ -600,6 +613,11 @@ smodss(long x, long y)
   long r = x%y;
   return (r >= 0)? r: labs(y) + r;
 }
+INLINE ulong
+umodsu(long x, ulong y)
+{
+  return x>=0 ? x%y: Fl_neg((-x)%y, y);
+}
 
 INLINE long
 sdivss_rem(long x, long y, long *r)
@@ -863,6 +881,44 @@ dvdiiz(GEN x, GEN y, GEN z)
   affii(p1,z); avma=av; return 1;
 }
 
+INLINE ulong
+remlll_pre(ulong u2, ulong u1, ulong u0, ulong n, ulong ninv)
+{
+  u1 = remll_pre(u2, u1, n, ninv);
+  return remll_pre(u1, u0, n, ninv);
+}
+
+INLINE ulong
+Fl_sqr_pre(ulong a, ulong p, ulong pi)
+{
+  register ulong x;
+  LOCAL_HIREMAINDER;
+  x = mulll(a,a);
+  return remll_pre(hiremainder, x, p, pi);
+}
+
+INLINE ulong
+Fl_mul_pre(ulong a, ulong b, ulong p, ulong pi)
+{
+  register ulong x;
+  LOCAL_HIREMAINDER;
+  x = mulll(a,b);
+  return remll_pre(hiremainder, x, p, pi);
+}
+
+INLINE ulong
+Fl_ellj_pre(ulong a4, ulong a6, ulong p, ulong pi)
+{
+  /* a43 = 4 a4^3 */
+  ulong a43 = Fl_double(Fl_double(
+              Fl_mul_pre(a4, Fl_sqr_pre(a4, p, pi), p, pi), p), p);
+  /* a62 = 27 a6^2 */
+  ulong a62 = Fl_mul_pre(Fl_sqr_pre(a6, p, pi), 27 % p, p, pi);
+  ulong z1 = Fl_mul_pre(a43, 1728 % p, p, pi);
+  ulong z2 = Fl_add(a43, a62, p);
+  return Fl_div(z1, z2, p);
+}
+
 /*******************************************************************/
 /*                                                                 */
 /*                        MP (INT OR REAL)                         */
@@ -931,6 +987,15 @@ Fl_triple(ulong a, ulong p)
   return (res >= p || res < a)? res - p: res;
 }
 INLINE ulong
+Fl_halve(ulong a, ulong p)
+{
+  ulong ap, ap2;
+  if ((a&1UL)==0) return a>>1;
+  ap = a + p; ap2 = ap>>1;
+  return ap>=a ? ap2: (ap2|HIGHBIT);
+}
+
+INLINE ulong
 Fl_add(ulong a, ulong b, ulong p)
 {
   ulong res = a + b;
diff --git a/src/kernel/none/mp.c b/src/kernel/none/mp.c
index 6c060c4..417bfbd 100644
--- a/src/kernel/none/mp.c
+++ b/src/kernel/none/mp.c
@@ -135,7 +135,7 @@ adduispec(ulong s, GEN x, long nx)
   GEN xd, zd = (GEN)avma;
   long lz;
 
-  if (nx == 1) return adduu(s, (ulong)x[0]);
+  if (nx == 1) return adduu(s, uel(x,0));
   lz = nx+3; (void)new_chunk(lz);
   xd = x + nx;
   *--zd = (ulong)*--xd + s;
@@ -185,7 +185,7 @@ addiispec(GEN x, GEN y, long nx, long ny)
     for(;;)
     {
       if (i < -nx) { zd[i] = 1; i--; break; } /* enlarge z */
-      zd[i] = (ulong)xd[i] + 1;
+      zd[i] = uel(xd,i) + 1;
       if (zd[i]) { i--; lz--; break; }
       i--;
     }
@@ -247,7 +247,7 @@ subiispec(GEN x, GEN y, long nx, long ny)
   if (overflow)
     for(;;)
     {
-      zd[i] = ((ulong)xd[i]) - 1;
+      zd[i] = uel(xd,i) - 1;
       if (xd[i--]) break;
     }
   if (i>=-nx)
@@ -266,7 +266,7 @@ roundr_up_ip(GEN x, long l)
   long i = l;
   for(;;)
   {
-    if (++((ulong*)x)[--i]) break;
+    if (++uel(x,--i)) break;
     if (i == 2) { x[2] = (long)HIGHBIT; shiftr_inplace(x, 1); break; }
   }
 }
@@ -328,7 +328,7 @@ shiftispec(GEN x, long nx, long n)
     {
       register const ulong sh = BITS_IN_LONG - m;
       shift_left(yd,x, 0,nx-1, 0,m);
-      i = ((ulong)x[0]) >> sh;
+      i = uel(x,0) >> sh;
       /* Extend y on the left? */
       if (i) { ny++; y = new_chunk(1); y[2] = i; }
     }
@@ -426,7 +426,7 @@ cmpiispec(GEN x, GEN y, long lx, long ly)
   if (lx > ly) return  1;
   i = 0; while (i<lx && x[i]==y[i]) i++;
   if (i==lx) return 0;
-  return ((ulong)x[i] > (ulong)y[i])? 1: -1;
+  return (uel(x,i) > uel(y,i))? 1: -1;
 }
 
 INLINE int
@@ -495,18 +495,29 @@ ulong
 umodiu(GEN y, ulong x)
 {
   long sy=signe(y),ly,i;
+  ulong xi;
   LOCAL_HIREMAINDER;
 
   if (!x) pari_err_INV("umodiu",gen_0);
   if (!sy) return 0;
   ly = lgefint(y);
-  if (x <= (ulong)y[2]) hiremainder=0;
+  if (x <= uel(y,2))
+  {
+    hiremainder=0;
+    if (ly==3)
+    {
+      hiremainder=uel(y,2)%x;
+      if (!hiremainder) return 0;
+      return (sy > 0)? hiremainder: x - hiremainder;
+    }
+  }
   else
   {
-    if (ly==3) return (sy > 0)? (ulong)y[2]: x - (ulong)y[2];
-    hiremainder=y[2]; ly--; y++;
+    if (ly==3) return (sy > 0)? uel(y,2): x - uel(y,2);
+    hiremainder=uel(y,2); ly--; y++;
   }
-  for (i=2; i<ly; i++) (void)divll(y[i],x);
+  xi = get_Fl_red(x);
+  for (i=2; i<ly; i++) (void)divll_pre(y[i],x,xi);
   if (!hiremainder) return 0;
   return (sy > 0)? hiremainder: x - hiremainder;
 }
@@ -517,20 +528,31 @@ diviu_rem(GEN y, ulong x, ulong *rem)
 {
   long ly,i;
   GEN z;
+  ulong xi;
   LOCAL_HIREMAINDER;
 
   if (!x) pari_err_INV("diviu_rem",gen_0);
   if (!signe(y)) { *rem = 0; return gen_0; }
 
   ly = lgefint(y);
-  if (x <= (ulong)y[2]) hiremainder=0;
+  if (x <= uel(y,2))
+  {
+    hiremainder=0;
+    if (ly==3)
+    {
+      z = cgetipos(3);
+      z[2] = divll(uel(y,2),x);
+      *rem = hiremainder; return z;
+    }
+  }
   else
   {
-    if (ly==3) { *rem = (ulong)y[2]; return gen_0; }
-    hiremainder=y[2]; ly--; y++;
+    if (ly==3) { *rem = uel(y,2); return gen_0; }
+    hiremainder = uel(y,2); ly--; y++;
   }
+  xi = get_Fl_red(x);
   z = cgetipos(ly);
-  for (i=2; i<ly; i++) z[i]=divll(y[i],x);
+  for (i=2; i<ly; i++) z[i]=divll_pre(y[i],x,xi);
   *rem = hiremainder; return z;
 }
 
@@ -539,6 +561,7 @@ divis_rem(GEN y, long x, long *rem)
 {
   long sy=signe(y),ly,s,i;
   GEN z;
+  ulong xi;
   LOCAL_HIREMAINDER;
 
   if (!x) pari_err_INV("divis_rem",gen_0);
@@ -546,14 +569,25 @@ divis_rem(GEN y, long x, long *rem)
   if (x<0) { s = -sy; x = -x; } else s = sy;
 
   ly = lgefint(y);
-  if ((ulong)x <= (ulong)y[2]) hiremainder=0;
+  if ((ulong)x <= uel(y,2))
+  {
+    hiremainder=0;
+    if (ly==3)
+    {
+      z = cgeti(3); z[1] = evallgefint(3) | evalsigne(s);
+      z[2] = divll(uel(y,2),x);
+      if (sy<0) hiremainder = - ((long)hiremainder);
+      *rem = (long)hiremainder; return z;
+    }
+  }
   else
   {
     if (ly==3) { *rem = itos(y); return gen_0; }
-    hiremainder=y[2]; ly--; y++;
+    hiremainder = uel(y,2); ly--; y++;
   }
+  xi = get_Fl_red(x);
   z = cgeti(ly); z[1] = evallgefint(ly) | evalsigne(s);
-  for (i=2; i<ly; i++) z[i]=divll(y[i],x);
+  for (i=2; i<ly; i++) z[i]=divll_pre(y[i],x,xi);
   if (sy<0) hiremainder = - ((long)hiremainder);
   *rem = (long)hiremainder; return z;
 }
@@ -562,6 +596,7 @@ GEN
 divis(GEN y, long x)
 {
   long sy=signe(y),ly,s,i;
+  ulong xi;
   GEN z;
   LOCAL_HIREMAINDER;
 
@@ -570,14 +605,24 @@ divis(GEN y, long x)
   if (x<0) { s = -sy; x = -x; } else s = sy;
 
   ly = lgefint(y);
-  if ((ulong)x <= (ulong)y[2]) hiremainder=0;
+  if ((ulong)x <= uel(y,2))
+  {
+    hiremainder=0;
+    if (ly==3)
+    {
+      z = cgeti(3); z[1] = evallgefint(3) | evalsigne(s);
+      z[2] = divll(y[2],x);
+      return z;
+    }
+  }
   else
   {
     if (ly==3) return gen_0;
     hiremainder=y[2]; ly--; y++;
   }
+  xi = get_Fl_red(x);
   z = cgeti(ly); z[1] = evallgefint(ly) | evalsigne(s);
-  for (i=2; i<ly; i++) z[i]=divll(y[i],x);
+  for (i=2; i<ly; i++) z[i]=divll_pre(y[i],x, xi);
   return z;
 }
 
@@ -598,7 +643,7 @@ divrr(GEN x, GEN y)
   {
     ulong k = x[2], l = (lx>3)? x[3]: 0;
     LOCAL_HIREMAINDER;
-    if (k < (ulong)y[2]) e--;
+    if (k < uel(y,2)) e--;
     else
     {
       l >>= 1; if (k&1) l |= HIGHBIT;
@@ -626,18 +671,18 @@ divrr(GEN x, GEN y)
     LOCAL_HIREMAINDER;
     LOCAL_OVERFLOW;
 
-    if ((ulong)r1[1] == y0)
+    if (uel(r1,1) == y0)
     {
       qp = ULONG_MAX; k = addll(y0,r1[2]);
     }
     else
     {
-      if ((ulong)r1[1] > y0) /* can't happen if i=0 */
+      if (uel(r1,1) > y0) /* can't happen if i=0 */
       {
         GEN y1 = y+1;
         j = lr-i; r1[j] = subll(r1[j],y1[j]);
         for (j--; j>0; j--) r1[j] = subllx(r1[j],y1[j]);
-        j=i; do ((ulong*)r)[--j]++; while (j && !r[j]);
+        j=i; do uel(r,--j)++; while (j && !uel(r,j));
       }
       hiremainder = r1[1]; overflow = 0;
       qp = divll(r1[2],y0); k = hiremainder;
@@ -662,9 +707,9 @@ divrr(GEN x, GEN y)
       r1[j] = subll(r1[j], addmul(qp,y[j]));
       hiremainder += overflow;
     }
-    if ((ulong)r1[1] != hiremainder)
+    if (uel(r1,1) != hiremainder)
     {
-      if ((ulong)r1[1] < hiremainder)
+      if (uel(r1,1) < hiremainder)
       {
         qp--;
         j = lr-i-(lr-i>=ly); r1[j] = addll(r1[j], y[j]);
@@ -686,9 +731,9 @@ divrr(GEN x, GEN y)
   }
   /* i = lr-1 */
   /* round correctly */
-  if ((ulong)r1[1] > (y0>>1))
+  if (uel(r1,1) > (y0>>1))
   {
-    j=i; do ((ulong*)r)[--j]++; while (j && !r[j]);
+    j=i; do uel(r,--j)++; while (j && !r[j]);
   }
   r1 = r-1; for (j=i; j>=2; j--) r[j]=r1[j];
   if (r[0] == 0) e--;
@@ -730,24 +775,37 @@ divri(GEN x, GEN y)
 GEN
 dvmdii(GEN x, GEN y, GEN *z)
 {
-  long sx=signe(x),sy=signe(y);
-  long lx, ly, lz, i, j, sh, lq, lr;
+  long sx = signe(x), sy = signe(y);
+  long lx, ly = lgefint(y), lz, i, j, sh, lq, lr;
   pari_sp av;
-  ulong y0,y1, *xd,*rd,*qd;
+  ulong y0,y0i,y1, *xd,*rd,*qd;
   GEN q, r, r1;
 
-  if (!sy)
-  {
-    if (z == ONLY_REM && !sx) return gen_0;
-    if (!sy) pari_err_INV("dvmdii",gen_0);
-  }
   if (!sx)
   {
+    if (ly < 3) pari_err_INV("dvmdii",gen_0);
     if (!z || z == ONLY_REM) return gen_0;
     *z=gen_0; return gen_0;
   }
+  if (ly <= 3)
+  {
+    ulong rem;
+    if (ly < 3) pari_err_INV("dvmdii",gen_0);
+    if (z == ONLY_REM)
+    {
+      rem = umodiu(x,uel(y,2));
+      if (!rem) return gen_0;
+      return (sx < 0)? utoineg(uel(y,2) - rem): utoipos(rem);
+    }
+    q = diviu_rem(x, uel(y,2), &rem);
+    if (sx != sy) togglesign(q);
+    if (!z) return q;
+    if (!rem) *z = gen_0;
+    else *z = sx < 0? utoineg(rem): utoipos(rem);
+    return q;
+  }
   lx=lgefint(x);
-  ly=lgefint(y); lz=lx-ly;
+  lz=lx-ly;
   if (lz <= 0)
   {
     if (lz == 0)
@@ -755,7 +813,7 @@ dvmdii(GEN x, GEN y, GEN *z)
       for (i=2; i<lx; i++)
         if (x[i] != y[i])
         {
-          if ((ulong)x[i] > (ulong)y[i]) goto DIVIDE;
+          if (uel(x,i) > uel(y,i)) goto DIVIDE;
           goto TRIVIAL;
         }
       if (z == ONLY_REM) return gen_0;
@@ -770,32 +828,6 @@ TRIVIAL:
   }
 DIVIDE: /* quotient is non-zero */
   av=avma; if (sx<0) sy = -sy;
-  if (ly==3)
-  {
-    LOCAL_HIREMAINDER;
-    y0 = y[2];
-    if (y0 <= (ulong)x[2]) hiremainder=0;
-    else
-    {
-      hiremainder = x[2]; lx--; x++;
-    }
-    q = new_chunk(lx); for (i=2; i<lx; i++) q[i]=divll(x[i],y0);
-    if (z == ONLY_REM)
-    {
-      avma=av; if (!hiremainder) return gen_0;
-      r=cgeti(3);
-      r[1] = evalsigne(sx) | evallgefint(3);
-      r[2]=hiremainder; return r;
-    }
-    q[1] = evalsigne(sy) | evallgefint(lx);
-    q[0] = evaltyp(t_INT) | evallg(lx);
-    if (!z) return q;
-    if (!hiremainder) { *z=gen_0; return q; }
-    r=cgeti(3);
-    r[1] = evalsigne(sx) | evallgefint(3);
-    r[2] = hiremainder; *z=r; return q;
-  }
-
   r1 = new_chunk(lx); sh = bfffo(y[2]);
   if (sh)
   { /* normalize so that highbit(y) = 1 (shift left x and y by sh bits)*/
@@ -803,28 +835,29 @@ DIVIDE: /* quotient is non-zero */
     r = new_chunk(ly);
     shift_left(r, y,2,ly-1, 0,sh); y = r;
     shift_left(r1,x,2,lx-1, 0,sh);
-    r1[1] = ((ulong)x[2]) >> m;
+    r1[1] = uel(x,2) >> m;
   }
   else
   {
     r1[1] = 0; for (j=2; j<lx; j++) r1[j] = x[j];
   }
   x = r1;
-  y0 = y[2]; y1 = y[3];
+  y0 = y[2]; y0i = get_Fl_red(y0);
+  y1 = y[3];
   for (i=0; i<=lz; i++)
   { /* r1 = x + i */
     ulong k, qp;
     LOCAL_HIREMAINDER;
     LOCAL_OVERFLOW;
 
-    if ((ulong)r1[1] == y0)
+    if (uel(r1,1) == y0)
     {
       qp = ULONG_MAX; k = addll(y0,r1[2]);
     }
     else
     {
       hiremainder = r1[1]; overflow = 0;
-      qp = divll(r1[2],y0); k = hiremainder;
+      qp = divll_pre(r1[2],y0,y0i); k = hiremainder;
     }
     if (!overflow)
     {
@@ -838,7 +871,7 @@ DIVIDE: /* quotient is non-zero */
       r1[j] = subll(r1[j], addmul(qp,y[j]));
       hiremainder += overflow;
     }
-    if ((ulong)r1[1] < hiremainder)
+    if (uel(r1,1) < hiremainder)
     {
       qp--;
       j = ly-1; r1[j] = addll(r1[j],y[j]);
@@ -951,17 +984,17 @@ red_montgomery(GEN T, GEN N, ulong inv)
 #endif
   if (k == 1)
   { /* as below, special cased for efficiency */
-    ulong n = (ulong)N[2];
+    ulong n = uel(N,2);
     if (d == 1) {
-      hiremainder = (ulong)T[2];
+      hiremainder = uel(T,2);
       m = hiremainder * inv;
       (void)addmul(m, n); /* t + m*n = 0 */
       return utoi(hiremainder);
     } else { /* d = 2 */
-      hiremainder = (ulong)T[3];
+      hiremainder = uel(T,3);
       m = hiremainder * inv;
       (void)addmul(m, n); /* t + m*n = 0 */
-      t = addll(hiremainder, (ulong)T[2]);
+      t = addll(hiremainder, uel(T,2));
       if (overflow) t -= n; /* t > n doesn't fit in 1 word */
       return utoi(t);
     }
@@ -1039,9 +1072,9 @@ diviuexact_i(GEN x, ulong y)
 
   if (y == 1) return icopy(x);
   lx = lgefint(x);
-  if (lx == 3) return utoipos((ulong)x[2] / y);
+  if (lx == 3) return utoipos(uel(x,2) / y);
   yinv = invmod2BIL(y);
-  lz = (y <= (ulong)x[2]) ? lx : lx-1;
+  lz = (y <= uel(x,2)) ? lx : lx-1;
   z = new_chunk(lz);
   z0 = z + lz;
   x0 = x + lx; x0min = x + lx-lz+2;
@@ -1086,7 +1119,7 @@ diviuexact(GEN x, ulong y)
   if (y == 1) return icopy(x);
   lx = lgefint(x);
   if (lx == 3) {
-    ulong q = (ulong)x[2] / y;
+    ulong q = uel(x,2) / y;
     return (s > 0)? utoipos(q): utoineg(q);
   }
   av = avma; (void)new_chunk(lx); vy = vals(y);
@@ -1095,7 +1128,7 @@ diviuexact(GEN x, ulong y)
     if (y == 1) { avma = av; return shifti(x, -vy); }
     x = shifti(x, -vy);
     if (lx == 3) {
-      ulong q = (ulong)x[2] / y;
+      ulong q = uel(x,2) / y;
       avma = av;
       return (s > 0)? utoipos(q): utoineg(q);
     }
@@ -1120,7 +1153,7 @@ diviiexact(GEN x, GEN y)
   if (!sx) return gen_0;
   lx = lgefint(x);
   if (lx == 3) {
-    q = (ulong)x[2] / (ulong)y[2];
+    q = uel(x,2) / uel(y,2);
     return (sx+sy) ? utoipos(q): utoineg(q);
   }
   vy = vali(y); av = avma;
@@ -1136,12 +1169,12 @@ diviiexact(GEN x, GEN y)
   ly = lgefint(y);
   if (ly == 3)
   {
-    x = diviuexact_i(x,(ulong)y[2]); /* x != 0 */
+    x = diviuexact_i(x,uel(y,2)); /* x != 0 */
     setsigne(x, (sx+sy)? 1: -1); return x;
   }
   y0inv = invmod2BIL(y[ly-1]);
   i=2; while (i<ly && y[i]==x[i]) i++;
-  lz = (i==ly || (ulong)y[i] < (ulong)x[i]) ? lx-ly+3 : lx-ly+2;
+  lz = (i==ly || uel(y,i) < uel(x,i)) ? lx-ly+3 : lx-ly+2;
   z = new_chunk(lz);
 
   y += ly - 1; /* now y[-i] = i-th word of y */
@@ -1151,7 +1184,7 @@ diviiexact(GEN x, GEN y)
     LOCAL_HIREMAINDER;
     LOCAL_OVERFLOW;
 
-    z[i] = q = y0inv*((ulong)x[ii]); /* i-th quotient */
+    z[i] = q = y0inv*uel(x,ii); /* i-th quotient */
     if (!q) continue;
 
     /* x := x - q * y */
@@ -1891,7 +1924,7 @@ static GEN
 sqrtispec1_sh(GEN n, GEN *pr)
 {
   GEN S;
-  ulong r, s, u0 = (ulong)n[0];
+  ulong r, s, u0 = uel(n,0);
   int sh = bfffo(u0) & ~1UL;
   if (sh) u0 <<= sh;
   p_sqrtu1(&u0, &s, &r);
@@ -1915,7 +1948,7 @@ static GEN
 sqrtispec2_sh(GEN n, GEN *pr)
 {
   GEN S;
-  ulong U[2], r, s, u0 = (ulong)n[0], u1 = (ulong)n[1];
+  ulong U[2], r, s, u0 = uel(n,0), u1 = uel(n,1);
   int hi, sh = bfffo(u0) & ~1UL;
   if (sh) {
     u0 = (u0 << sh) | (u1 >> (BITS_IN_LONG-sh));
@@ -2022,7 +2055,7 @@ sqrtremi(GEN N, GEN *r)
 GEN
 sqrtr_abs(GEN x)
 {
-  long l = lg(x) - 2, e = expo(x), er = e>>1;
+  long l = realprec(x) - 2, e = expo(x), er = e>>1;
   GEN b, c, res = cgetr(2 + l);
   res[1] = evalsigne(1) | evalexpo(er);
   if (e&1) {
@@ -2036,11 +2069,11 @@ sqrtr_abs(GEN x)
     ulong u;
     b = new_chunk(2 + (l << 1));
     shift_left(b+1, x+2, 0,l-1, 0, BITS_IN_LONG-1);
-    b[0] = ((ulong)x[2])>>1;
+    b[0] = uel(x,2)>>1;
     xmpn_zero(b + l+1,l+1);
     b = sqrtispec(b, l+1, &c);
     xmpn_copy(res+2, b+2, l);
-    u = (ulong)b[l+2];
+    u = uel(b,l+2);
     if ( u&HIGHBIT || (u == ~HIGHBIT && cmpii(c,b) > 0))
       roundr_up_ip(res, l+2);
   }
@@ -2141,7 +2174,7 @@ convi(GEN x, long *l)
 {
   long lz, lx = lgefint(x);
   ulong *z;
-  if (lx == 3 && (ulong)x[2] < 1000000000UL) {
+  if (lx == 3 && uel(x,2) < 1000000000UL) {
     z = (ulong*)new_chunk(1);
     *z = x[2];
     *l = 1; return z+1;
diff --git a/src/kernel/none/mp_indep.c b/src/kernel/none/mp_indep.c
index 93d7af8..accc7cd 100644
--- a/src/kernel/none/mp_indep.c
+++ b/src/kernel/none/mp_indep.c
@@ -420,7 +420,7 @@ mulir(GEN x, GEN y)
   long sx = signe(x), sy;
   if (!sx) return mul0r(y);
   if (lgefint(x) == 3) {
-    GEN z = mulur((ulong)x[2], y);
+    GEN z = mulur(uel(x,2), y);
     if (sx < 0) togglesign(z);
     return z;
   }
@@ -677,24 +677,14 @@ modiiz(GEN x, GEN y, GEN z)
 GEN
 divrs(GEN x, long y)
 {
-  long i, lx, garde, sh, s = signe(x);
   GEN z;
-  LOCAL_HIREMAINDER;
-
-  if (!y) pari_err_INV("divrs",gen_0);
-  if (y<0) { s = -s; y = -y; }
-  if (!s) return real_0_bit(expo(x) - expu(y));
-  if (y==1) { z = rcopy(x); setsigne(z,s); return z; }
-  if (y==2) { z = shiftr(x, -1); setsigne(z,s); return z; }
-
-  z=cgetr(lx=lg(x)); hiremainder=0;
-  for (i=2; i<lx; i++) z[i] = divll(x[i],y);
-
-  /* we may have hiremainder != 0 ==> garde */
-  garde=divll(0,y); sh=bfffo(z[2]);
-  if (sh) shift_left(z,z, 2,lx-1, garde,sh);
-  z[1] = evalsigne(s) | evalexpo(expo(x)-sh);
-  if ((garde << sh) & HIGHBIT) roundr_up_ip(z, lx);
+  if (y < 0)
+  {
+    z = divru(x, (ulong)-y);
+    togglesign(z);
+  }
+  else
+    z = divru(x, (ulong)y);
   return z;
 }
 
@@ -707,27 +697,50 @@ divru(GEN x, ulong y)
 
   if (!y) pari_err_INV("divru",gen_0);
   if (!s) return real_0_bit(expo(x) - expu(y));
-  if (y==1) return rcopy(x);
-  if (y==2) return shiftr(x, -1);
-
+  if (!(y & (y-1))) /* power of 2 */
+  {
+    if (y == 1) return rcopy(x);
+    return shiftr(x, -expu(y));
+  }
   e = expo(x);
   lx = lg(x);
   z = cgetr(lx);
-  if (y <= (ulong)x[2])
+  if (lx == 3)
   {
-    hiremainder = 0;
-    for (i=2; i<lx; i++) z[i] = divll(x[i],y);
-    /* we may have hiremainder != 0 ==> garde */
-    garde = divll(0,y);
+    if (y <= uel(x,2))
+    {
+      hiremainder = 0;
+      z[2] = divll(x[2],y);
+      /* we may have hiremainder != 0 ==> garde */
+      garde = divll(0,y);
+    }
+    else
+    {
+      hiremainder = x[2];
+      z[2] = divll(0,y);
+      garde = hiremainder;
+      e -= BITS_IN_LONG;
+    }
   }
   else
   {
-    long l = lx-1;
-    hiremainder = x[2];
-    for (i=2; i<l; i++) z[i] = divll(x[i+1],y);
-    z[i] = divll(0,y);
-    garde = hiremainder;
-    e -= BITS_IN_LONG;
+    ulong yp = get_Fl_red(y);
+    if (y <= uel(x,2))
+    {
+      hiremainder = 0;
+      for (i=2; i<lx; i++) z[i] = divll_pre(x[i],y,yp);
+      /* we may have hiremainder != 0 ==> garde */
+      garde = divll_pre(0,y,yp);
+    }
+    else
+    {
+      long l = lx-1;
+      hiremainder = x[2];
+      for (i=2; i<l; i++) z[i] = divll_pre(x[i+1],y,yp);
+      z[i] = divll_pre(0,y,yp);
+      garde = hiremainder;
+      e -= BITS_IN_LONG;
+    }
   }
   sh=bfffo(z[2]); /* z[2] != 0 */
   if (sh) shift_left(z,z, 2,lx-1, garde,sh);
diff --git a/src/kernel/none/ratlift.c b/src/kernel/none/ratlift.c
index 94cfd6e..0418c96 100644
--- a/src/kernel/none/ratlift.c
+++ b/src/kernel/none/ratlift.c
@@ -74,7 +74,7 @@ int
 Fp_ratlift(GEN x, GEN m, GEN amax, GEN bmax, GEN *a, GEN *b)
 {
   GEN d, d1, v, v1, q, r;
-  pari_sp av = avma, av1, lim;
+  pari_sp av = avma, av1;
   long lb, lbb, s, s0;
   ulong vmax;
   ulong xu, xu1, xv, xv1; /* Lehmer stage recurrence matrix */
@@ -97,7 +97,7 @@ Fp_ratlift(GEN x, GEN m, GEN amax, GEN bmax, GEN *a, GEN *b)
   lb = lgefint(bmax);
   lbb = bfffo(*int_MSW(bmax));
   s = 1;
-  av1 = avma; lim = stack_lim(av, 1);
+  av1 = avma;
 
   /* General case: Euclidean division chain starting with m div x, and
    * with bounds on the sequence of convergents' denoms v_j.
@@ -212,7 +212,7 @@ Fp_ratlift(GEN x, GEN m, GEN amax, GEN bmax, GEN *a, GEN *b)
       }
     }
 
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"ratlift");
       gerepileall(av1, 4, &d, &d1, &v, &v1);
diff --git a/src/kernel/none/tune-gen.h b/src/kernel/none/tune-gen.h
index df60f49..8cf5c99 100644
--- a/src/kernel/none/tune-gen.h
+++ b/src/kernel/none/tune-gen.h
@@ -1,40 +1,46 @@
 #ifdef PARI_TUNE
-long SQRI_FFT_LIMIT           = __SQRI_FFT_LIMIT;
-long MULII_FFT_LIMIT          = __MULII_FFT_LIMIT;
-long SQRI_KARATSUBA_LIMIT     = __SQRI_KARATSUBA_LIMIT;
-long MULII_KARATSUBA_LIMIT    = __MULII_KARATSUBA_LIMIT;
-long MULRR_MULII_LIMIT        = __MULRR_MULII_LIMIT;
-long Fp_POW_REDC_LIMIT        = __Fp_POW_REDC_LIMIT;
-long Fp_POW_BARRETT_LIMIT     = __Fp_POW_BARRETT_LIMIT;
-long INVMOD_GMP_LIMIT         = __INVMOD_GMP_LIMIT;
-long DIVRR_GMP_LIMIT          = __DIVRR_GMP_LIMIT;
-long Flx_MUL_KARATSUBA_LIMIT  = __Flx_MUL_KARATSUBA_LIMIT;
-long Flx_SQR_KARATSUBA_LIMIT  = __Flx_SQR_KARATSUBA_LIMIT;
-long Flx_MUL_HALFMULII_LIMIT  = __Flx_MUL_HALFMULII_LIMIT;
-long Flx_SQR_HALFSQRI_LIMIT   = __Flx_SQR_HALFSQRI_LIMIT;
-long Flx_MUL_MULII_LIMIT      = __Flx_MUL_MULII_LIMIT;
-long Flx_SQR_SQRI_LIMIT       = __Flx_SQR_SQRI_LIMIT;
-long Flx_MUL_MULII2_LIMIT     = __Flx_MUL_MULII2_LIMIT;
-long Flx_SQR_SQRI2_LIMIT      = __Flx_SQR_SQRI2_LIMIT;
-long Flx_INVBARRETT_LIMIT     = __Flx_INVBARRETT_LIMIT;
-long Flx_DIVREM_BARRETT_LIMIT = __Flx_DIVREM_BARRETT_LIMIT;
-long Flx_REM_BARRETT_LIMIT    = __Flx_REM_BARRETT_LIMIT;
-long Flx_BARRETT_LIMIT        = __Flx_BARRETT_LIMIT;
-long Flx_HALFGCD_LIMIT        = __Flx_HALFGCD_LIMIT;
-long Flx_GCD_LIMIT            = __Flx_GCD_LIMIT;
-long Flx_EXTGCD_LIMIT         = __Flx_EXTGCD_LIMIT;
-long FpX_INVBARRETT_LIMIT     = __FpX_INVBARRETT_LIMIT;
-long FpX_DIVREM_BARRETT_LIMIT = __FpX_DIVREM_BARRETT_LIMIT;
-long FpX_REM_BARRETT_LIMIT    = __FpX_REM_BARRETT_LIMIT;
-long FpX_BARRETT_LIMIT        = __FpX_BARRETT_LIMIT;
-long FpX_HALFGCD_LIMIT        = __FpX_HALFGCD_LIMIT;
-long FpX_GCD_LIMIT            = __FpX_GCD_LIMIT;
-long FpX_EXTGCD_LIMIT         = __FpX_EXTGCD_LIMIT;
-long EXPNEWTON_LIMIT          = __EXPNEWTON_LIMIT;
-long INVNEWTON_LIMIT          = __INVNEWTON_LIMIT;
-long LOGAGM_LIMIT             = __LOGAGM_LIMIT;
-long LOGAGMCX_LIMIT           = __LOGAGMCX_LIMIT;
-long AGM_ATAN_LIMIT           = __AGM_ATAN_LIMIT;
-long RgX_SQR_LIMIT            = __RgX_SQR_LIMIT;
-long RgX_MUL_LIMIT            = __RgX_MUL_LIMIT;
+long AGM_ATAN_LIMIT                 = __AGM_ATAN_LIMIT;
+long DIVRR_GMP_LIMIT                = __DIVRR_GMP_LIMIT;
+long EXPNEWTON_LIMIT                = __EXPNEWTON_LIMIT;
+long Flx_BARRETT_HALFMULII_LIMIT    = __Flx_BARRETT_HALFMULII_LIMIT;
+long Flx_BARRETT_KARATSUBA_LIMIT    = __Flx_BARRETT_KARATSUBA_LIMIT;
+long Flx_BARRETT_MULII2_LIMIT       = __Flx_BARRETT_MULII2_LIMIT;
+long Flx_BARRETT_MULII_LIMIT        = __Flx_BARRETT_MULII_LIMIT;
+long Flx_DIVREM_BARRETT_LIMIT       = __Flx_DIVREM_BARRETT_LIMIT;
+long Flx_EXTGCD_LIMIT               = __Flx_EXTGCD_LIMIT;
+long Flx_GCD_LIMIT                  = __Flx_GCD_LIMIT;
+long Flx_HALFGCD_LIMIT              = __Flx_HALFGCD_LIMIT;
+long Flx_INVBARRETT_HALFMULII_LIMIT = __Flx_INVBARRETT_HALFMULII_LIMIT;
+long Flx_INVBARRETT_KARATSUBA_LIMIT = __Flx_INVBARRETT_KARATSUBA_LIMIT;
+long Flx_INVBARRETT_MULII2_LIMIT    = __Flx_INVBARRETT_MULII2_LIMIT;
+long Flx_INVBARRETT_MULII_LIMIT     = __Flx_INVBARRETT_MULII_LIMIT;
+long Flx_MUL_HALFMULII_LIMIT        = __Flx_MUL_HALFMULII_LIMIT;
+long Flx_MUL_KARATSUBA_LIMIT        = __Flx_MUL_KARATSUBA_LIMIT;
+long Flx_MUL_MULII2_LIMIT           = __Flx_MUL_MULII2_LIMIT;
+long Flx_MUL_MULII_LIMIT            = __Flx_MUL_MULII_LIMIT;
+long Flx_REM_BARRETT_LIMIT          = __Flx_REM_BARRETT_LIMIT;
+long Flx_SQR_HALFSQRI_LIMIT         = __Flx_SQR_HALFSQRI_LIMIT;
+long Flx_SQR_KARATSUBA_LIMIT        = __Flx_SQR_KARATSUBA_LIMIT;
+long Flx_SQR_SQRI2_LIMIT            = __Flx_SQR_SQRI2_LIMIT;
+long Flx_SQR_SQRI_LIMIT             = __Flx_SQR_SQRI_LIMIT;
+long FpX_BARRETT_LIMIT              = __FpX_BARRETT_LIMIT;
+long FpX_DIVREM_BARRETT_LIMIT       = __FpX_DIVREM_BARRETT_LIMIT;
+long FpX_EXTGCD_LIMIT               = __FpX_EXTGCD_LIMIT;
+long FpX_GCD_LIMIT                  = __FpX_GCD_LIMIT;
+long FpX_HALFGCD_LIMIT              = __FpX_HALFGCD_LIMIT;
+long FpX_INVBARRETT_LIMIT           = __FpX_INVBARRETT_LIMIT;
+long FpX_REM_BARRETT_LIMIT          = __FpX_REM_BARRETT_LIMIT;
+long Fp_POW_BARRETT_LIMIT           = __Fp_POW_BARRETT_LIMIT;
+long Fp_POW_REDC_LIMIT              = __Fp_POW_REDC_LIMIT;
+long INVMOD_GMP_LIMIT               = __INVMOD_GMP_LIMIT;
+long INVNEWTON_LIMIT                = __INVNEWTON_LIMIT;
+long LOGAGMCX_LIMIT                 = __LOGAGMCX_LIMIT;
+long LOGAGM_LIMIT                   = __LOGAGM_LIMIT;
+long MULII_FFT_LIMIT                = __MULII_FFT_LIMIT;
+long MULII_KARATSUBA_LIMIT          = __MULII_KARATSUBA_LIMIT;
+long MULRR_MULII_LIMIT              = __MULRR_MULII_LIMIT;
+long RgX_MUL_LIMIT                  = __RgX_MUL_LIMIT;
+long RgX_SQR_LIMIT                  = __RgX_SQR_LIMIT;
+long SQRI_FFT_LIMIT                 = __SQRI_FFT_LIMIT;
+long SQRI_KARATSUBA_LIMIT           = __SQRI_KARATSUBA_LIMIT;
 #endif
diff --git a/src/kernel/none/tune.h b/src/kernel/none/tune.h
index 9753e41..eadc650 100644
--- a/src/kernel/none/tune.h
+++ b/src/kernel/none/tune.h
@@ -1,79 +1,91 @@
 #ifdef LONG_IS_64BIT
-#define __MULII_KARATSUBA_LIMIT         23
-#define __SQRI_KARATSUBA_LIMIT          36
-#define __MULII_FFT_LIMIT             1441
-#define __SQRI_FFT_LIMIT              1651
-#define __MULRR_MULII_LIMIT            276
-#define __Fp_POW_REDC_LIMIT             99
-#define __Fp_POW_BARRETT_LIMIT         101
-#define __INVNEWTON_LIMIT              656
-#define __DIVRR_GMP_LIMIT               -1
-#define __EXPNEWTON_LIMIT               66
-#define __LOGAGM_LIMIT                  16
-#define __LOGAGMCX_LIMIT                13
-#define __AGM_ATAN_LIMIT                56
-#define __INVMOD_GMP_LIMIT              -1
-#define __Flx_MUL_KARATSUBA_LIMIT      147
-#define __Flx_SQR_KARATSUBA_LIMIT      330
+#define __AGM_ATAN_LIMIT                 56
+#define __DIVRR_GMP_LIMIT                -1
+#define __EXPNEWTON_LIMIT                66
+#define __Flx_BARRETT_HALFMULII_LIMIT    29
+#define __Flx_BARRETT_KARATSUBA_LIMIT    2561
+#define __Flx_BARRETT_MULII2_LIMIT       30
+#define __Flx_BARRETT_MULII_LIMIT        1681
+#define __Flx_DIVREM_BARRETT_LIMIT       2804
+#define __Flx_EXTGCD_LIMIT               284
+#define __Flx_GCD_LIMIT                  1890
+#define __Flx_HALFGCD_LIMIT              80
+#define __Flx_INVBARRETT_HALFMULII_LIMIT 424
+#define __Flx_INVBARRETT_KARATSUBA_LIMIT 5120
+#define __Flx_INVBARRETT_MULII2_LIMIT    36
+#define __Flx_INVBARRETT_MULII_LIMIT     3840
 #define __Flx_MUL_HALFMULII_LIMIT        5
-#define __Flx_SQR_HALFSQRI_LIMIT         3
-#define __Flx_MUL_MULII_LIMIT         1639
-#define __Flx_SQR_SQRI_LIMIT             5
+#define __Flx_MUL_KARATSUBA_LIMIT        147
 #define __Flx_MUL_MULII2_LIMIT           5
+#define __Flx_MUL_MULII_LIMIT            1639
+#define __Flx_REM_BARRETT_LIMIT          3577
+#define __Flx_SQR_HALFSQRI_LIMIT         3
+#define __Flx_SQR_KARATSUBA_LIMIT        330
 #define __Flx_SQR_SQRI2_LIMIT            8
-#define __Flx_INVBARRETT_LIMIT        3577
-#define __Flx_DIVREM_BARRETT_LIMIT    2804
-#define __Flx_REM_BARRETT_LIMIT       3577
-#define __Flx_BARRETT_LIMIT           1623
-#define __Flx_HALFGCD_LIMIT             80
-#define __Flx_GCD_LIMIT               1890
-#define __Flx_EXTGCD_LIMIT             284
-#define __FpX_INVBARRETT_LIMIT         254
-#define __FpX_DIVREM_BARRETT_LIMIT     292
-#define __FpX_REM_BARRETT_LIMIT        306
-#define __FpX_BARRETT_LIMIT             85
-#define __FpX_HALFGCD_LIMIT             75
-#define __FpX_GCD_LIMIT                731
-#define __FpX_EXTGCD_LIMIT             117
+#define __Flx_SQR_SQRI_LIMIT             5
+#define __FpX_BARRETT_LIMIT              85
+#define __FpX_DIVREM_BARRETT_LIMIT       292
+#define __FpX_EXTGCD_LIMIT               117
+#define __FpX_GCD_LIMIT                  731
+#define __FpX_HALFGCD_LIMIT              75
+#define __FpX_INVBARRETT_LIMIT           254
+#define __FpX_REM_BARRETT_LIMIT          306
+#define __Fp_POW_BARRETT_LIMIT           101
+#define __Fp_POW_REDC_LIMIT              99
+#define __INVMOD_GMP_LIMIT               -1
+#define __INVNEWTON_LIMIT                656
+#define __LOGAGMCX_LIMIT                 13
+#define __LOGAGM_LIMIT                   16
+#define __MULII_FFT_LIMIT                1441
+#define __MULII_KARATSUBA_LIMIT          23
+#define __MULRR_MULII_LIMIT              276
 #define __RgX_MUL_LIMIT                  9
-#define __RgX_SQR_LIMIT                 35
+#define __RgX_SQR_LIMIT                  35
+#define __SQRI_FFT_LIMIT                 1651
+#define __SQRI_KARATSUBA_LIMIT           36
 #else
-#define __MULII_KARATSUBA_LIMIT         18
-#define __SQRI_KARATSUBA_LIMIT          27
-#define __MULII_FFT_LIMIT             1386
-#define __SQRI_FFT_LIMIT              1469
-#define __MULRR_MULII_LIMIT            102
-#define __Fp_POW_REDC_LIMIT             99
-#define __Fp_POW_BARRETT_LIMIT          97
-#define __INVNEWTON_LIMIT              380
-#define __DIVRR_GMP_LIMIT               -1
-#define __EXPNEWTON_LIMIT               66
-#define __LOGAGM_LIMIT                  55
-#define __LOGAGMCX_LIMIT                58
-#define __AGM_ATAN_LIMIT               159
-#define __INVMOD_GMP_LIMIT              -1
-#define __Flx_MUL_KARATSUBA_LIMIT       85
-#define __Flx_SQR_KARATSUBA_LIMIT      159
+#define __AGM_ATAN_LIMIT                 159
+#define __DIVRR_GMP_LIMIT                -1
+#define __EXPNEWTON_LIMIT                66
+#define __Flx_BARRETT_HALFMULII_LIMIT    244
+#define __Flx_BARRETT_KARATSUBA_LIMIT    905
+#define __Flx_BARRETT_MULII2_LIMIT       1004
+#define __Flx_BARRETT_MULII_LIMIT        2715
+#define __Flx_DIVREM_BARRETT_LIMIT       3942
+#define __Flx_EXTGCD_LIMIT               850
+#define __Flx_GCD_LIMIT                  7165
+#define __Flx_HALFGCD_LIMIT              232
+#define __Flx_INVBARRETT_HALFMULII_LIMIT 898
+#define __Flx_INVBARRETT_KARATSUBA_LIMIT 3471
+#define __Flx_INVBARRETT_MULII2_LIMIT    3672
+#define __Flx_INVBARRETT_MULII_LIMIT     4196
 #define __Flx_MUL_HALFMULII_LIMIT        8
+#define __Flx_MUL_KARATSUBA_LIMIT        85
+#define __Flx_MUL_MULII2_LIMIT           3755
+#define __Flx_MUL_MULII_LIMIT            698
+#define __Flx_REM_BARRETT_LIMIT          3942
 #define __Flx_SQR_HALFSQRI_LIMIT         6
-#define __Flx_MUL_MULII_LIMIT          698
-#define __Flx_SQR_SQRI_LIMIT          1276
-#define __Flx_MUL_MULII2_LIMIT        3755
-#define __Flx_SQR_SQRI2_LIMIT         4139
-#define __Flx_INVBARRETT_LIMIT        4345
-#define __Flx_DIVREM_BARRETT_LIMIT    3942
-#define __Flx_REM_BARRETT_LIMIT       3942
-#define __Flx_BARRETT_LIMIT            915
-#define __Flx_HALFGCD_LIMIT            232
-#define __Flx_GCD_LIMIT               7165
-#define __Flx_EXTGCD_LIMIT             850
-#define __FpX_INVBARRETT_LIMIT         337
-#define __FpX_DIVREM_BARRETT_LIMIT     306
-#define __FpX_REM_BARRETT_LIMIT        306
-#define __FpX_BARRETT_LIMIT            144
-#define __FpX_HALFGCD_LIMIT            145
-#define __FpX_GCD_LIMIT               1292
-#define __FpX_EXTGCD_LIMIT             238
+#define __Flx_SQR_KARATSUBA_LIMIT        159
+#define __Flx_SQR_SQRI2_LIMIT            4139
+#define __Flx_SQR_SQRI_LIMIT             1276
+#define __FpX_BARRETT_LIMIT              144
+#define __FpX_DIVREM_BARRETT_LIMIT       306
+#define __FpX_EXTGCD_LIMIT               238
+#define __FpX_GCD_LIMIT                  1292
+#define __FpX_HALFGCD_LIMIT              145
+#define __FpX_INVBARRETT_LIMIT           337
+#define __FpX_REM_BARRETT_LIMIT          306
+#define __Fp_POW_BARRETT_LIMIT           97
+#define __Fp_POW_REDC_LIMIT              99
+#define __INVMOD_GMP_LIMIT               -1
+#define __INVNEWTON_LIMIT                380
+#define __LOGAGMCX_LIMIT                 58
+#define __LOGAGM_LIMIT                   55
+#define __MULII_FFT_LIMIT                1386
+#define __MULII_KARATSUBA_LIMIT          18
+#define __MULRR_MULII_LIMIT              102
 #define __RgX_MUL_LIMIT                  5
-#define __RgX_SQR_LIMIT                 26
+#define __RgX_SQR_LIMIT                  26
+#define __SQRI_FFT_LIMIT                 1469
+#define __SQRI_KARATSUBA_LIMIT           27
 #endif
diff --git a/src/language/anal.c b/src/language/anal.c
index 41054e9..f77cf3a 100644
--- a/src/language/anal.c
+++ b/src/language/anal.c
@@ -199,6 +199,83 @@ find:
   return retval;
 }
 
+/********************************************************************/
+/**                                                                **/
+/**                   HASH TABLE MANIPULATIONS                     **/
+/**                                                                **/
+/********************************************************************/
+/* return hashing value for identifier s */
+static ulong
+hashvalue(const char *s)
+{
+  ulong n = 0, c;
+  while ( (c = (ulong)*s++) ) n = (n<<1) ^ c;
+  return n;
+}
+
+static ulong
+hashvalue_raw(const char *s, long len)
+{
+  long n = 0, i;
+  for(i=0; i<len; i++) { n = (n<<1) ^ *s; s++; }
+  return n;
+}
+
+static void
+insertep(entree *ep, entree **table, ulong hash)
+{
+  ep->hash = hash;
+  hash %= functions_tblsz;
+  ep->next = table[hash];
+  table[hash] = ep;
+}
+
+static entree *
+initep(const char *name, long len)
+{
+  const long add = 4*sizeof(long);
+  entree *ep = (entree *) pari_calloc(sizeof(entree) + add + len+1);
+  entree *ep1 = initial_value(ep);
+  char *u = (char *) ep1 + add;
+  ep->name    = u; strncpy(u, name,len); u[len]=0;
+  ep->valence = EpNEW;
+  ep->value   = NULL;
+  ep->menu    = 0;
+  ep->code    = NULL;
+  ep->help    = NULL;
+  ep->pvalue  = NULL;
+  ep->arity   = 0;
+  return ep;
+}
+
+/* Look for s of length len in T; if 'insert', insert if missing */
+static entree *
+findentry(const char *s, long len, entree **T, int insert)
+{
+  ulong hash = hashvalue_raw(s, len);
+  entree *ep;
+  for (ep = T[hash % functions_tblsz]; ep; ep = ep->next)
+    if (ep->hash == hash)
+    {
+      const char *t = ep->name;
+      if (!strncmp(t, s, len) && !t[len]) return ep;
+    }
+  /* not found */
+  if (insert) { ep = initep(s,len); insertep(ep, T, hash); }
+  return ep;
+}
+entree *
+pari_is_default(const char *s)
+{ return findentry(s, strlen(s), defaults_hash, 0); }
+entree *
+is_entry(const char *s)
+{ return findentry(s, strlen(s), functions_hash, 0); }
+entree *
+fetch_entry_raw(const char *s, long len)
+{ return findentry(s, len, functions_hash, 1); }
+entree *
+fetch_entry(const char *s) { return fetch_entry_raw(s, strlen(s)); }
+
 /*******************************************************************/
 /*                                                                 */
 /*                  SYNTACTICAL ANALYZER FOR GP                    */
@@ -208,14 +285,17 @@ GEN
 readseq(char *t)
 {
   pari_sp av = avma;
-  return gerepileupto(av, closure_evalres(pari_compile_str(t,0)));
+  GEN x;
+  if (gp_meta(t,0)) return gnil;
+  x = pari_compile_str(t);
+  return gerepileupto(av, closure_evalres(x));
 }
 
 /* filtered readseq = remove blanks and comments */
 GEN
 gp_read_str(const char *s)
 {
-  char *t = filtre(s, (compatible == OLDALL));
+  char *t = gp_filter(s);
   GEN x = readseq(t);
   pari_free(t); return x;
 }
@@ -223,8 +303,8 @@ gp_read_str(const char *s)
 GEN
 compile_str(const char *s)
 {
-  char *t = filtre(s, (compatible == OLDALL));
-  GEN x = pari_compile_str(t, 1);
+  char *t = gp_filter(s);
+  GEN x = pari_compile_str(t);
   pari_free(t); return x;
 }
 
@@ -233,7 +313,7 @@ check_proto(const char *code)
 {
   long arity = 0;
   const char *s = code, *old;
-  if (*s == 'l' || *s == 'v' || *s == 'i' || *s == 'm') s++;
+  if (*s == 'l' || *s == 'v' || *s == 'i' || *s == 'm' || *s == 'u') s++;
   while (*s && *s != '\n') switch (*s++)
   {
     case '&':
@@ -241,6 +321,7 @@ check_proto(const char *code)
     case 'G':
     case 'I':
     case 'J':
+    case 'U':
     case 'L':
     case 'M':
     case 'P':
@@ -281,34 +362,24 @@ check_proto(const char *code)
   if (arity > 20) pari_err_IMPL("functions with more than 20 parameters");
   return arity;
 }
-
-static entree *
-installep(const char *name, long len, entree **table)
+static void
+check_name(const char *name)
 {
-  const long add = 4*sizeof(long);
-  entree *ep = (entree *) pari_calloc(sizeof(entree) + add + len+1);
-  entree *ep1 = initial_value(ep);
-  char *u = (char *) ep1 + add;
-  ep->name    = u; strncpy(u, name,len); u[len]=0;
-  ep->valence = EpNEW;
-  ep->value   = NULL;
-  ep->menu    = 0;
-  ep->code    = NULL;
-  ep->help    = NULL;
-  ep->pvalue  = NULL;
-  ep->arity   = 0;
-  ep->next    = *table;
-  return *table = ep;
+  const char *s = name;
+  if (isalpha((int)*s))
+    while (is_keyword_char(*++s)) /* empty */;
+  if (*s) pari_err(e_SYNTAX,"not a valid identifier", s, name);
 }
 
 entree *
 install(void *f, const char *name, const char *code)
 {
-  long hash, arity;
-  entree *ep = is_entry_intern(name, functions_hash, &hash);
+  long arity = check_proto(code);
+  entree *ep;
 
-  arity=check_proto(code);
-  if (ep && ep->valence != EpNEW)
+  check_name(name);
+  ep = fetch_entry(name);
+  if (ep->valence != EpNEW)
   {
     if (ep->valence != EpINSTALL)
       pari_err(e_MISC,"[install] identifier '%s' already in use", name);
@@ -317,34 +388,36 @@ install(void *f, const char *name, const char *code)
   }
   else
   {
-    const char *s = name;
-    if (isalpha((int)*s))
-      while (is_keyword_char(*++s)) /* empty */;
-    if (*s) pari_err(e_SYNTAX,"not a valid identifier", s, name);
-    if (!ep) ep = installep(name, strlen(name), functions_hash + hash);
-    ep->value=f; ep->valence=EpINSTALL;
+    ep->value = f;
+    ep->valence = EpINSTALL;
   }
   ep->code = pari_strdup(code);
-  ep->arity=arity;
-  return ep;
+  ep->arity = arity; return ep;
 }
 
+static void
+killep(entree *ep)
+{
+  GEN p = (GEN)initial_value(ep);
+  freeep(ep);
+  *p = 0; /* otherwise pari_var_create won't regenerate it */
+  ep->valence = EpNEW;
+  ep->value   = NULL;
+  ep->pvalue  = NULL;
+}
 /* Kill ep, i.e free all memory it references, and reset to initial value */
 void
 kill0(const char *e)
 {
   entree *ep = is_entry(e);
   if (!ep || EpSTATIC(ep)) pari_err(e_MISC,"can't kill that");
-  freeep(ep);
-  ep->valence = EpNEW;
-  ep->value   = NULL;
-  ep->pvalue  = NULL;
+  killep(ep);
 }
 
 void
 addhelp(const char *e, char *s)
 {
-  entree *ep = fetch_entry(e, strlen(e));
+  entree *ep = fetch_entry(e);
   if (ep->help && !EpSTATIC(ep)) pari_free((void*)ep->help);
   ep->help = pari_strdup(s);
 }
@@ -719,106 +792,111 @@ chartoGENstr(char c)
   char *t = GSTR(x);
   t[0] = c; t[1] = 0; return x;
 }
+
 /********************************************************************/
-/**                                                                **/
-/**                   HASH TABLE MANIPULATIONS                     **/
-/**                                                                **/
+/*                                                                  */
+/*                Formal variables management                       */
+/*                                                                  */
 /********************************************************************/
-/* return hashing value for identifier s */
-static ulong
-hashvalue(const char *s)
-{
-  ulong n = 0, c;
-  while ( (c = (ulong)*s++) ) n = (n<<1) ^ c;
-  return n % functions_tblsz;
-}
-
-static ulong
-hashvalue_raw(const char *s, long len, ulong n)
-{
-  long i;
-  for(i=0; i<len; i++) { n = (n<<1) ^ *s; s++; }
-  return n % functions_tblsz;
-}
+static long max_priority, min_priority;
+static long max_avail; /* max variable not yet used */
+static long nvar; /* first GP free variable */
+static hashtable *h_polvar;
 
-/* Looking for entry in hashtable. ep1 is the cell's first element */
-static entree *
-findentry(const char *name, long len, entree *ep1)
+void
+varstate_save(struct pari_varstate *s)
 {
-  entree *ep;
-  for (ep = ep1; ep; ep = ep->next)
-    if (!strncmp(ep->name, name, len) && !(ep->name)[len]) return ep;
-  return NULL; /* not found */
+  s->nvar = nvar;
+  s->max_avail = max_avail;
+  s->max_priority = max_priority;
+  s->min_priority = min_priority;
 }
 
-entree *
-is_entry_intern(const char *s, entree **table, long *pthash)
+static void
+varentries_set(long v, entree *ep)
 {
-  long hash = hashvalue(s);
-  if (pthash) *pthash = hash;
-  return findentry(s, strlen(s), table[hash]);
+  hash_insert(h_polvar, (void*)ep->name, (void*)v);
+  varentries[v] = ep;
 }
+static int
+_given_value(void *E, hashentry *e) { return e->val == E; }
 
-entree *
-is_entry(const char *s)
+static void
+varentries_unset(long v)
 {
-  return is_entry_intern(s,functions_hash,NULL);
+  entree *ep = varentries[v];
+  if (ep)
+  {
+    hashentry *e = hash_remove_select(h_polvar, (void*)ep->name, (void*)v,
+        _given_value);
+    if (!e) pari_err_BUG("varentries_unset [unknown var]");
+    varentries[v] = NULL;
+    pari_free(e);
+    if (v <= nvar && is_entry(ep->name)) { killep(ep); return; }
+    pari_free(ep);
+ }
 }
-
-entree *
-fetch_entry(const char *s, long len)
+static void
+varentries_reset(long v, entree *ep)
 {
-  entree **funhash = functions_hash + hashvalue_raw(s, len, 0);
-  entree *ep = findentry(s, len, *funhash);
-  if (ep) return ep;
-  else return installep(s,len,funhash);
+  varentries_unset(v);
+  varentries_set(v, ep);
 }
 
-/* Assume s point somewhere in the code text, so s[-1]='.' and s[-2]>0
- * So many kludges, so little time */
-entree *
-fetch_member(const char *s, long len)
+void
+varstate_restore(struct pari_varstate *s)
 {
-  entree **funhash = functions_hash+hashvalue_raw(s-1, len+1, '_');
-  entree *ep;
-  for (ep = *funhash; ep; ep = ep->next)
+  long i;
+  for (i = nvar; i >= s->nvar; i--)
   {
-    if (ep->name[0]!='_' || ep->name[1]!='.') continue;
-    if (!strncmp(ep->name+2, s, len) && !(ep->name)[len+2]) break;
+    varentries_unset(i);
+    varpriority[i] = -i;
   }
-  if (ep) return ep;
-  ep=installep(s-2,len+2,funhash);
-  ((char*)ep->name)[0]='_';
-  return ep;
+  for (i = max_avail; i < s->max_avail; i++)
+  {
+    varentries_unset(i);
+    varpriority[i] = -i;
+  }
+  nvar = s->nvar;
+  max_avail = s->max_avail;
+  max_priority = s->max_priority;
+  min_priority = s->min_priority;
 }
 
-/********************************************************************/
-/*                                                                  */
-/*                Formal variables management                       */
-/*                                                                  */
-/********************************************************************/
-static long max_avail; /* max variable not yet used */
-static long nvar; /* first GP free variable */
+void
+pari_var_close(void)
+{
+  free((void*)varentries);
+  free((void*)(varpriority-1));
+  hash_destroy(h_polvar);
+}
 
-void pari_var_init(void) {
+void
+pari_var_init(void)
+{
+  long i;
+  varentries = (entree**) pari_calloc((MAXVARN+1)*sizeof(entree*));
+  varpriority = (long*)pari_malloc((MAXVARN+2)*sizeof(long)) + 1;
+  varpriority[-1] = 1-LONG_MAX;
+  h_polvar = hash_create_str(100, 0);
   nvar = 0; max_avail = MAXVARN;
-  (void)fetch_var();
-  (void)fetch_named_var("x");
+  max_priority = min_priority = 0;
+  (void)fetch_user_var("x");
+  (void)fetch_user_var("y");
+  /* initialize so that people can use pol_x(i) directly */
+  for (i = 2; i <= (long)MAXVARN; i++) varpriority[i] = -i;
+  /* reserve varnum 1..9 for static temps with predictable priority wrt x */
+  nvar = 10;
+  min_priority = -MAXVARN;
 }
 long pari_var_next(void) { return nvar; }
 long pari_var_next_temp(void) { return max_avail; }
-static long
-pari_var_pop(long v)
-{
-  if (v != nvar-1) pari_err(e_MISC,"can't pop user variable %ld", v);
-  return --nvar;
-}
-void
+long
 pari_var_create(entree *ep)
 {
   GEN p = (GEN)initial_value(ep);
   long v;
-  if (*p) return;
+  if (*p) return varn(p);
   if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
   v = nvar++;
   /* set p = pol_x(v) */
@@ -826,74 +904,105 @@ pari_var_create(entree *ep)
   p[1] = evalsigne(1) | evalvarn(v);
   gel(p,2) = gen_0;
   gel(p,3) = gen_1;
-  varentries[v] = ep;
+  varentries_set(v, ep);
+  varpriority[v]= min_priority--;
+  return v;
 }
 
 long
 delete_var(void)
 { /* user wants to delete one of his/her/its variables */
-  if (max_avail == MAXVARN-1) return 0; /* nothing to delete */
-  max_avail++; return max_avail+1;
+  if (max_avail == MAXVARN) return 0; /* nothing to delete */
+  max_avail++;
+  if      (varpriority[max_avail] == min_priority) min_priority++;
+  else if (varpriority[max_avail] == max_priority) max_priority--;
+  return max_avail+1;
 }
 long
 fetch_var(void)
 {
   if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
+  varpriority[max_avail] = min_priority--;
   return max_avail--;
 }
-
-/* FIXE: obsolete, kept for backward compatibility */
 long
-manage_var(long n, entree *ep)
-{
-  switch(n) {
-      case manage_var_init: pari_var_init(); return 0;
-      case manage_var_next: return pari_var_next();
-      case manage_var_max_avail: return pari_var_next_temp();
-      case manage_var_pop: return pari_var_pop((long)ep);
-      case manage_var_delete: return delete_var();
-      case manage_var_create:
-        pari_var_create(ep);
-        return varn((GEN)initial_value(ep));
-  }
-  pari_err(e_MISC, "panic");
-  return -1; /* not reached */
+fetch_var_higher(void)
+{
+  if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
+  varpriority[max_avail] = ++max_priority;
+  return max_avail--;
 }
 
-entree *
-fetch_named_var(const char *s)
+static int
+_higher(void *E, hashentry *e)
+{ long v = (long)e->val; return (varncmp(v, (long)E) < 0); }
+static int
+_lower(void *E, hashentry *e)
+{ long v = (long)e->val; return (varncmp(v, (long)E) > 0); }
+
+static GEN
+var_register(long v, const char *s)
+{
+  varentries_reset(v, initep(s, strlen(s)));
+  return pol_x(v);
+}
+GEN
+varhigher(const char *s, long w)
 {
-  entree **funhash = functions_hash + hashvalue(s);
-  entree *ep = findentry(s, strlen(s), *funhash);
-  if (!ep) ep = installep(s,strlen(s),funhash);
-  else switch (EpVALENCE(ep))
+  long v;
+  if (w >= 0)
   {
-    case EpVAR: return ep;
-    case EpNEW: break;
-    default: pari_err(e_MISC, "%s already exists with incompatible valence", s);
+    hashentry *e = hash_select(h_polvar, (void*)s, (void*)w, _higher);
+    if (e) return pol_x((long)e->val);
   }
-  pari_var_create(ep);
-  ep->valence=EpVAR;
-  ep->value=initial_value(ep);
-  return ep;
+  /* no luck: need to create */
+  if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
+  v = nvar++;
+  varpriority[v]= ++max_priority;
+  return var_register(v, s);
+}
+GEN
+varlower(const char *s, long w)
+{
+  long v;
+  if (w >= 0)
+  {
+    hashentry *e = hash_select(h_polvar, (void*)s, (void*)w, _lower);
+    if (e) return pol_x((long)e->val);
+  }
+  /* no luck: need to create */
+  v = fetch_var();
+  return var_register(v, s);
 }
 
 long
 fetch_user_var(const char *s)
 {
-  return varn((GEN)initial_value(fetch_named_var(s)) );
+  entree *ep = fetch_entry(s);
+  long v;
+  switch (EpVALENCE(ep))
+  {
+    case EpVAR: return varn((GEN)initial_value(ep));
+    case EpNEW: break;
+    default: pari_err(e_MISC, "%s already exists with incompatible valence", s);
+  }
+  v = pari_var_create(ep);
+  ep->valence = EpVAR;
+  ep->value = initial_value(ep);
+  return v;
 }
 
 GEN
-fetch_var_value(long vx, GEN t)
+fetch_var_value(long v, GEN t)
 {
-  entree *ep = varentries[vx];
-  long vn;
+  entree *ep = varentries[v];
   if (!ep) return NULL;
-  if (!t)  return (GEN) ep->value;
-  vn=localvars_find(t,ep);
-  if (vn) return get_lex(vn);
-  return (GEN) ep->value;
+  if (t)
+  {
+    long vn = localvars_find(t,ep);
+    if (vn) return get_lex(vn);
+  }
+  return (GEN)ep->value;
 }
 
 void
@@ -912,27 +1021,30 @@ name_var(long n, const char *s)
   ep->valence = EpVAR;
   ep->name = u; strcpy(u,s);
   ep->value = gen_0; /* in case geval is called */
-  if (varentries[n]) pari_free(varentries[n]);
-  varentries[n] = ep;
+  varentries_reset(n, ep);
 }
 
+static int
+cmp_by_var(void *E,GEN x, GEN y)
+{ (void)E; return varncmp((long)x,(long)y); }
+GEN
+vars_sort_inplace(GEN z)
+{ gen_sort_inplace(z,NULL,cmp_by_var,NULL); return z; }
+GEN
+vars_to_RgXV(GEN h)
+{
+  long i, l = lg(h);
+  GEN z = cgetg(l, t_VEC);
+  for (i = 1; i < l; i++) gel(z,i) = pol_x(h[i]);
+  return z;
+}
 GEN
 gpolvar(GEN x)
 {
   long v;
   if (!x) {
-    long k = 1, n = pari_var_next();
-    GEN z = cgetg(n+1, t_VEC);
-    for (v = 0; v < n; v++)
-    {
-      entree *ep = varentries[v];
-      if (ep && ep->name[0] != '_') gel(z,k++) = (GEN)initial_value(ep);
-    }
-    if (k <= n) {
-      setlg(z,k);
-      stackdummy((pari_sp)(z+n), (pari_sp)(z+k));
-    }
-    return z;
+    GEN h = hash_values(h_polvar);
+    return vars_to_RgXV(vars_sort_inplace(h));
   }
   if (typ(x)==t_PADIC) return gcopy( gel(x,2) );
   v = gvar(x);
@@ -943,10 +1055,9 @@ gpolvar(GEN x)
 static void
 fill_hashtable_single(entree **table, entree *ep)
 {
-  long n = hashvalue(ep->name);
   EpSETSTATIC(ep);
-  ep->next = table[n]; table[n] = ep;
-  if (ep->code) ep->arity=check_proto(ep->code);
+  insertep(ep, table,  hashvalue(ep->name));
+  if (ep->code) ep->arity = check_proto(ep->code);
   ep->pvalue = NULL;
 }
 
@@ -983,8 +1094,8 @@ alias0(const char *s, const char *old)
   entree *ep, *e;
   GEN x;
 
-  ep = fetch_entry(old,strlen(old));
-  e  = fetch_entry(s,strlen(s));
+  ep = fetch_entry(old);
+  e  = fetch_entry(s);
   if (EpVALENCE(e) != EpALIAS && EpVALENCE(e) != EpNEW)
     pari_err(e_MISC,"can't replace an existing symbol by an alias");
   freeep(e);
diff --git a/src/language/anal.h b/src/language/anal.h
index f77d470..054845b 100644
--- a/src/language/anal.h
+++ b/src/language/anal.h
@@ -48,8 +48,8 @@ union token_value { long val; };
 
 int pari_lex(union token_value *yylval, struct node_loc *yylloc, char **lex);
 int pari_parse(char **lex);
-entree* fetch_entry(const char *s, long len);
-entree* fetch_member(const char *s, long len);
+entree* fetch_entry_raw(const char *s, long len);
+entree* fetch_entry(const char *s);
 void pari_close_parser(void);
 void pari_close_compiler(void);
 void pari_close_evaluator(void);
diff --git a/src/language/compat.c b/src/language/compat.c
deleted file mode 100644
index 7290ee1..0000000
--- a/src/language/compat.c
+++ /dev/null
@@ -1,722 +0,0 @@
-/* Copyright (C) 2000  The PARI group.
-
-This file is part of the PARI/GP package.
-
-PARI/GP 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. It is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY WHATSOEVER.
-
-Check the License for details. You should have received a copy of it, along
-with the package; see the file 'COPYING'. If not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
-
-#include "pari.h"
-#include "paripriv.h"
-#include "anal.h"
-static GEN
-ghell2(GEN e, GEN a, long prec) { return ellheight0(e,a,0,prec); }
-
-static GEN
-polylogd(long m, GEN x, long prec) { return polylog0(m,x,1,prec); }
-
-static GEN
-polylogdold(long m, GEN x, long prec) { return polylog0(m,x,2,prec); }
-
-static GEN
-polylogp(long m, GEN x, long prec) { return polylog0(m,x,3,prec); }
-
-static GEN
-prod0(GEN x, GEN a, GEN b, GEN ch) {return produit(a,b,ch,x);}
-
-static GEN
-sum0(GEN x, GEN a, GEN b, GEN ch) {return somme(a,b,ch,x);}
-
-static long
-sturm0(GEN x) {return sturm(x);}
-
-static GEN
-sigmak0(long k, GEN x) {return sumdivk(x,k);}
-
-static GEN
-lseriesell0(GEN a, GEN b, GEN c, GEN d, long prec)
-  {(void)c; return elllseries(a,b,d,prec);}
-
-static GEN
-weipell(GEN e, long precdl) { return ellwpseries(e,0,precdl); }
-
-static long
-rounderror(GEN x)
-{
-  pari_sp av = avma;
-  long e; (void)grndtoi(x,&e);
-  avma = av; return (long)(e*LOG10_2);
-}
-
-static GEN
-_factpol(GEN x, long t/*unused*/, long hint/*unused*/) {
-  (void)t; (void)hint; return QX_factor(x);
-}
-
-static void
-suppressed(void) {pari_err(e_MISC,"this function no longer exists");}
-
-#define BUCH_PROTO "GDGDGD5,G,D1,G,D4,L,D3,L,p"
-#define B_ARGS GEN g1,GEN g2,GEN g3,GEN g4,GEN g5,long l1,long l2,long prec
-#define B_ARG1 g1,gtodouble(g2),gtodouble(g3),l1
-#define B_CALL(flag) Buchall_param(B_ARG1,(flag),prec)
-#define B_UNUSED (void)g4,(void)g5,(void)l2
-
-#define B_DEFAULT if (!g2) g2 = dbltor(.3); \
-                  if (!g3) g3 = dbltor(.3)
-
-#define CLASSUNIT(flag) do { \
-  pari_sp av = avma; \
-  GEN bnf = B_CALL(flag), nf = bnf_get_nf(bnf), x; \
-  B_UNUSED; \
-  x = mkvec4(gel(nf,1), gel(nf,2), mkvec2(gel(nf,3), gel(nf,4)), gel(nf,7));\
-  return gerepilecopy(av, mkmat(shallowconcat(x, gel(bnf,8)))); } while(0)
-
-static GEN
-buchgenfu(B_ARGS) { B_DEFAULT; CLASSUNIT(0); }
-static GEN
-buchgenforcefu(B_ARGS) { B_DEFAULT; CLASSUNIT(nf_FORCE); }
-static GEN
-buchinitfu(B_ARGS) { B_DEFAULT; B_UNUSED; return B_CALL(0); }
-static GEN
-buchinitforcefu(B_ARGS) { B_DEFAULT; B_UNUSED; return B_CALL(nf_FORCE); }
-static GEN
-smallbuchinit(B_ARGS) { (void)g2,(void)g3,(void)l1,B_UNUSED; return bnfcompress(Buchall(g1, 0, prec)); }
-static GEN
-factoredbase(GEN x, GEN fa) { return nfbasis0(x, 0, fa); }
-static GEN
-factoreddiscf(GEN x, GEN fa) { return nfdisc0(x, 0, fa); }
-static GEN
-buchfu(GEN bnf) { return bnf_get_fu_nocheck(checkbnf(bnf)); }
-static GEN
-buchrayinitgen(GEN bnf, GEN ideal)
-{ return Buchray(bnf,ideal, nf_INIT | nf_GEN); }
-static GEN
-buchrayinit(GEN bnf, GEN ideal)
-{ return Buchray(bnf,ideal, nf_INIT); }
-static GEN
-buchray(GEN bnf, GEN ideal)
-{ return Buchray(bnf,ideal, nf_GEN); }
-static GEN
-principalideal(GEN nf, GEN x) { return algtobasis(nf,x); }
-
-entree oldfonctions[]={
-{"!_",0,(void*)gnot,13,"G","!_"},
-{"#_",0,(void*)glength,13,"lG","length(x): number of non code words in x, number of characters for a string."},
-{"%",0,(void*)pari_get_hist,1,"D0,L,","last history item"},
-{"+_",0,NULL,13,NULL,"+_"},
-{"-_",0,(void*)gneg,13,"G","-_"},
-{"_!",0,(void*)mpfact,13,"L","_!"},
-{"_!=_",0,(void*)gne,13,"GG","_!=_"},
-{"_%=_",0,(void*)gmode,13,"&G","_%=_"},
-{"_%_",0,(void*)gmod,13,"GG","_%_"},
-{"_&&_",0,(void*)andpari,13,"GE","_&&_"},
-{"_'",0,(void*)deriv,13,"GDn","_'"},
-{"_*=_",0,(void*)gmule,13,"&G","x*=y: shortcut for x=x*y."},
-{"_*_",0,(void*)gmul,13,"GG","_*_"},
-{"_++",0,(void*)gadd1e,13,"&","x++"},
-{"_+=_",0,(void*)gadde,13,"&G","x+=y: shortcut for x=x+y."},
-{"_+_",0,(void*)gadd,13,"GG","x+y: sum of x and y."},
-{"_--",0,(void*)gsub1e,13,"&","x--"},
-{"_-=_",0,(void*)gsube,13,"&G","x-=y"},
-{"_-_",0,(void*)gsub,13,"GG","x-y: difference of x and y."},
-{"_.a1",0,(void*)member_a1,14,"G","_.a1"},
-{"_.a2",0,(void*)member_a2,14,"G","_.a2"},
-{"_.a3",0,(void*)member_a3,14,"G","_.a3"},
-{"_.a4",0,(void*)member_a4,14,"G","_.a4"},
-{"_.a6",0,(void*)member_a6,14,"G","_.a6"},
-{"_.area",0,(void*)member_area,14,"G","_.area"},
-{"_.b2",0,(void*)member_b2,14,"G","_.b2"},
-{"_.b4",0,(void*)member_b4,14,"G","_.b4"},
-{"_.b6",0,(void*)member_b6,14,"G","_.b6"},
-{"_.b8",0,(void*)member_b8,14,"G","_.b8"},
-{"_.bid",0,(void*)member_bid,14,"G","_.bid"},
-{"_.bnf",0,(void*)member_bnf,14,"G","_.bnf"},
-{"_.c4",0,(void*)member_c4,14,"G","_.c4"},
-{"_.c6",0,(void*)member_c6,14,"G","_.c6"},
-{"_.clgp",0,(void*)member_clgp,14,"G","_.clgp"},
-{"_.codiff",0,(void*)member_codiff,14,"G","_.codiff"},
-{"_.cyc",0,(void*)member_cyc,14,"G","_.cyc"},
-{"_.diff",0,(void*)member_diff,14,"G","_.diff"},
-{"_.disc",0,(void*)member_disc,14,"G","_.disc"},
-{"_.e",0,(void*)member_e,14,"G","_.e"},
-{"_.eta",0,(void*)member_eta,14,"G","_.eta"},
-{"_.f",0,(void*)member_f,14,"G","_.f"},
-{"_.fu",0,(void*)member_fu,14,"G","_.fu"},
-{"_.futu",0,(void*)member_futu,14,"G","_.futu"},
-{"_.gen",0,(void*)member_gen,14,"G","_.gen"},
-{"_.group",0,(void*)member_group,14,"G","_.group"},
-{"_.index",0,(void*)member_index,14,"G","_.index"},
-{"_.j",0,(void*)member_j,14,"G","_.j"},
-{"_.mod",0,(void*)member_mod,14,"G","_.mod"},
-{"_.nf",0,(void*)member_nf,14,"G","_.nf"},
-{"_.no",0,(void*)member_no,14,"G","_.no"},
-{"_.omega",0,(void*)member_omega,14,"G","_.omega"},
-{"_.orders",0,(void*)member_orders,14,"G","_.orders"},
-{"_.p",0,(void*)member_p,14,"G","_.p"},
-{"_.pol",0,(void*)member_pol,14,"G","_.pol"},
-{"_.r1",0,(void*)member_r1,14,"G","_.r1"},
-{"_.r2",0,(void*)member_r2,14,"G","_.r2"},
-{"_.reg",0,(void*)member_reg,14,"G","_.reg"},
-{"_.roots",0,(void*)member_roots,14,"G","_.roots"},
-{"_.sign",0,(void*)member_sign,14,"G","_.sign"},
-{"_.t2",0,(void*)member_t2,14,"G","_.t2"},
-{"_.tate",0,(void*)member_tate,14,"G","_.tate"},
-{"_.tu",0,(void*)member_tu,14,"G","_.tu"},
-{"_.tufu",0,(void*)member_tufu,14,"G","_.tufu"},
-{"_.zk",0,(void*)member_zk,14,"G","_.zk"},
-{"_.zkst",0,(void*)member_zkst,14,"G","_.zkst"},
-{"_/=_",0,(void*)gdive,13,"&G","x/=y"},
-{"_/_",0,(void*)gdiv,13,"GG","_/_"},
-{"_<<=_",0,(void*)gshiftle,13,"&L","x<<=y"},
-{"_<<_",0,(void*)gshift,13,"GL","x<<y"},
-{"_<=_",0,(void*)gle,13,"GG","_<=_"},
-{"_<_",0,(void*)glt,13,"GG","_<_"},
-{"_==_",0,(void*)geq,13,"GG","_==_"},
-{"_>=_",0,(void*)gge,13,"GG","_>=_"},
-{"_>>=_",0,(void*)gshiftre,13,"&L","_>>=_"},
-{"_>>_",0,(void*)gshift_right,13,"GL","x>>y"},
-{"_>_",0,(void*)ggt,13,"GG","_>_"},
-{"_[_.._,_.._]",0,(void*)matslice0,13,"GD0,L,D0,L,D0,L,D0,L,","x[a..b,c..d] = [x[a,c],  x[a+1,c],  ...,x[b,c];                      x[a,c+1],x[a+1,c+1],...,x[b,c+1];                        ...       ...          ...                      x[a,d],  x[a+1,d]  ,...,x[b,d]]"},
-{"_[_.._]",0,(void*)vecslice0,13,"GD0,L,L","x[a..b] = [x[a],x[a+1],...,x[b]]"},
-{"_\\/=_",0,(void*)gdivrounde,13,"&G","x\\\\/=y"},
-{"_\\/_",0,(void*)gdivround,13,"GG","x\\\\/y: rounded Euclidean quotient of x and y."},
-{"_\\=_",0,(void*)gdivente,13,"&G","x\\\\=y"},
-{"_\\_",0,(void*)gdivent,13,"GG","x\\\\y: Euclidean quotient of x and y."},
-{"_^_",0,(void*)gpow,13,"GGp","_^_"},
-{"_^s",0,(void*)gpowgs,13,"GL","_^s"},
-{"__",0,NULL,13,NULL,"__"},
-{"_derivfun",0,(void*)derivfun0,15,"GGp","_derivfun(closure,[args]) numerical derivation of closure with respect to the first variable at (args)."},
-{"_eval_mnemonic",0,(void*)eval_mnemonic,15,"lGs","Convert a mnemonic string to a flag."},
-{"_multi_if",0,(void*)ifpari_multi,15,"GE*","internal variant of if() that allows more than 3 arguments."},
-{"_void_if",0,(void*)ifpari_void,11,"vGDIDI","internal variant of if() that does not return a value."},
-{"_||_",0,(void*)orpari,13,"GE","x||y"},
-{"_~",0,(void*)gtrans,13,"G","_~"},
-{"O",0,(void*)ggrando,7,"GD1,L,","O(a^b): p-adic or power series zero with precision given by b."},
-{"O(_^_)",0,(void*)ggrando,7,"GD1,L,","O(a^b): p-adic or power series zero with precision given by b."},
-{"Str",0,(void*)Str,2,"s*","Str({x}*): concatenates its (string) argument into a single string."},
-{"abs",1,(void*)gabs,3,"Gp","abs(x)=absolute value (or modulus) of x."},
-{"acos",1,(void*)gacos,3,"Gp","acos(x)=inverse cosine of x."},
-{"acosh",1,(void*)gacosh,3,"Gp","acosh(x)=inverse hyperbolic cosine of x."},
-{"addell",3,(void*)elladd,5,"GGG","addell(e,z1,z2)=sum of the points z1 and z2 on elliptic curve e."},
-{"addprimes",1,(void*)addprimes,4,"G","addprimes(x)=add primes in the vector x (with at most 20 components) to the prime table."},
-{"adj",1,(void*)adj,8,"G","adj(x)=adjoint matrix of x."},
-{"agm",2,(void*)agm,3,"GGp","agm(x,y)=arithmetic-geometric mean of x and y."},
-{"akell",2,(void*)akell,5,"GG","akell(e,n)=computes the n-th Fourier coefficient of the L-function of the elliptic curve e."},
-{"algdep",23,(void*)algdep,8,"GL","algdep(x,n)=algebraic relations up to degree n of x."},
-{"algdep2",33,(void*)algdep0,8,"GLL","algdep2(x,n,dec)=algebraic relations up to degree n of x where dec is as in  lindep2."},
-{"algtobasis",2,(void*)algtobasis,6,"GG","algtobasis(nf,x)=transforms the algebraic number x into a column vector on the integral basis nf[7]."},
-{"anell",23,(void*)anell,5,"GL","anell(e,n)=computes the first n Fourier coefficients of the L-function of the elliptic curve e (n<32768)."},
-{"apell",2,(void*)ellap,5,"GG","apell(e,p)=computes a_p for the elliptic curve e using Shanks-Mestre's method."},
-{"apell2",2,(void*)ellap,5,"GG","apell2(e,p)=apell(e,p)."},
-{"apprpadic",2,(void*)padicappr,7,"GG","apprpadic(x,a)=p-adic roots of the polynomial x congruent to a mod p."},
-{"arg",1,(void*)garg,3,"Gp","arg(x)=argument of x,such that -pi<arg(x)<=pi."},
-{"asin",1,(void*)gasin,3,"Gp","asin(x)=inverse sine of x."},
-{"asinh",1,(void*)gasinh,3,"Gp","asinh(x)=inverse hyperbolic sine of x."},
-{"assmat",1,(void*)matcompanion,8,"G","matcompanion(x)=associated matrix to polynomial x."},
-{"atan",1,(void*)gatan,3,"Gp","atan(x)=inverse tangent of x."},
-{"atanh",1,(void*)gatanh,3,"Gp","atanh(x)=inverse hyperbolic tangent of x."},
-{"basis",13,(void*)nfbasis0,6,"GD0,L,DG","basis(x)=integral basis of the field Q[a], where a is a root of the polynomial x, using the round 4 algorithm."},
-{"basis2",13,(void*)nfbasis0,6,"GD2,L,DG","basis2(x)=integral basis of the field Q[a], where a is a root of the polynomial x, using the round 2 algorithm."},
-{"basistoalg",2,(void*)basistoalg,6,"GG","basistoalg(nf,x)=transforms the vertical vector x on the integral basis into an algebraic number."},
-{"bernreal",11,(void*)bernreal,3,"Lp","bernreal(x)=Bernoulli number B_x, as a real number with the current precision."},
-{"bernvec",11,(void*)bernvec,3,"L","bernvec(x)=Vector of rational Bernoulli numbers B_0, B_2,... up to B_(2x)."},
-{"bestappr",2,(void*)bestappr,4,"GGp","bestappr(x,k)=gives the best approximation to the real x with denominator less or equal to k."},
-{"bezout",2,(void*)gcdext0,4,"GG","bezout(x,y)=gives a 3-dimensional row vector [u,v,d] such that d=gcd(x,y) and u*x+v*y=d."},
-{"bezoutres",2,(void*)polresultantext,4,"GG","bezoutres(x,y)=gives a 3-dimensional row vector [u,v,d] such that d=resultant(x,y) and u*x+v*y=d, where x and y are polynomials."},
-{"bigomega",1,(void*)bigomega,4,"lG","bigomega(x)=number of repeated prime divisors of x."},
-{"bilhell",3,(void*)bilhell,5,"GGGp","bilhell(e,z1,z2)=canonical bilinear form for the points z1,z2 on the elliptic curve e. Either z1 or z2 can also be a vector/matrix of points."},
-{"bin",21,(void*)binomial,4,"GL","bin(x,y)=binomial coefficient x*(x-1)...*(x-y+1)/y! defined for y in Z and any x."},
-{"binary",1,(void*)binaire,2,"G","binary(x)=gives the vector formed by the binary digits of x (x C-integer)."},
-{"bittest",2,(void*)gbittest,2,"GL","bittest(x,n)=gives bit number n (coefficient of 2^n) of the integer x."},
-{"boundcf",21,(void*)gboundcf,4,"GL","boundcf(x,lmax)=continued fraction expansion of x with at most lmax terms."},
-{"boundfact",21,(void*)boundfact,4,"GL","boundfact(x,lim)=partial factorization of the integer x (using primes up to lim)."},
-{"buchcertify",10,(void*)bnfcertify,6,"lG","buchcertify(bnf)=certify the correctness (i.e. remove the GRH) of the bnf data output by buchinit or buchinitfu."},
-{"buchfu",1,(void*)buchfu,6,"Gp","buchfu(bnf)=compute the fundamental units of the number field bnf output by buchinit."},
-{"buchgen",99,(void*)buchgenfu,6,BUCH_PROTO,"buchgen(P,...)=compute the structure of the class group and the regulator for the number field defined by the polynomial P. See manual for the other parameters (which can be omitted)."},
-{"buchgenforcefu",99,(void*)buchgenforcefu,6,BUCH_PROTO,"buchgenforcefu(P,...)=compute the structure of the class group, the regulator a primitive root of unity and a system of fundamental units for the number field defined by the polynomial P, and insist until the units are obtained. See manual for the other parameters (which can be omitted)."},
-{"buchgenfu",99,(void*)buchgenfu,6,BUCH_PROTO,"buchgenfu(P,...)=compute the structure of the class group, the regulator a primitive root of unity and a system of fundamental units (if they are not too large) for the number field defined by the polynomial P. See manual for the other parameters (which can be omitted)."},
-{"buchimag",99,(void*)buchimag,4,"GD0.1,G,D0.1,G,D5,G,","buchimag(D,...)=compute the structure of the class group of the complex quadratic field of discriminant D<0. See manual for the other parameters (which can be omitted)."},
-{"buchinit",99,(void*)buchinitfu,6,BUCH_PROTO,"buchinit(P,...)=compute the necessary data for future use in ideal and unit group computations. See manual for details."},
-{"buchinitforcefu",99,(void*)buchinitforcefu,6,BUCH_PROTO,"buchinitforcefu(P,...)=compute the necessary data for future use in ideal and unit group computations, and insist on having fundamental units. See manual for details."},
-{"buchinitfu",99,(void*)buchinitfu,6,BUCH_PROTO,"buchinitfu(P,...)=compute the necessary data for future use in ideal and unit group computations, including fundamental units if they are not too large. See manual for details."},
-{"buchnarrow",1,(void*)buchnarrow,6,"Gp","buchnarrow(bnf)=given a big number field as output by buchinitxx, gives as a 3-component vector the structure of the narrow class group."},
-{"buchray",2,(void*)buchray,6,"GGp","buchray(bnf,ideal)=given a big number field as output by buchinitfu (only) and  an ideal or a 2-component row vector formed by an ideal and a list of R1 zeros or ones representing a module, finds the ray class group structure corresponding to this module."},
-{"buchrayinit",2,(void*)buchrayinit,6,"GGp","buchrayinit(bnf,ideal)=same as buchrayinitgen, except that the generators are not explicitly computed."},
-{"buchrayinitgen",2,(void*)buchrayinitgen,6,"GGp","buchrayinitgen(bnf,ideal)=given a big number field as output by buchinitfu (only) and  an ideal or a 2-component row vector formed by an ideal and a list of R1 zeros or ones representing a module, initializes data for computing in the ray class group  corresponding to this module. In particular, the fifth component is the ray class group structure."},
-{"buchreal",97,(void*)buchreal,4,"GD0,G,D0.1,G,D0.1,G,D5,G,p","buchreal(D,...)=compute the structure of the class group and the regulator of the real quadratic field of discriminant D>0 in the wide sense. See manual for the other parameters (which can be omitted)."},
-{"bytesize",10,(void*)gsizebyte,2,"lG","bytesize(x)=number of bytes occupied by the complete tree of the object x."},
-{"ceil",1,(void*)gceil,2,"G","ceil(x)=ceiling of x=smallest integer>=x."},
-{"centerlift",1,(void*)centerlift,2,"G","centerlift(x)=centered lift of x. Same as lift except for integermods."},
-{"cf",1,(void*)gcf,4,"Gp","cf(x)=continued fraction expansion of x (x rational,real or rational function)."},
-{"cf2",2,(void*)gcf2,4,"GGp","cf2(b,x)=continued fraction expansion of x (x rational,real or rational function), where b is the vector of numerators of the continued fraction."},
-{"changevar",0,(void*)suppressed,11,"GG","changevar(x,y)=THIS FUNCTION HAS BEEN SUPPRESSED."},
-{"char",14,(void*)caradj,8,"GnD&","char(x,y)=det(y*I-x)=characteristic polynomial of the matrix x using the comatrix."},
-{"char1",14,(void*)caract,8,"Gn","char1(x,y)=det(y*I-x)=characteristic polynomial of the matrix x using Lagrange interpolation."},
-{"char2",14,(void*)carhess,8,"Gn","char2(x,y)=characteristic polynomial of the matrix x expressed with variable y, using the Hessenberg form. Can be much faster or much slower than char, depending on the base ring."},
-{"chell",2,(void*)ellchangecurve,5,"GG","chell(x,y)=change data on elliptic curve according to y=[u,r,s,t]."},
-{"chinese",2,(void*)chinese,4,"GG","chinese(x,y)=x,y being integers modulo mx and my,finds z such that z is congruent to x mod mx and y mod my."},
-{"chptell",2,(void*)ellchangepoint,5,"GG","chptell(x,y)=change data on point or vector of points x on an elliptic curve according to y=[u,r,s,t]."},
-{"classno",1,(void*)classno,4,"G","classno(x)=class number of discriminant x."},
-{"classno2",1,(void*)classno2,4,"G","classno2(x)=class number of discriminant x."},
-{"coeff",21,(void*)truecoeff,2,"GL","coeff(x,s)=coefficient of degree s of x, or the s-th component for vectors or matrices (for which it is simpler to use x[])."},
-{"compimag",2,(void*)qficomp,4,"GG","compimag(x,y)=Gaussian composition of the binary quadratic forms x and y of negative discriminant."},
-{"compo",21,(void*)compo,2,"GL","compo(x,s)=the s'th component of the internal representation of x. For vectors or matrices, it is simpler to use x[]."},
-{"compositum",2,(void*)compositum,6,"GG","compositum(pol1,pol2)=vector of all possible compositums of the number fields defined by the polynomials pol1 and pol2."},
-{"compositum2",2,(void*)compositum2,6,"GG","compositum2(pol1,pol2)=vector of all possible compositums of the number fields defined by the polynomials pol1 and pol2, with roots of pol1 and pol2 expressed on the compositum polynomials."},
-{"comprealraw",2,(void*)qfrcompraw,4,"GG","comprealraw(x,y)=Gaussian composition without reduction of the binary quadratic forms x and y of positive discriminant."},
-{"concat",2,(void*)concat,8,"GG","concat(x,y)=concatenation of x and y."},
-{"conductor",99,(void*)bnrconductor0,6,"GDGDGD1,L,","conductor(bnr,subgroup)=conductor of the subfield of the ray class field bnr given by buchrayinit, defined by the HNF matrix subgroup."},
-{"conductorofchar",2,(void*)bnrconductorofchar,6,"GG","conductorofchar(bnr,chi)=conductor of the character chi on the ray class group bnr."},
-{"conj",1,(void*)gconj,2,"G","conj(x)=the algebraic conjugate of x."},
-{"conjvec",1,(void*)conjvec,2,"Gp","conjvec(x)=conjugate vector of the algebraic number x."},
-{"content",1,(void*)content,4,"G","content(x)=gcd of all the components of x, when this makes sense."},
-{"convol",2,(void*)convol,7,"GG","convol(x,y)=convolution (or Hadamard product) of two power series."},
-{"core",1,(void*)core,4,"G","core(n)=unique (positive of negative) squarefree integer d dividing n such that n/d is a square."},
-{"core2",1,(void*)core2,4,"G","core2(n)=2-component row vector [d,f], where d is the unique squarefree integer dividing n such that n/d=f^2 is a square."},
-{"coredisc",1,(void*)coredisc,4,"G","coredisc(n)=discriminant of the quadratic field Q(sqrt(n))."},
-{"coredisc2",1,(void*)coredisc2,4,"G","coredisc2(n)=2-component row vector [d,f], where d is the discriminant of the quadratic field Q(sqrt(n)) and n=df^2. f may be a half integer."},
-{"cos",1,(void*)gcos,3,"Gp","cos(x)=cosine of x."},
-{"cosh",1,(void*)gcosh,3,"Gp","cosh(x)=hyperbolic cosine of x."},
-{"cvtoi",13,(void*)gcvtoi,2,"Gf","cvtoi(x)=truncation of x, without taking into account loss of integer part precision."},
-{"cyclo",11,(void*)polcyclo,7,"LDn","cyclo(n)=n-th cyclotomic polynomial."},
-{"decodefactor",1,(void*)factorback,4,"G","decodefactor(fa)=given a factorisation fa, gives the factored object back."},
-{"decodemodule",2,(void*)decodemodule,6,"GG","decodemodule(nf,fa)=given a coded module fa as in discrayabslist, gives the true module."},
-{"degree",10,(void*)degree,2,"lG","degree(x)=degree of the polynomial or rational function x. -1 if equal 0, 0 if non-zero scalar."},
-{"denom",1,(void*)denom,2,"G","denom(x)=denominator of x (or lowest common denominator in case of an array)."},
-{"deplin",1,(void*)deplin,8,"Gp","deplin(x)=finds a linear dependence between the columns of the matrix x."},
-{"deriv",14,(void*)deriv,7,"Gn","deriv(x,y)=derivative of x with respect to the main variable of y."},
-{"det",1,(void*)det,8,"G","det(x)=determinant of the matrix x."},
-{"det2",1,(void*)det2,8,"G","det2(x)=determinant of the matrix x (better for integer entries)."},
-{"detint",1,(void*)detint,8,"G","detint(x)=some multiple of the determinant of the lattice generated by the columns of x (0 if not of maximal rank). Useful with hermitemod."},
-{"diagonal",1,(void*)diagonal,8,"G","diagonal(x)=creates the diagonal matrix whose diagonal entries are the entries of the vector x."},
-{"dilog",1,(void*)dilog,3,"Gp","dilog(x)=dilogarithm of x."},
-{"dirdiv",2,(void*)dirdiv,7,"GG","dirdiv(x,y)=division of the Dirichlet series x by the Dir. series y."},
-{"direuler",83,(void*)direuler0,7,"V=GGEDG","direuler(p=a,b,expr)=Dirichlet Euler product of expression expr from p=a to p=b, limited to b terms. Expr should be a polynomial or rational function in p and X, and X is understood to mean p^(-s)."},
-{"dirmul",2,(void*)dirmul,7,"GG","dirmul(x,y)=multiplication of the Dirichlet series x by the Dir. series y."},
-{"dirzetak",2,(void*)dirzetak,6,"GG","dirzetak(nf,b)=Dirichlet series of the Dedekind zeta function of the number field nf up to the bound b-1."},
-{"disc",1,(void*)poldisc0,7,"GDn","disc(x)=discriminant of the polynomial x."},
-{"discf",1,(void*)nfdisc0,6,"GD0,L,DG","discf(x)=discriminant of the number field defined by the polynomial x using round 4."},
-{"discf2",1,(void*)nfdisc0,6,"GD2,L,DG","discf2(x)=discriminant of the number field defined by the polynomial x using round 2."},
-{"discrayabs",62,(void*)bnrdisc0,6,"GD0,G,D0,G,D0,L,","discrayabs(bnr,subgroup)=absolute [N,R1,disc] of the subfield of the ray class field bnr given by buchrayinit, defined by the HNF matrix subgroup."},
-{"discrayabscond",62,(void*)bnrdisc0,6,"GD0,G,D0,G,D2,L,","discrayabscond(bnr,subgroup)=absolute [N,R1,disc] of the subfield of the ray class field bnr given by buchrayinit, defined by the HNF matrix subgroup. Result is zero if fmodule is not the conductor."},
-{"discrayabslist",2,(void*)discrayabslist,6,"GG","discrayabslist(bnf,listes)=if listes is a 2-component vector as output by ideallistunit or similar, gives list of corresponding discrayabscond."},
-{"discrayabslistarch",32,(void*)discrayabslistarch,6,"GGL","discrayabslistarch(bnf,arch,bound)=gives list of discrayabscond of all modules up to norm bound with archimedean places arch, in a longvector format."},
-{"discrayabslistarchall",32,(void*)discrayabslistarch,6,"GL","discrayabslistarchall(bnf,bound)=gives list of discrayabscond of all modules up to norm bound with all possible archimedean places arch in reverse lexicographic order, in a longvector format."},
-{"discrayabslistlong",21,(void*)discrayabslistlong,6,"GL","discrayabslistlong(bnf,bound)=gives list of discrayabscond of all modules up to norm bound without archimedean places, in a longvector format."},
-{"discrayrel",62,(void*)bnrdisc0,6,"GD0,G,D0,G,D1,L,","discrayrel(bnr,subgroup)=relative [N,R1,rnfdisc] of the subfield of the ray class field bnr given by buchrayinit, defined by the HNF matrix subgroup."},
-{"discrayrelcond",62,(void*)bnrdisc0,6,"GD0,G,D0,G,D3,L,","discrayrelcond(bnr,subgroup)=relative [N,R1,rnfdisc] of the subfield of the ray class field bnr given by buchrayinit, defined by the HNF matrix subgroup. Result is zero if module is not the conductor."},
-{"divisors",1,(void*)divisors,4,"G","divisors(x)=gives a vector formed by the divisors of x in increasing order."},
-{"divres",2,(void*)gdiventres,1,"GG","divres(x,y)=euclidean division of x by y giving as a 2-dimensional column vector the quotient and the remainder."},
-{"divsum",22,(void*)sumdivexpr,9,"GVE","divsum(n,X,expr)=sum of expression expr, X running over the divisors of n."},
-{"eigen",1,(void*)eigen,8,"Gp","eigen(x)=eigenvectors of the matrix x given as columns of a matrix."},
-{"eint1",1,(void*)eint1,3,"Gp","eint1(x)=exponential integral E1(x)."},
-{"erfc",1,(void*)gerfc,3,"Gp","erfc(x)=complementary error function."},
-{"eta",1,(void*)eta,3,"Gp","eta(x)=eta function without the q^(1/24)."},
-{"euler",0,(void*)mpeuler,3,"p","euler=euler()=euler's constant with current precision."},
-{"eval",1,(void*)geval_gp,7,"GC","eval(x)=evaluation of x, replacing variables by their value."},
-{"exp",1,(void*)gexp,3,"Gp","exp(x)=exponential of x."},
-{"extract",2,(void*)extract0,8,"GGDG","extract(x,y)=extraction of the components of the vector x according to the vector or mask y, from left to right (1, 2, 4, 8, ...for the first, second, third, fourth,...component)."},
-{"fact",11,(void*)mpfactr,4,"Lp","fact(x)=factorial of x (x C-integer), the result being given as a real number."},
-{"factcantor",2,(void*)factcantor,4,"GG","factcantor(x,p)=factorization mod p of the polynomial x using Cantor-Zassenhaus."},
-{"factfq",3,(void*)factorff,4,"GGG","factfq(x,p,a)=factorization of the polynomial x in the finite field F_p[X]/a(X)F_p[X]."},
-{"factmod",2,(void*)factmod,4,"GG","factmod(x,p)=factorization mod p of the polynomial x using Berlekamp."},
-{"factor",1,(void*)factor,4,"G","factor(x)=factorization of x."},
-{"factoredbasis",28,(void*)factoredbase,6,"GG","factoredbasis(x,p)=integral basis of the maximal order defined by the polynomial x, where p is the matrix of the factorization of the discriminant of x."},
-{"factoreddiscf",2,(void*)factoreddiscf,6,"GG","factoreddiscf(x,p)=discriminant of the maximal order defined by the polynomial x, where p is the matrix of the factorization of the discriminant of x."},
-{"factoredpolred",2,(void*)factoredpolred,6,"GG","factoredpolred(x,p)=reduction of the polynomial x, where p is the matrix of the factorization of the discriminant of x (gives minimal polynomials only)."},
-{"factoredpolred2",2,(void*)factoredpolred2,6,"GG","factoredpolred2(x,p)=reduction of the polynomial x, where p is the matrix of the factorization of the discriminant of x (gives elements and minimal polynomials)."},
-{"factornf",2,(void*)polfnf,6,"GG","factornf(x,t)=factorization of the polynomial x over the number field defined by the polynomial t."},
-{"factorpadic",32,(void*)factorpadic,7,"GGL","factorpadic(x,p,r)=p-adic factorization of the polynomial x to precision r, using the round 4 algorithm."},
-{"factorpadic2",32,(void*)factorpadic0,7,"GGLD1,L,","factorpadic2(x,p,r)=p-adic factorization of the polynomial x to precision r, using Buchmann-Lenstra."},
-{"factpol",33,(void*)_factpol,7,"GLL","factpol(x,l,hint)=factorization over Z of the polynomial x up to degree l (complete if l=0) using Hensel lift, knowing that the degree of each factor is a multiple of hint."},
-{"factpol2",0,(void*)suppressed,6,"GL","factpol2(x,l)=factorization over Z of the polynomial x up to degree l (complete if l=0) using root finding."},
-{"fibo",11,(void*)fibo,4,"L","fibo(x)=fibonacci number of index x (x C-integer)."},
-{"floor",1,(void*)gfloor,2,"G","floor(x)=floor of x=largest integer<=x."},
-{"for",83,(void*)forpari,11,"vV=GGI","for(X=a,b,seq)=the sequence is evaluated, X going from a up to b."},
-{"fordiv",84,(void*)fordiv,11,"vGVI","fordiv(n,X,seq)=the sequence is evaluated, X running over the divisors of n."},
-{"forprime",83,(void*)forprime,11,"vV=GGI","forprime(X=a,b,seq)=the sequence is evaluated, X running over the primes between a and b."},
-{"forstep",86,(void*)forstep,11,"vV=GGGI","forstep(X=a,b,s,seq)=the sequence is evaluated, X going from a to b in steps of s."},
-{"forvec",87,(void*)forvec,11,"vV=GID0,L,","forvec(x=v,seq)=v being a vector of two-component vectors of length n, the sequence is evaluated with x[i] going from v[i][1] to v[i][2] for i=n,..,1."},
-{"fpn",21,(void*)ffinit,2,"GLDn","fpn(p,n)=monic irreducible polynomial of degree n over F_p[x]."},
-{"frac",1,(void*)gfrac,2,"G","frac(x)=fractional part of x=x-floor(x)."},
-{"galois",1,(void*)polgalois,6,"Gp","galois(x)=Galois group of the polynomial x (see manual for group coding)."},
-{"galoisapply",3,(void*)galoisapply,6,"GGG","galoisapply(nf,aut,x)=Apply the Galois automorphism sigma (polynomial or polymod) to the object x (element or ideal) in the number field nf."},
-{"galoisconj",1,(void*)galoisconj,6,"GDG","galoisconj(nf)=list of conjugates of a root of the polynomial x=nf[1] in the same number field, using p-adics, LLL on integral basis (not always complete)."},
-{"galoisconj1",0,(void*)suppressed,6,"G","galoisconj1(nf)=list of conjugates of a root of the polynomial x=nf[1] in the same number field nf, using complex numbers, LLL on integral basis (not always complete)."},
-{"galoisconjforce",0,(void*)suppressed,6,"G","galoisconjforce(nf)=list of conjugates of a root of the polynomial x=nf[1] in the Galois number field nf, using p-adics, LLL on integral basis. Guaranteed to be complete if the field is Galois, otherwise there is an infinite loop."},
-{"gamh",1,(void*)ggammah,3,"Gp","gamh(x)=gamma of x+1/2 (x integer)."},
-{"gamma",1,(void*)ggamma,3,"Gp","gamma(x)=gamma function at x."},
-{"gauss",2,(void*)gauss,8,"GG","gauss(a,b)=gaussian solution of ax=b (a matrix,b vector)."},
-{"gaussmodulo",3,(void*)gaussmodulo,8,"GGG","gaussmodulo(M,D,Y)=(long)gen_1 solution of system of congruences MX=Y mod D."},
-{"gaussmodulo2",3,(void*)gaussmodulo2,8,"GGG","gaussmodulo2(M,D,Y)=all solutions of system of congruences MX=Y mod D."},
-{"gcd",2,(void*)ggcd,4,"GG","gcd(x,y)=greatest common divisor of x and y."},
-{"getheap",0,(void*)getheap,2,"","getheap()=2-component vector giving the current number of objects in the heap and the space they occupy."},
-{"getrand",0,(void*)getrand,2,"","getrand()=current value of random number seed."},
-{"getstack",0,(void*)getstack,2,"l","getstack()=current value of stack pointer avma."},
-{"gettime",0,(void*)gettime,2,"l","gettime()=time (in milliseconds) since last call to gettime."},
-{"globalred",1,(void*)ellglobalred,5,"G","globalred(e)=e being an elliptic curve, returns [N,[u,r,s,t],c], where N is the conductor of e, [u,r,s,t] leads to the standard model for e, and c is the product of the local Tamagawa numbers c_p."},
-{"goto",0,(void*)suppressed,11,"s*","goto(n)=THIS FUNCTION HAS BEEN SUPPRESSED."},
-{"hclassno",1,(void*)hclassno,4,"G","hclassno(x)=Hurwitz-Kronecker class number of x>0."},
-{"hell",2,(void*)ghell,5,"GGp","hell(e,x)=canonical height of point x on elliptic curve E defined by the vector e computed using theta-functions."},
-{"hell2",2,(void*)ghell2,5,"GGp","hell2(e,x)=canonical height of point x on elliptic curve E defined by the vector e computed using Tate's method."},
-{"hermite",1,(void*)ZM_hnf,8,"G","hermite(x)=(upper triangular) Hermite normal form of x, basis for the lattice formed by the columns of x, using a naive algorithm."},
-{"hermite2",1,(void*)hnfall,8,"G","hermite2(x)=2-component vector [H,U] such that H is an (upper triangular) Hermite normal form of x, basis for the lattice formed by the columns of x, and U is a unimodular matrix such that xU=H, using Batut's algorithm."},
-{"hermitehavas",0,(void*)suppressed,8,"G","hermitehavas(x)=3-component vector [H,U,P] such that H is an (upper triangular) Hermite normal form of x with extra zero columns, U is a unimodular matrix and P is a permutation of the rows such that P applied to xU gives H, using Havas's algorithm."},
-{"hermitemod",2,(void*)hnfmod,8,"GG","hermitemod(x,d)=(upper triangular) Hermite normal form of x, basis for the lattice formed by the columns of x, where d is the non-zero determinant of this lattice."},
-{"hermitemodid",2,(void*)hnfmodid,8,"GG","hermitemodid(x,d)=(upper triangular) Hermite normal form of x concatenated with d times the identity matrix."},
-{"hermiteperm",1,(void*)hnfperm,8,"G","hermiteperm(x)=3-component vector [H,U,P] such that H is an (upper triangular) Hermite normal form of x with extra zero columns, U is a unimodular matrix and P is a permutation of the rows such that P applied to xU gives H, using Batut's algorithm."},
-{"hess",1,(void*)hess,8,"G","hess(x)=Hessenberg form of x."},
-{"hilb",30,(void*) hilbert,4,"lGGG","hilb(x,y,p)=Hilbert symbol at p of x,y (integers or fractions)."},
-{"hilbert",11,(void*)mathilbert,8,"L","hilbert(n)=Hilbert matrix of order n (n C-integer)."},
-{"hilbp",20,(void*) hilbert,4,"lGGDG","hilbp(x,y)=Hilbert symbol of x,y (where x or y is integermod or p-adic)."},
-{"hvector",22,(void*)vecteur,9,"GVE","hvector(n,X,expr)=row vector with n components of expression expr, the variable X ranging from 1 to n."},
-{"hyperu",3,(void*)hyperu,3,"GGGp","hyperu(a,b,x)=U-confluent hypergeometric function."},
-{"i",0,(void*)gen_I,2,"","i=i()=square root of -1."},
-{"idealadd",3,(void*)idealadd,6,"GGG","idealadd(nf,x,y)=sum of two ideals x and y in the number field defined by nf."},
-{"idealaddmultone",2,(void*)idealaddmultoone,6,"GG","idealaddone(nf,x,y)=when the sum of two ideals x and y in the number field K defined by nf is equal to Z_K, gives a two-component vector [a,b] such that a is in x, b is in y and a+b=1."},
-{"idealaddone",3,(void*)idealaddtoone,6,"GGG","idealaddmultone(nf,list)=when the sum of the ideals in the number field K defined by nf and given in the vector list is equal to Z_K, gives a vector of elements of the corresponding ideals who sum to 1."},
-{"idealappr",2,(void*)idealappr,6,"GGp","idealappr(nf,x)=x being a fractional ideal, gives an element b such that v_p(b)=v_p(x) for all prime ideals p dividing x, and v_p(b)>=0 for all other p."},
-{"idealapprfact",2,(void*)idealapprfact,6,"GG","idealapprfact(nf,x)=x being a prime ideal factorization with possibly zero or negative exponents, gives an element b such that v_p(b)=v_p(x) for all prime ideals p dividing x, and v_p(b)>=0 for all other p."},
-{"idealchinese",3,(void*)idealchinese,6,"GGG","idealchinese(nf,x,y)=x being a prime ideal factorization and y a vector of elements, gives an element b such that v_p(b-y_p)>=v_p(x) for all prime ideals p dividing x, and v_p(b)>=0 for all other p."},
-{"idealcoprime",3,(void*)idealcoprime,6,"GGG","idealcoprime(nf,x,y)=gives an element b in nf such that b.x is an integral ideal coprime to the integral ideal y."},
-{"idealdiv",3,(void*)idealdiv,6,"GGG","idealdiv(nf,x,y)=quotient x/y of two ideals x and y in HNF in the number field nf."},
-{"idealdivexact",3,(void*)idealdivexact,6,"GGG","idealdivexact(nf,x,y)=quotient x/y of two ideals x and y in HNF in the number field nf when the quotient is known to be an integral ideal."},
-{"idealfactor",2,(void*)idealfactor,6,"GG","idealfactor(nf,x)=factorization of the ideal x given in HNF into prime ideals in the number field nf."},
-{"idealhermite",2,(void*)idealhnf,6,"GG","idealhermite(nf,x)=hermite normal form of the ideal x in the number field nf, whatever form x may have."},
-{"idealhermite2",3,(void*)idealhnf0,6,"GGG","idealhermite2(nf,a,b)=hermite normal form of the ideal aZ_K+bZ_K in the number field K defined by nf, where a and b are elements."},
-{"idealintersect",3,(void*)idealintersect,6,"GGG","idealintersect(nf,x,y)=intersection of two ideals x and y in HNF in the number field defined by nf."},
-{"idealinv",2,(void*)idealinv,6,"GG","idealinv(nf,x)=inverse of the ideal x in the number field nf not using the different."},
-{"idealinv2",2,(void*)idealinv,6,"GG","idealinv2(nf,x)=inverse of the ideal x in the number field nf using the different."},
-{"ideallist",21,(void*)ideallist,6,"GL","ideallist(nf,bound)=vector of vectors of all ideals of norm<=bound in nf."},
-{"ideallistarch",3,(void*)ideallistarch,6,"GGG","ideallistarch(nf,list,arch)=vector of vectors of all zidealstarinits of all modules in list with archimedean arch added, without generators."},
-{"ideallistarchgen",3,(void*)ideallistarch,6,"GGG","ideallistarchgen(nf,list,arch)=vector of vectors of all zidealstarinits of all modules in list with archimedean arch added, with generators."},
-{"ideallistunit",21,(void*)ideallist0,6,"GLD2,L,","ideallistunit(bnf,bound)=2-component vector [L,U] where L is as ideallistzstar, and U is a vector of vector of zinternallogs of the units, without generators."},
-{"ideallistunitarch",3,(void*)ideallistarch,6,"GGG","ideallistunitarch(bnf,lists,arch)=adds the archimedean arch to the lists output by ideallistunit."},
-{"ideallistunitarchgen",3,(void*)ideallistarch,6,"GGG","ideallistunitarchgen(bnf,lists,arch)=adds the archimedean arch to the lists output by ideallistunitgen."},
-{"ideallistunitgen",21,(void*)ideallist0,6,"GLD3,L,","ideallistunitgen(bnf,bound)=2-component vector [L,U] where L is as ideallistzstar, and U is a vector of vector of zinternallogs of the units, with generators."},
-{"ideallistzstar",21,(void*)ideallist0,6,"GLD0,L,","ideallistzstar(nf,bound)=vector of vectors of all zidealstarinits of all ideals of norm<=bound, without generators."},
-{"ideallistzstargen",21,(void*)ideallist0,6,"GLD1,L,","ideallistzstargen(nf,bound)=vector of vectors of all zidealstarinits of all ideals of norm<=bound, with generators."},
-{"ideallllred",3,(void*)idealred0,6,"GGGp","ideallllred(nf,x,vdir)=LLL reduction of the ideal x in the number field nf along direction vdir, in HNF."},
-{"idealmul",3,(void*)idealmul,6,"GGG","idealmul(nf,x,y)=product of the two ideals x and y in the number field nf."},
-{"idealmulred",3,(void*)idealmulred,6,"GGGp","idealmulred(nf,x,y)=reduced product of the two ideals x and y in the number field nf."},
-{"idealnorm",2,(void*)idealnorm,6,"GG","idealnorm(nf,x)=norm of the ideal x in the number field nf."},
-{"idealpow",3,(void*)idealpow,6,"GGG","idealpow(nf,x,n)=n-th power of the ideal x in HNF in the number field nf."},
-{"idealpowred",3,(void*)idealpowred,6,"GGGp","idealpowred(nf,x,n)=reduced n-th power of the ideal x in HNF in the number field nf."},
-{"idealtwoelt",2,(void*)idealtwoelt,6,"GG","idealtwoelt(nf,x)=2-element representation of an ideal x in the number field nf."},
-{"idealtwoelt2",3,(void*)idealtwoelt2,6,"GGG","idealtwoelt2(nf,x,a)=2-element representation of an ideal x in the number field nf, with the first element equal to a."},
-{"idealval",30,(void*)idealval,6,"lGGG","idealval(nf,x,p)=valuation at p given in primedec format of the ideal x in the number field nf."},
-{"idmat",11,(void*)matid,8,"L","idmat(n)=identity matrix of order n (n C-integer)."},
-{"if",0,(void*)ifpari,11,"GDEDE","if(a,seq1,seq2): if a is nonzero, seq1 is evaluated, otherwise seq2. seq1 and seq2 are optional, and if seq2 is omitted, the preceding comma can be omitted also."},
-{"imag",1,(void*)gimag,2,"G","imag(x)=imaginary part of x."},
-{"image",1,(void*)image,8,"G","image(x)=basis of the image of the matrix x."},
-{"image2",1,(void*)image2,8,"G","image2(x)=basis of the image of the matrix x."},
-{"imagecompl",1,(void*)imagecompl,8,"G","imagecompl(x)=vector of column indices not corresponding to the indices given by the function image."},
-{"incgam",2,(void*)incgam,3,"GGp","incgam(s,x)=incomplete gamma function."},
-{"incgam1",2,(void*)suppressed,3,"GGp","incgam1(s,x)=incomplete gamma function (for debugging only)."},
-{"incgam2",2,(void*)suppressed,3,"GGp","incgam2(s,x)=incomplete gamma function (for debugging only)."},
-{"incgam3",2,(void*)incgamc,3,"GGp","incgam3(s,x)=complementary incomplete gamma function."},
-{"incgam4",3,(void*)incgam0,3,"GGGp","incgam4(s,x,y)=incomplete gamma function where y=gamma(s) is precomputed."},
-{"indexrank",1,(void*)indexrank,8,"G","indexrank(x)=gives two extraction vectors (rows and columns) for the matrix x such that the exracted matrix is square of maximal rank."},
-{"indsort",1,(void*)indexsort,8,"G","indsort(x)=indirect sorting of the vector x."},
-{"initalg",1,(void*)nfinit,6,"Gp","initalg(x)=x being a nonconstant irreducible polynomial, gives the vector: [x,[r1,r2],nfdisc,index,[M,MC,T2,T,different] (see manual),r1+r2 first roots, integral basis, matrix of power basis in terms of integral basis, multiplication table of basis]."},
-{"initalgred",1,(void*)nfinitred,6,"Gp","initalgred(x)=x being a nonconstant irreducible polynomial, finds (using polred) a simpler polynomial pol defining the same number field, and gives the vector: [pol,[r1,r2],nfdisc,index,[M,MC,T2,T,different] (see manual), r1+r2 first roots, integral basis, matrix of power basis in terms of integral basis, multiplication table of basis]."},
-{"initalgred2",1,(void*)nfinitred2,6,"Gp","initalgred2(P)=P being a nonconstant irreducible polynomial, gives a two-element vector [nf,mod(a,pol)], where nf is as output by nfinitred and mod(a,pol) is a polymod equal to mod(x,P) and pol=nf[1]."},
-{"initell",1,(void*)ellinit,5,"GDGp","initell(x)=x being the vector [a1,a2,a3,a4,a6], gives the vector: [a1,a2,a3,a4,a6,b2,b4,b6,b8,c4,c6,delta,j,[e1,e2,e3],w1,w2,eta1,eta2,q,area]."},
-{"initzeta",1,(void*)initzeta,6,"Gp","initzeta(x)=compute number field information necessary to use zetak, where x is an irreducible polynomial."},
-{"integ",14,(void*)integ,7,"Gn","integ(x,y)=formal integration of x with respect to the main variable of y."},
-{"intersect",2,(void*)intersect,8,"GG","intersect(x,y)=intersection of the vector spaces whose bases are the columns of x and y."},
-{"intgen",99,(void*)intnumromb0,9,"V=GGED1,L,p","intgen(X=a,b,s)=general numerical integration of s from a to b with respect to X, to be used after removing singularities."},
-{"intinf",99,(void*)intnumromb0,9,"V=GGED2,L,p","intinf(X=a,b,s)=numerical integration of s from a to b with respect to X, where a or b can be plus or minus infinity (1.0e4000), but of same sign."},
-{"intnum",99,(void*)intnumromb0,9,"V=GGED0,L,p","intnum(X=a,b,s)=numerical integration of s from a to b with respect to X."},
-{"intopen",99,(void*)intnumromb0,9,"V=GGED3,L,p","intopen(X=a,b,s)=numerical integration of s from a to b with respect to X, where s has only limits at a or b."},
-{"inverseimage",2,(void*)inverseimage,8,"GG","inverseimage(x,y)=an element of the inverse image of the vector y by the matrix x if one exists, the empty vector otherwise."},
-{"isdiagonal",10,(void*)isdiagonal,8,"lG","isdiagonal(x)=true(1) if x is a diagonal matrix, false(0) otherwise."},
-{"isfund",1,(void*)isfundamental,4,"lG","isfund(x)=true(1) if x is a fundamental discriminant (including 1), false(0) if not."},
-{"isideal",20,(void*)isideal,6,"lGG","isideal(nf,x)=true(1) if x is an ideal in the number field nf, false(0) if not."},
-{"isincl",2,(void*)nfisincl,6,"GG","isincl(x,y)=tests whether the number field defined by the polynomial x is isomorphic to a subfield of the one defined by y; 0 if not, otherwise all the isomorphisms."},
-{"isinclfast",2,(void*)nfisincl,6,"GG","isinclfast(nf1,nf2)=tests whether the number nf1 is isomorphic to a subfield of nf2 or not. If it gives a non-zero result, this proves that this is the case. However if it gives zero, nf1 may still be isomorphic to a subfield of nf2 so you have to use the much slower isincl to be sure."},
-{"isirreducible",1,(void*)isirreducible,7,"lG","isirreducible(x)=true(1) if x is an irreducible non-constant polynomial, false(0) if x is reducible or constant."},
-{"isisom",2,(void*)nfisisom,6,"GG","isisom(x,y)=tests whether the number field defined by the polynomial x is isomorphic to the one defined by y; 0 if not, otherwise all the isomorphisms."},
-{"isisomfast",2,(void*)nfisisom,6,"GG","isisomfast(nf1,nf2)=tests whether the number fields nf1 and nf2 are isomorphic or not. If it gives a non-zero result, this proves that they are isomorphic. However if it gives zero, nf1 and nf2 may still be isomorphic so you have to use the much slower isisom to be sure."},
-{"isoncurve",20,(void*)oncurve,5,"iGG","isoncurve(e,x)=true(1) if x is on elliptic curve e, false(0) if not."},
-{"isprime",1,(void*)gisprime,4,"GD0,L,","isprime(x)=true(1) if x is a strong pseudoprime for 10 random bases, false(0) if not."},
-{"isprincipal",2,(void*)isprincipal,6,"GG","isprincipal(bnf,x)=bnf being output by buchinit, gives the vector of exponents on the class group generators of x. In particular x is principal if and only if the result is the zero vector."},
-{"isprincipalforce",2,(void*)isprincipalforce,6,"GG","isprincipalforce(bnf,x)=same as isprincipal, except that the precision is doubled until the result is obtained."},
-{"isprincipalgen",2,(void*)isprincipalgen,6,"GG","isprincipalgen(bnf,x)=bnf being output by buchinit, gives [v,alpha,bitaccuracy], where v is the vector of exponents on the class group generators and alpha is the generator of the resulting principal ideal. In particular x is principal if and only if v is the zero vector."},
-{"isprincipalgenforce",2,(void*)isprincipalgenforce,6,"GG","isprincipalgenforce(bnf,x)=same as isprincipalgen, except that the precision is doubled until the result is obtained."},
-{"isprincipalray",2,(void*)isprincipalray,6,"GG","isprincipalray(bnf,x)=bnf being output by buchrayinit, gives the vector of exponents on the ray class group generators of x. In particular x is principal if and only if the result is the zero vector."},
-{"isprincipalraygen",2,(void*)isprincipalraygen,6,"GG","isprincipalraygen(bnf,x)=bnf being output by buchrayinit, gives [v,alpha,bitaccuracy], where v is the vector of exponents on the class group generators and alpha is the generator of the resulting principal ideal. In particular x is principal if and only if v is the zero vector."},
-{"ispsp",1,(void*)gispseudoprime,4,"GD1,L,","ispsp(x)=true(1) if x is a strong pseudoprime, false(0) if not."},
-{"isqrt",1,(void*)sqrtint,4,"G","isqrt(x)=integer square root of x (x integer)."},
-{"isset",10,(void*)setisset,8,"lG","isset(x)=true(1) if x is a set (row vector with strictly increasing entries), false(0) if not."},
-{"issqfree",1,(void*)issquarefree,4,"lG","issqfree(x)=true(1) if x is squarefree, false(0) if not."},
-{"issquare",1,(void*)issquare,4,"lG","issquare(x)=true(1) if x is a square, false(0) if not."},
-{"isunit",2,(void*)bnfisunit,6,"GG","isunit(bnf,x)=bnf being output by buchinit, gives the vector of exponents of x on the fundamental units and the roots of unity if x is a unit, the empty vector otherwise."},
-{"jacobi",1,(void*)jacobi,8,"Gp","jacobi(x)=eigenvalues and orthogonal matrix of eigenvectors of the real symmetric matrix x."},
-{"jbesselh",2,(void*)jbesselh,3,"GGp","jbesselh(n,x)=J-bessel function of index n+1/2 and argument x, where n is a non-negative integer."},
-{"jell",1,(void*)jell,3,"Gp","jell(x)=elliptic j invariant of x."},
-{"karamul",0,(void*)suppressed,7,"GGL","karamul(x,y,k)=THIS FUNCTION HAS BEEN SUPPRESSED."},
-{"kbessel",2,(void*)kbessel,3,"GGp","kbessel(nu,x)=K-bessel function of index nu and argument x (x positive real of type real, nu of any scalar type)."},
-{"kbessel2",2,(void*)kbessel,3,"GGp","kbessel2(nu,x)=K-bessel function of index nu and argument x (x positive real of type real, nu of any scalar type)."},
-{"ker",1,(void*)ker,8,"G","ker(x)=basis of the kernel of the matrix x."},
-{"keri",1,(void*)keri,8,"G","keri(x)=basis of the kernel of the matrix x with integer entries."},
-{"kerint",1,(void*)matkerint0,8,"GD0,L,","kerint(x)=LLL-reduced Z-basis of the kernel of the matrix x with integral entries using a modified LLL."},
-{"kerint1",1,(void*)matkerint0,8,"GD1,L,","kerint1(x)=LLL-reduced Z-basis of the kernel of the matrix x with rational entries using matrixqz3 and the HNF."},
-{"kerint2",1,(void*)suppressed,8,"G","kerint2(x)=LLL-reduced Z-basis of the kernel of the matrix x with integral entries using a modified LLL."},
-{"kro",2,(void*)kronecker,4,"lGG","kro(x,y)=kronecker symbol (x/y)."},
-{"label",0,(void*)suppressed,11,"s*","label(n)=THIS FUNCTION HAS BEEN SUPPRESSED."},
-{"lambdak",2,(void*)glambdak,6,"GGp","lambdak(nfz,s)=Dedekind lambda function of the number field nfz at s, where nfz is the vector computed by initzeta (NOT by nfinit)."},
-{"laplace",1,(void*)laplace,7,"G","laplace(x)=replaces the power series sum of a_n*x^n/n! by sum of a_n*x^n."},
-{"lcm",2,(void*)glcm,4,"GG","lcm(x,y)=least common multiple of x and y=x*y/gcd(x,y)."},
-{"legendre",11,(void*)pollegendre,7,"LDn","legendre(n)=legendre polynomial of degree n (n C-integer)."},
-{"length",1,(void*)glength,2,"lG","length(x)=number of non code words in x."},
-{"lex",20,(void*)lexcmp,2,"iGG","lex(x,y)=compare x and y lexicographically (1 if x>y, 0 if x=y, -1 if x<y)."},
-{"lexsort",1,(void*)lexsort,8,"G","lexsort(x)=sort the elements of the vector x in ascending lexicographic order."},
-{"lift",1,(void*)lift,2,"G","lift(x)=lifts every element of Z/nZ to Z or Z[x]/PZ[x] to Z[x]."},
-{"lindep",1,(void*)lindep,8,"G","lindep(x)=Z-linear dependencies between components of x (Hastad et al)."},
-{"lindep2",23,(void*)lindep2,8,"GL","lindep2(x,dec)=Z-linear dependencies between components of x using LLL, where dec should be about one half the number of decimal digits of precision."},
-{"lll",1,(void*)lll,8,"Gp","lll(x)=lll reduction of the vectors forming the matrix x (gives the unimodular transformation matrix)."},
-{"lll1",1,(void*)suppressed,8,"Gp","lll1(x)=old version of lll reduction of the vectors forming the matrix x (gives the unimodular transformation matrix)."},
-{"lllgen",1,(void*)lllgen,8,"Gp","lllgen(x)=lll reduction of the vectors forming the matrix x with polynomial coefficients (gives the unimodular transformation matrix)."},
-{"lllgram",1,(void*)lllgram,8,"Gp","lllgram(x)=lll reduction of the lattice whose gram matrix is x (gives the unimodular transformation matrix)."},
-{"lllgram1",1,(void*)suppressed,8,"Gp","lllgram1(x)=old version of lll reduction of the lattice whose gram matrix is x (gives the unimodular transformation matrix)."},
-{"lllgramgen",1,(void*)lllgramgen,8,"G","lllgramgen(x)=lll reduction of the lattice whose gram matrix is x with polynomial coefficients (gives the unimodular transformation matrix)."},
-{"lllgramint",1,(void*)lllgramint,8,"G","lllgramint(x)=lll reduction of the lattice whose gram matrix is the integral matrix x (gives the unimodular transformation matrix)."},
-{"lllgramkerim",1,(void*)lllgramkerim,8,"G","lllgramkerim(x)=kernel and lll reduction of the lattice whose gram matrix is the integral matrix x."},
-{"lllgramkerimgen",1,(void*)lllgramkerimgen,8,"G","lllgramkerimgen(x)=kernel and lll reduction of the lattice whose gram matrix is the matrix x with polynomial coefficients."},
-{"lllint",1,(void*)lllint,8,"G","lllint(x)=lll reduction of the vectors forming the matrix x when the gram matrix is integral (gives the unimodular transformation matrix)."},
-{"lllintpartial",1,(void*)lllintpartial,8,"G","lllintpartial(x)=partial (hence faster) lll reduction of the vectors forming the matrix x when the gram matrix is integral (gives the unimodular transformation matrix)."},
-{"lllkerim",1,(void*)lllkerim,8,"G","lllkerim(x)=kernel and lll reduction of the vectors forming the integral matrix x."},
-{"lllkerimgen",1,(void*)lllkerimgen,8,"G","lllkerimgen(x)=kernel and lll reduction of the vectors forming the matrix x with polynomial coefficients."},
-{"lllrat",1,(void*)suppressed,8,"G","lllrat(x)=lll reduction of the vectors forming the matrix x, computations done with rational numbers (gives the unimodular transformation matrix)."},
-{"ln",1,(void*)glog,3,"Gp","ln(x)=log(x)=natural logarithm of x."},
-{"lngamma",1,(void*)glngamma,3,"Gp","lngamma(x)=logarithm of the gamma function of x."},
-{"localred",2,(void*)elllocalred,5,"GG","localred(e,p)=e being an ellliptic curve, returns [f,kod,[u,r,s,t],c], where f is the conductor's exponent, kod is the kodaira type for e at p, [u,r,s,t] is the change of variable needed to make e minimal at p, and c is the local Tamagawa number c_p."},
-{"log",1,(void*)glog,3,"Gp","log(x)=ln(x)=natural logarithm of x."},
-{"logagm",1,(void*)glog,3,"Gp","logagm(x)=natural logarithm of x, computed using agm (faster than log for more than a few hundred decimal digits)."},
-{"lseriesell",4,(void*)lseriesell0,5,"GGGGp","lseriesell(e,s,N,A)=L-series at s of the elliptic curve e, where |N| is the conductor, sign(N) the sign of the functional equation, and A a cut-off point close to 1."},
-{"makebigbnf",1,(void*)bnfinit0,6,"GD0,L,DGp","makebigbnf(sbnf)=transforms small sbnf as output by smallbuchinit into a true big bnf."},
-{"mat",1,(void*)gtomat,8,"G","mat(x)=transforms any GEN x into a matrix."},
-{"matextract",3,(void*)extract0,8,"GGG","matextract(x,y,z)=extraction of the components of the matrix x according to the vector or masks y (for the rows) and z (for the columns) from left to right (1,2,4,8,...for the first, second, third, fourth, ...rows or columns)."},
-{"mathell",2,(void*)mathell,5,"GGp","mathell(e,x)=gives the height matrix for vector of points x on elliptic curve e using theta functions."},
-{"matrix",49,(void*)matrice,9,"GGVVE","matrix(m,n,X,Y,expr)=mXn matrix of expression expr, the row variable X going  from 1 to m and the column variable Y going from 1 to n."},
-{"matrixqz",2,(void*)QM_minors_coprime,8,"GG","matrixqz(x,p)=transforms the rational or integral mxn (m>=n) matrix x into an integral matrix with gcd of maximal determinants equal to 1 if p is equal to 0, not divisible by p otherwise."},
-{"matrixqz2",1,(void*)QM_ImZ_hnf,8,"G","matrixqz2(x)=finds a basis of the intersection with Z^n of the lattice spanned by the columns of x."},
-{"matrixqz3",1,(void*)QM_ImQ_hnf,8,"G","matrixqz3(x)=finds a basis of the intersection with Z^n of the Q-vector space spanned by the columns of x."},
-{"matsize",1,(void*)matsize,2,"G","matsize(x)=number of rows and columns of the vector/matrix x as a 2-vector."},
-{"max",2,(void*)gmax,1,"GG","max(x,y)=maximum of x and y."},
-{"min",2,(void*)gmin,1,"GG","min(x,y)=minimum of x and y."},
-{"minideal",3,(void*)idealmin,6,"GGG","idealmin(nf,ix,vdir)=minimum of the ideal ix in the direction vdir in the number field nf."},
-{"minim",33,(void*)minim,8,"GGG","minim(x,bound,maxnum)=number of vectors of square norm <= bound, maximum norm and list of vectors for the integral and definite quadratic form x; minimal non-zero vectors if bound=0."},
-{"minim2",23,(void*)minim2,8,"GG","minim2(x,bound)=looks for vectors of square norm <= bound, return the first one and its norm."},
-{"mod",25,(void*)gmodulo,2,"GG","mod(x,y)=creates the integer x modulo y on the PARI stack."},
-{"modp",25,(void*)gmodulo,2,"GG","modp(x,y)=creates the integer x modulo y as a permanent object (on the heap)."},
-{"modreverse",1,(void*)modreverse,6,"G","modreverse(x)=reverse polymod of the polymod x, if it exists."},
-{"modulargcd",2,(void*)QX_gcd,2,"GG","modulargcd(x,y)=gcd of the polynomials x and y using the modular method."},
-{"mu",1,(void*)moebius,4,"lG","mu(x)=Moebius function of x."},
-{"newtonpoly",2,(void*)newtonpoly,6,"GG","newtonpoly(x,p)=Newton polygon of polynomial x with respect to the prime p."},
-{"nextprime",1,(void*)nextprime,4,"G","nextprime(x)=smallest prime number>=x."},
-{"nfdetint",2,(void*)nfdetint,6,"GG","nfdetint(nf,x)=multiple of the ideal determinant of the pseudo generating set x."},
-{"nfdiv",3,(void*)nfdiv,6,"GGG","nfdiv(nf,a,b)=element a/b in nf."},
-{"nfdiveuc",3,(void*)nfdiveuc,6,"GGG","nfdiveuc(nf,a,b)=gives algebraic integer q such that a-bq is small."},
-{"nfdivres",3,(void*)nfdivrem,6,"GGG","nfdivres(nf,a,b)=gives [q,r] such that r=a-bq is small."},
-{"nfhermite",2,(void*)nfhnf,6,"GG","nfhermite(nf,x)=if x=[A,I], gives a pseudo-basis of the module sum A_jI_j."},
-{"nfhermitemod",3,(void*)nfhnfmod,6,"GGG","nfhermitemod(nf,x,detx)=if x=[A,I], and detx is a multiple of the ideal determinant of x, gives a pseudo-basis of the module sum A_jI_j."},
-{"nfmod",3,(void*)nfmod,6,"GGG","nfmod(nf,a,b)=gives r such that r=a-bq is small with q algebraic integer."},
-{"nfmul",3,(void*)nfmul,6,"GGG","nfmul(nf,a,b)=element a.b in nf."},
-{"nfpow",3,(void*)nfpow,6,"GGG","nfpow(nf,a,k)=element a^k in nf."},
-{"nfreduce",3,(void*)nfreduce,6,"GGG","nfreduce(nf,a,id)=gives r such that a-r is the ideal id and r is small."},
-{"nfsmith",2,(void*)nfsnf,6,"GG","nfsmith(nf,x)=if x=[A,I,J], outputs [c_1,...c_n] Smith normal form of x."},
-{"nfval",30,(void*)nfval,6,"lGGG","nfval(nf,a,pr)=valuation of element a at the prime pr."},
-{"norm",1,(void*)gnorm,2,"G","norm(x)=norm of x."},
-{"norml2",1,(void*)gnorml2,2,"G","norml2(x)=square of the L2-norm of the vector x."},
-{"nucomp",3,(void*)nucomp,4,"GGG","nucomp(x,y,l)=composite of primitive positive definite quadratic forms x and y using nucomp and nudupl, where l=[|D/4|^(1/4)] is precomputed."},
-{"numdiv",1,(void*)numdiv,4,"G","numdiv(x)=number of divisors of x."},
-{"numer",1,(void*)numer,2,"G","numer(x)=numerator of x."},
-{"nupow",2,(void*)nupow,4,"GG","nupow(x,n)=n-th power of primitive positive definite quadratic form x using nucomp and nudupl."},
-{"o",0,(void*)ggrando,7,"GD1,L,","o(a^b): p-adic or power series zero with precision given by b."},
-{"omega",1,(void*)omega,4,"lG","omega(x)=number of unrepeated prime divisors of x."},
-{"ordell",2,(void*)ellordinate,5,"GGp","ordell(e,x)=y-coordinates corresponding to x-ordinate x on elliptic curve e."},
-{"order",1,(void*)order,4,"G","order(x)=order of the integermod x in (Z/nZ)*."},
-{"orderell",2,(void*)orderell,5,"GG","orderell(e,p)=order of the point p on the elliptic curve e over Q, 0 if non-torsion."},
-{"ordred",1,(void*)polredord,6,"Gp","ordred(x)=reduction of the polynomial x, staying in the same order."},
-{"padicprec",20,(void*)padicprec,2,"lGG","padicprec(x,p)=absolute p-adic precision of object x."},
-{"pascal",99,(void*)matqpascal,8,"LDG","pascal(n)=pascal triangle of order n (n C-integer)."},
-{"perf",10,(void*)perf,8,"G","perf(a)=rank of matrix of xx~ for x minimal vectors of a gram matrix a."},
-{"permutation",24,(void*)numtoperm,2,"LG","permutation(n,k)=permutation number k (mod n!) of n letters (n C-integer)."},
-{"permutation2num",1,(void*)permtonum,2,"G","permutation2num(vect)=ordinal (between 1 and n!) of permutation vect."},
-{"pf",2,(void*)primeform,4,"GGp","pf(x,p)=returns the prime form whose first coefficient is p, of discriminant x."},
-{"phi",1,(void*)eulerphi,4,"G","phi(x)=Euler's totient function of x."},
-{"pi",0,(void*)mppi,3,"p","pi=pi()=the constant pi, with current precision."},
-{"pnqn",1,(void*)pnqn,4,"G","pnqn(x)=[p_n,p_{n-1};q_n,q_{n-1}] corresponding to the continued fraction x."},
-{"pointell",2,(void*)pointell,5,"GGp","pointell(e,z)=coordinates of point on the curve e corresponding to the complex number z."},
-{"polint",31,(void*)polint,7,"GGGD&","polint(xa,ya,x)=polynomial interpolation at x according to data vectors xa, ya."},
-{"polred",1,(void*)polred,6,"G","polred(x)=reduction of the polynomial x (gives minimal polynomials only)."},
-{"polred2",1,(void*)polred2,6,"G","polred2(x)=reduction of the polynomial x (gives elements and minimal polynomials)."},
-{"polredabs",1,(void*)polredabs,6,"G","polredabs(x)=a smallest generating polynomial of the number field for the T2 norm on the roots, with smallest index for the minimal T2 norm."},
-{"polredabs2",1,(void*)polredabs2,6,"G","polredabs2(x)=gives [pol,a] where pol is as in polredabs, and alpha is the element whose characteristic polynomial is pol."},
-{"polredabsall",1,(void*)polredabsall,6,"G","polredabsall(x)=complete list of the smallest generating polynomials of the number field for the T2 norm on the roots."},
-{"polredabsfast",0,(void*)suppressed,6,"G","polredabsfast(x)=a smallest generating polynomial of the number field for the T2 norm on the roots."},
-{"polredabsnored",1,(void*)polredabs,6,"G","polredabsnored(x)=a smallest generating polynomial of the number field for the T2 norm on the roots without initial polred."},
-{"polsym",21,(void*)polsym,7,"GL","polsym(x,n)=vector of symmetric powers of the roots of x up to n."},
-{"polvar",1,(void*)gpolvar,2,"G","polvar(x)=main variable of object x. Gives p for p-adic x, error for scalars."},
-{"poly",14,(void*)gtopoly,2,"Gn","poly(x,v)=convert x (usually a vector or a power series) into a polynomial with variable v, starting with the leading coefficient."},
-{"polylog",24,(void*)gpolylog,3,"LGp","polylog(m,x)=m-th polylogarithm of x."},
-{"polylogd",24,(void*)polylogd,3,"LGp","polylogd(m,x)=D_m~-modified m-th polylog of x."},
-{"polylogdold",24,(void*)polylogdold,3,"LGp","polylogdold(m,x)=D_m-modified m-th polylog of x."},
-{"polylogp",24,(void*)polylogp,3,"LGp","polylogp(m,x)=P_m-modified m-th polylog of x."},
-{"polyrev",14,(void*)gtopolyrev,2,"Gn","polyrev(x,v)=convert x (usually a vector or a power series) into a polynomial with variable v, starting with the constant term."},
-{"polzag",21,(void*)polzag,9,"LL","polzag(n,m)=Zagier's polynomials of index n,m."},
-{"powell",3,(void*)ellmul,5,"GGGp","powell(e,x,n)=n times the point x on elliptic curve e (n in Z)."},
-{"powrealraw",23,(void*)qfrpowraw,4,"GL","powrealraw(x,n)=n-th power without reduction of the binary quadratic form x of positive discriminant."},
-{"prec",21,(void*)gprec,2,"GL","prec(x,n)=change the precision of x to be n (n C-integer)."},
-{"precision",1,(void*)precision0,2,"GD0,L,","precision(x)=real precision of object x."},
-{"prime",11,(void*)prime,4,"L","prime(n)=returns the n-th prime (n C-integer)."},
-{"primedec",2,(void*)idealprimedec,6,"GG","primedec(nf,p)=prime ideal decomposition of the prime number p in the number field nf as a vector of 5 component vectors [p,a,e,f,b] representing the prime ideals pZ_K+a.Z_K, e,f as usual, a as vector of components on the  integral basis, b Lenstra's constant."},
-{"primes",11,(void*)primes,4,"L","primes(n)=returns the vector of the first n primes (n C-integer)."},
-{"primroot",1,(void*)znprimroot,4,"G","primroot(n)=returns a primitive root of n when it exists."},
-{"principalideal",2,(void*)principalideal,6,"GG","principalideal(nf,x)=returns the principal ideal generated by the algebraic number x in the number field nf."},
-{"principalidele",2,(void*)suppressed,6,"GG","principalidele(nf,x)=returns the principal idele generated by the algebraic number x in the number field nf."},
-{"prod",48,(void*)prod0,9,"GV=GGE","prod(x,X=a,b,expr)=x times the product (X runs from a to b) of expression."},
-{"prodeuler",37,(void*)prodeuler0,9,"V=GGEp","prodeuler(X=a,b,expr)=Euler product (X runs over the primes between a and b) of real or complex expression."},
-{"prodinf",27,(void*)prodinf0,9,"V=GED0,L,p","prodinf(X=a,expr)=infinite product (X goes from a to infinity) of real or complex expression."},
-{"prodinf1",27,(void*)prodinf0,9,"V=GED1,L,p","prodinf1(X=a,expr)=infinite product (X goes from a to infinity) of real or complex 1+expression."},
-{"psi",1,(void*)gpsi,3,"Gp","psi(x)=psi-function at x."},
-{"qfi",3,(void*)qfi,4,"GGG","qfi(a,b,c)=binary quadratic form a*x^2+b*x*y+c*y^2 with b^2-4*a*c<0."},
-{"qfr",4,(void*)qfr,4,"GGGG","qfr(a,b,c,d)=binary quadratic form a*x^2+b*x*y+c*y^2 with b^2-4*a*c>0 and distance d."},
-{"quaddisc",1,(void*)quaddisc,4,"G","quaddisc(x)=discriminant of the quadratic field Q(sqrt(x))."},
-{"quadgen",1,(void*)quadgen,2,"G","quadgen(x)=standard generator of quadratic order of discriminant x."},
-{"quadpoly",1,(void*)quadpoly,2,"G","quadpoly(x)=quadratic polynomial corresponding to the discriminant x."},
-{"random",0,(void*)genrand,2,"DG","random()=random integer between 0 and 2^31-1."},
-{"rank",10,(void*)rank,8,"lG","rank(x)=rank of the matrix x."},
-{"rayclassno",2,(void*)bnrclassno,6,"GG","rayclassno(bnf,x)=ray class number of the module x for the big number field bnf. Faster than buchray if only the ray class number is wanted."},
-{"rayclassnolist",2,(void*)bnrclassnolist,6,"GG","rayclassnolist(bnf,liste)=if listes is as output by idealisunit or similar, gives list of corresponding ray class numbers."},
-{"real",1,(void*)greal,2,"G","real(x)=real part of x."},
-{"recip",1,(void*)polrecip,7,"G","recip(x)=reciprocal polynomial of x."},
-{"redimag",1,(void*)redimag,4,"G","redimag(x)=reduction of the binary quadratic form x with D<0."},
-{"redreal",1,(void*)redreal,4,"G","redreal(x)=reduction of the binary quadratic form x with D>0."},
-{"redrealnod",2,(void*)redrealnod,4,"GG","redrealnod(x,sq)=reduction of the binary quadratic form x with D>0 without distance function where sq=[sqrt D]."},
-{"reduceddisc",1,(void*)reduceddiscsmith,7,"G","reduceddisc(f)=vector of elementary divisors of Z[a]/f'(a)Z[a], where a is a root of the polynomial f."},
-{"regula",1,(void*)quadregulator,4,"Gp","regula(x)=regulator of the real quadratic field of discriminant x."},
-{"reorder",0,(void*)suppressed,11,"G","reorder(x)=THIS FUNCTION HAS BEEN SUPPRESSED."},
-{"resultant",2,(void*)resultant_all,7,"GGD&","resultant(x,y)=resultant of the polynomials x and y with exact entries."},
-{"resultant2",2,(void*)resultant2,7,"GG","resultant2(x,y)=resultant of the polynomials x and y."},
-{"reverse",1,(void*)serreverse,7,"G","reverse(x)=reversion of the power series x."},
-{"rhoreal",1,(void*)rhoreal,4,"G","rhoreal(x)=single reduction step of the binary quadratic form x of positive discriminant."},
-{"rhorealnod",2,(void*)rhorealnod,4,"GG","rhorealnod(x,sq)=single reduction step of the binary quadratic form x with D>0 without distance function where sq=[sqrt D]."},
-{"rndtoi",13,(void*)grndtoi,2,"Gf","rndtoi(x)=take the nearest integer to all the coefficients of x, without taking into account loss of integer part precision."},
-{"rnfbasis",2,(void*)rnfbasis,6,"GG","rnfbasis(bnf,order)=given an order as output by rnfpseudobasis or rnfsteinitz, gives either a basis of the order if it is free, or an n+1-element generating set."},
-{"rnfdiscf",2,(void*)rnfdiscf,6,"GG","rnfdiscf(nf,pol)=given a pol with coefficients in nf, gives a 2-component vector [D,d], where D is the relative ideal discriminant, and d is the relative discriminant in nf^*/nf*^2."},
-{"rnfequation",2,(void*)rnfequation,6,"GG","rnfequation(nf,pol)=given a pol with coefficients in nf, gives the absolute equation of the number field defined by pol."},
-{"rnfequation2",2,(void*)rnfequation2,6,"GG","rnfequation2(nf,pol)=given a pol with coefficients in nf, gives [apol,th], where apol is the absolute equation of the number field defined by pol and th expresses the root of nf[1] in terms of the root of apol."},
-{"rnfhermitebasis",2,(void*)rnfhnfbasis,6,"GG","rnfhermitebasis(bnf,order)=given an order as output by rnfpseudobasis, gives either a true HNF basis of the order if it exists, zero otherwise."},
-{"rnfisfree",20,(void*)rnfisfree,6,"lGG","rnfisfree(bnf,order)=given an order as output by rnfpseudobasis or rnfsteinitz, outputs true (1) or false (0) according to whether the order is free or not."},
-{"rnflllgram",3,(void*)rnflllgram,6,"GGG","rnflllgram(nf,pol,order)=given a pol with coefficients in nf and an order as output by rnfpseudobasis or similar, gives [[neworder],U], where neworder is a reduced order and U is the unimodular transformation matrix."},
-{"rnfpolred",2,(void*)rnfpolred,6,"GG","rnfpolred(nf,pol)=given a pol with coefficients in nf, finds a list of polynomials defining some subfields, hopefully simpler."},
-{"rnfpseudobasis",2,(void*)rnfpseudobasis,6,"GG","rnfpseudobasis(nf,pol)=given a pol with coefficients in nf, gives a 4-component vector [A,I,D,d] where [A,I] is a pseudo basis of the maximal order in HNF on the power basis, D is the relative ideal discriminant, and d is the relative discriminant in nf^*/nf*^2."},
-{"rnfsteinitz",2,(void*)rnfsteinitz,6,"GG","rnfsteinitz(nf,order)=given an order as output by rnfpseudobasis, gives [A,I,..] where (A,I) is a pseudo basis where all the ideals except perhaps the last are trivial."},
-{"rootmod",2,(void*)rootmod,7,"GG","rootmod(x,p)=roots mod p of the polynomial x."},
-{"rootmod2",2,(void*)rootmod2,7,"GG","rootmod2(x,p)=roots mod p of the polynomial x, when p is small."},
-{"rootpadic",32,(void*)rootpadic,7,"GGL","rootpadic(x,p,r)=p-adic roots of the polynomial x to precision r."},
-{"roots",1,(void*)roots,7,"Gp","roots(x)=roots of the polynomial x using Schonhage's method modified by Gourdon."},
-{"rootsof1",1,(void*)rootsof1,6,"G","rootsof1(nf)=number of roots of unity and primitive root of unity in the number field nf."},
-{"rootsold",0,(void*)suppressed,11,"G","rootsold(x)=THIS FUNCTION HAS BEEN SUPPRESSED."},
-{"round",1,(void*)ground,2,"G","round(x)=take the nearest integer to all the coefficients of x."},
-{"rounderror",10,(void*)rounderror,2,"lG","rounderror(x)=maximum error found in rounding x."},
-{"series",14,(void*)gtoser,2,"GnDP","series(x,v)=convert x (usually a vector) into a power series with variable v, starting with the constant coefficient."},
-{"set",1,(void*)gtoset,8,"G","set(x)=convert x into a set, i.e. a row vector with strictly increasing coefficients."},
-{"setintersect",2,(void*)setintersect,8,"GG","setintersect(x,y)=intersection of the sets x and y."},
-{"setminus",2,(void*)setminus,8,"GG","setminus(x,y)=set of elements of x not belonging to y."},
-{"setrand",11,(void*)setrand,2,"vG","setrand(n)=reset the seed of the random number generator to n."},
-{"setsearch",20,(void*)setsearch,8,"lGGD0,L,","setsearch(x,y)=looks if y belongs to the set x. Returns 0 if it is not, otherwise returns the index j such that y==x[j]."},
-{"setunion",2,(void*)setunion,8,"GG","setunion(x,y)=union of the sets x and y."},
-{"shift",21,(void*)gshift,1,"GL","shift(x,n)=shift x left n bits if n>=0, right -n bits if n<0."},
-{"shiftmul",21,(void*)gmul2n,1,"GL","shiftmul(x,n)=multiply x by 2^n (n>=0 or n<0)."},
-{"sigma",1,(void*)sumdiv,4,"G","sigma(x)=sum of the divisors of x."},
-{"sigmak",24,(void*)sigmak0,4,"LG","sigmak(k,x)=sum of the k-th powers of the divisors of x (k C-integer)."},
-{"sign",10,(void*)gsigne,1,"iG","sign(x)=sign of x, of type integer, real or fraction."},
-{"signat",1,(void*)qfsign,8,"G","signat(x)=signature of the symmetric matrix x."},
-{"signunit",1,(void*)signunits,6,"G","signunit(bnf)=matrix of signs of the real embeddings of the system of fundamental units found by buchinit."},
-{"simplefactmod",2,(void*)simplefactmod,4,"GG","simplefactmod(x,p)=same as factmod except that only the degrees of the irreducible factors are given."},
-{"simplify",1,(void*)simplify,2,"G","simplify(x)=simplify the object x as much as possible."},
-{"sin",1,(void*)gsin,3,"Gp","sin(x)=sine of x."},
-{"sinh",1,(void*)gsinh,3,"Gp","sinh(x)=hyperbolic sine of x."},
-{"size",10,(void*)sizedigit,2,"lG","size(x)=maximum number of decimal digits minus one of (the coefficients of) x."},
-{"smallbasis",13,(void*)nfbasis0,6,"GD1,L,DG","smallbasis(x)=integral basis of the field Q[a], where a is a root of the polynomial x where one assumes that no square of a prime>primelimit divides the discriminant of x."},
-{"smallbuchinit",93,(void*)smallbuchinit,6,BUCH_PROTO,"smallbuchinit(pol)=small buchinit, which can be converted to a big one using makebigbnf."},
-{"smalldiscf",1,(void*)nfdisc0,6,"GD1,L,DG","smalldiscf(x)=discriminant of the number field defined by the polynomial x where one assumes that no square of a prime>primelimit divides the discriminant of x."},
-{"smallfact",1,(void*)boundfact,4,"GD0,L,","smallfact(x)=partial factorization of the integer x (using only the stored primes)."},
-{"smallinitell",1,(void*)ellinit,5,"GDGp","smallinitell(x)=x being the vector [a1,a2,a3,a4,a6], gives the vector: [a1,a2,a3,a4,a6,b2,b4,b6,b8,c4,c6,delta,j]."},
-{"smallpolred",1,(void*)smallpolred,6,"G","smallpolred(x)=partial reduction of the polynomial x (gives minimal polynomials only)."},
-{"smallpolred2",1,(void*)smallpolred2,6,"G","smallpolred2(x)=partial reduction of the polynomial x (gives elements and minimal polynomials)."},
-{"smith",1,(void*)smith,8,"G","smith(x)=Smith normal form (i.e. elementary divisors) of the matrix x, expressed as a vector."},
-{"smith2",1,(void*)smithall,8,"G","smith2(x)=gives a three element vector [u,v,d] where u and v are square unimodular matrices such that d=u*x*v=diagonal(smith(x))."},
-{"smithclean",1,(void*)smithclean,8,"G","smithclean(z)=if z=[u,v,d] as output by smith2, removes from u,v,d the rows and columns corresponding to entries equal to 1 in d."},
-{"smithpol",1,(void*)gsmith,8,"G","smithpol(x)=Smith normal form (i.e. elementary divisors) of the matrix x with polynomial coefficients, expressed as a vector."},
-{"solve",37,(void*)zbrent0,9,"V=GGEp","solve(X=a,b,expr)=real root of expression expr (X between a and b), where expr(a)*expr(b)<=0."},
-{"sort",1,(void*)sort,8,"G","sort(x)=sort in ascending order of the vector x."},
-{"sqr",1,(void*)gsqr,3,"G","sqr(x)=square of x. NOT identical to x*x."},
-{"sqred",1,(void*)qfgaussred,8,"G","sqred(x)=square reduction of the (symmetric) matrix x ( returns a square matrix whose i-th diagonal term is the coefficient of the i-th square in which the coefficient of the i-th variable is 1)."},
-{"sqrt",1,(void*)gsqrt,3,"Gp","sqrt(x)=square root of x."},
-{"srgcd",2,(void*)RgX_gcd,7,"GG","srgcd(x,y)=polynomial gcd of x and y using the subresultant algorithm."},
-{"sturm",10,(void*)sturm0,7,"lG","sturm(x)=number of real roots of the polynomial x."},
-{"sturmpart",30,(void*)sturmpart,7,"lGGG","sturmpart(x,a,b)=number of real roots of the polynomial x in the interval (a,b]."},
-{"subcyclo",2,(void*)polsubcyclo,6,"LLDn","subcyclo(p,d)=finds an equation for the d-th degree subfield of Q(zeta_p), where p must be a prime power."},
-{"subell",3,(void*)ellsub,5,"GGGp","subell(e,z1,z2)=difference of the points z1 and z2 on elliptic curve e."},
-{"subst",26,(void*)gsubst,7,"GnG","subst(x,y,z)=in expression x, replace the variable y by the expression z."},
-{"sum",48,(void*)sum0,9,"GV=GGE","sum(x,X=a,b,expr)=x plus the sum (X goes from a to b) of expression expr."},
-{"sumalt",27,(void*)sumalt0,9,"V=GED0,L,p","sumalt(X=a,expr)=Villegas-Zagier's acceleration of alternating series expr, X starting at a."},
-{"sumalt2",27,(void*)sumalt0,9,"V=GED1,L,p","sumalt2(X=a,expr)=Cohen-Villegas-Zagier's acceleration of alternating series expr, X starting at a."},
-{"suminf",27,(void*)suminf0,9,"V=GEp","suminf(X=a,expr)=infinite sum (X goes from a to infinity) of real or complex expression expr."},
-{"sumpos",27,(void*)sumpos0,9,"V=GED0,L,p","sumpos(X=a,expr)=sum of positive series expr, the formal variable X starting at a."},
-{"sumpos2",27,(void*)sumpos0,9,"V=GED1,L,p","sumpos2(X=a,expr)=sum of positive series expr, the formal variable X starting at a, using Zagier's polynomials."},
-{"supplement",1,(void*)suppl,8,"G","supplement(x)=supplement the columns of the matrix x to an invertible matrix."},
-{"sylvestermatrix",2,(void*)sylvestermatrix,7,"GG","sylvestermatrix(x,y)=forms the sylvester matrix associated to the two polynomials x and y. Warning: the polynomial coefficients are in columns, not in rows."},
-{"tan",1,(void*)gtan,3,"Gp","tan(x)=tangent of x."},
-{"tanh",1,(void*)gtanh,3,"Gp","tanh(x)=hyperbolic tangent of x."},
-{"taniyama",1,(void*)elltaniyama,5,"GP","taniyama(e)=modular parametrization of elliptic curve e."},
-{"taylor",12,(void*)tayl,7,"GnP","taylor(x,y)=taylor expansion of x with respect to the main variable of y."},
-{"tchebi",11,(void*)polchebyshev,7,"LD1,L,Dn","tchebi(n)=Tchebitcheff polynomial of degree n (n C-integer)."},
-{"teich",1,(void*)teich,3,"Gp","teich(x)=teichmuller character of p-adic number x."},
-{"theta",2,(void*)theta,3,"GGp","theta(q,z)=Jacobi sine theta-function."},
-{"thetanullk",21,(void*)thetanullk,3,"GLp","thetanullk(q,k)=k'th derivative at z=0 of theta(q,z)."},
-{"threetotwo",0,(void*)suppressed,6,"GGGG","threetotwo(nf,a,b,c)=returns a 3-component vector [d,e,U] such that U is a unimodular 3x3 matrix with algebraic integer coefficients such that [a,b,c]*U=[0,d,e]."},
-{"threetotwo2",0,(void*)suppressed,6,"GGGG","threetotwo2(nf,a,b,c)=returns a 3-component vector [d,e,U] such that U is a unimodular 3x3 matrix with algebraic integer coefficients such that [a,b,c]*U=[0,d,e]."},
-{"torsell",1,(void*)elltors,5,"Gp","torsell(e)=torsion subgroup of elliptic curve e: order, structure, generators."},
-{"trace",1,(void*)gtrace,8,"G","trace(x)=trace of x."},
-{"trans",1,(void*)gtrans,8,"G","trans(x)=x~=transpose of x."},
-{"trunc",1,(void*)gtrunc,2,"G","trunc(x)=truncation of x;when x is a power series,take away the O(X^)."},
-{"tschirnhaus",1,(void*)tschirnhaus,6,"G","tschirnhaus(x)=random Tschirnhausen transformation of the polynomial x."},
-{"twototwo",0,(void*)suppressed,6,"GGG","twototwo(nf,a,b)=returns a 3-component vector [d,e,U] such that U is a unimodular 2x2 matrix with algebraic integer coefficients such that [a,b]*U=[d,e] and d,e are hopefully smaller."},
-{"unit",1,(void*)quadunit,4,"G","unit(x)=fundamental unit of the quadratic field of discriminant x where x must be positive."},
-{"until",0,(void*)untilpari,11,"vEI","until(a,seq): evaluate the expression sequence seq until a is nonzero."},
-{"valuation",20,(void*)gvaluation,2,"lGG","valuation(x,p)=valuation of x with respect to p."},
-{"vec",1,(void*)gtovec,2,"G","vec(x)=transforms the object x into a vector. Used mainly if x is a polynomial or a power series."},
-{"vecindexsort",2,(void*)indexsort,8,"G","vecindexsort(x): indirect sorting of the vector x."},
-{"veclexsort",2,(void*)lexsort,8,"G","veclexsort(x): sort the elements of the vector x in ascending lexicographic order."},
-{"vecmax",1,(void*)vecmax,2,"G","vecmax(x)=maximum of the elements of the vector/matrix x."},
-{"vecmin",1,(void*)vecmin,2,"G","vecmin(x)=minimum of the elements of the vector/matrix x."},
-{"vecsort",2,(void*)vecsort0,8,"GGD0,L,","vecsort(x,k)=sorts the vector of vector (or matrix) x according to the value of its k-th component."},
-{"vector",22,(void*)vecteur,9,"GVE","vector(n,X,expr)=row vector with n components of expression expr (X ranges from 1 to n)."},
-{"vvector",22,(void*)vvecteur,9,"GVE","vvector(n,X,expr)=column vector with n components of expression expr (X ranges from 1 to n)."},
-{"weipell",1,(void*)weipell,5,"GP","weipell(e)=formal expansion in x=z of Weierstrass P function."},
-{"wf",1,(void*)weberf,3,"Gp","weberf(x)=Weber's f function of x (j=(f^24-16)^3/f^24)."},
-{"wf2",1,(void*)weberf2,3,"Gp","weberf2(x)=Weber's f2 function of x (j=(f2^24+16)^3/f2^24)."},
-{"while",0,(void*)whilepari,11,"vEI","while(a,seq): while a is nonzero evaluate the expression sequence seq. Otherwise 0."},
-{"zell",2,(void*)zell,5,"GGp","zell(e,z)=In the complex case, lattice point corresponding to the point z on the elliptic curve e."},
-{"zeta",1,(void*)gzeta,3,"Gp","zeta(s)=Riemann zeta function at s."},
-{"zetak",2,(void*)gzetak,6,"GGp","zetak(nfz,s)=Dedekind zeta function of the number field nfz at s, where nfz is the vector computed by initzeta (NOT by nfinit)."},
-{"zideallog",3,(void*)ideallog,6,"GGG","zideallog(nf,x,bid)=if bid is a big ideal as given by zidealstarinit or zidealstarinitgen , gives the vector of exponents on the generators bid[2][3] (even if these generators have not been computed)."},
-{"zidealstar",2,(void*)idealstar0,6,"GGD0,L,","zidealstar(nf,I)=3-component vector v, giving the structure of (Z_K/I)^*. v[1] is  the order (i.e. phi(I)), v[2] is a vector of cyclic components, and v[3]  is a vector giving the corresponding generators."},
-{"zidealstarinit",2,(void*)idealstar0,6,"GGD1,L,","zidealstarinit(nf,I)=6-component vector [I,v,fa,f2,U,V] where v is as in zidealstar without the generators, fa is the prime ideal factorisation of I and f2, U and V are technical but essential to work in (Z_K/I)^*."},
-{"zidealstarinitgen",2,(void*)idealstar0,6,"GGD2,L,","zidealstarinitgen(nf,I)=6-component vector [I,v,fa,f2,U,V] where v is as in zidealstar fa is the prime ideal factorisation of I and f2, U and V are technical but essential to work in (Z_K/I)^*."},
-{"znstar",1,(void*)znstar,4,"G","znstar(n)=3-component vector v, giving the structure of (Z/nZ)^*. v[1] is  the order (i.e. phi(n)), v[2] is a vector of cyclic components, and v[3]  is a vector giving the corresponding generators."},
-
-{NULL,0,NULL,0,NULL,NULL} /* sentinel */
-};
diff --git a/src/language/compile.c b/src/language/compile.c
index 19cc6fb..874fc67 100644
--- a/src/language/compile.c
+++ b/src/language/compile.c
@@ -27,13 +27,11 @@ enum COflags {COsafelex=1, COsafedyn=2};
  **                                                                       **
  ***************************************************************************/
 
-static GEN
-strntoGENexp(const char *str, long len)
+static char *
+translate(const char **src, char *s)
 {
-  GEN z = cgetg(1+nchar2nlong(len-1), t_STR);
-  char *s=GSTR(z);
-  const char *t=str+1;
-  while (t<=str+len)
+  const char *t = *src;
+  while (*t)
   {
     while (*t == '\\')
     {
@@ -42,7 +40,7 @@ strntoGENexp(const char *str, long len)
         case 'e':  *s='\033'; break; /* escape */
         case 'n':  *s='\n'; break;
         case 't':  *s='\t'; break;
-        default:   *s=*t; if (!*t) compile_err("unfinished string",str);
+        default:   *s=*t; if (!*t) { *src=s; return NULL; }
       }
       t++; s++;
     }
@@ -53,7 +51,32 @@ strntoGENexp(const char *str, long len)
     }
     *s++ = *t++;
   }
-  *s = '\0';
+  *s=0; *src=t; return s;
+}
+
+static void
+matchQ(const char *s, char *entry)
+{
+  if (*s != '"')
+    pari_err(e_SYNTAX,"expected character: '\"' instead of",s,entry);
+}
+
+/*  Read a "string" from src. Format then copy it, starting at s. Return
+ *  pointer to char following the end of the input string */
+char *
+pari_translate_string(const char *src, char *s, char *entry)
+{
+  matchQ(src, entry); src++; s = translate(&src, s);
+  if (!s) pari_err(e_SYNTAX,"run-away string",src,entry);
+  matchQ(src, entry); return (char*)src+1;
+}
+
+static GEN
+strntoGENexp(const char *str, long len)
+{
+  GEN z = cgetg(1+nchar2nlong(len-1), t_STR);
+  const char *t = str+1;
+  if (!translate(&t, GSTR(z))) compile_err("run-away string",str);
   return z;
 }
 
@@ -499,15 +522,16 @@ get_ret_type(const char **p, long arity, Gtype *t, long *flag)
 {
   *flag = 0;
   if (**p == 'v') { (*p)++; *t=Gvoid; return OCcallvoid; }
-  else if (**p == 'i') { (*p)++; *t=Gsmall; return OCcallint; }
-  else if (**p == 'l') { (*p)++; *t=Gsmall; return OCcalllong; }
+  else if (**p == 'i') { (*p)++; *t=Gsmall;  return OCcallint; }
+  else if (**p == 'l') { (*p)++; *t=Gsmall;  return OCcalllong; }
+  else if (**p == 'u') { (*p)++; *t=Gusmall; return OCcalllong; }
   else if (**p == 'm') { (*p)++; *flag = FLnocopy; }
   *t=Ggen; return arity==2?OCcallgen2:OCcallgen;
 }
 
 /*supported types:
- * type: Gsmall, Ggen, Gvoid, Gvec, Gclosure
- * mode: Gsmall, Ggen, Gvar, Gvoid
+ * type: Gusmall, Gsmall, Ggen, Gvoid, Gvec, Gclosure
+ * mode: Gusmall, Gsmall, Ggen, Gvar, Gvoid
  */
 static void
 compilecast_loc(int type, int mode, const char *loc)
@@ -515,13 +539,21 @@ compilecast_loc(int type, int mode, const char *loc)
   if (type==mode) return;
   switch (mode)
   {
+  case Gusmall:
+    if (type==Ggen)        op_push_loc(OCitou,-1,loc);
+    else if (type==Gvoid)  op_push_loc(OCpushlong,0,loc);
+    else if (type!=Gsmall)
+      compile_err("this should be a small integer >=0",loc);
+    break;
   case Gsmall:
     if (type==Ggen)        op_push_loc(OCitos,-1,loc);
     else if (type==Gvoid)  op_push_loc(OCpushlong,0,loc);
-    else compile_err("this should be a small integer",loc);
+    else if (type!=Gusmall)
+      compile_err("this should be a small integer",loc);
     break;
   case Ggen:
     if (type==Gsmall)      op_push_loc(OCstoi,0,loc);
+    else if (type==Gusmall)op_push_loc(OCutoi,0,loc);
     else if (type==Gvoid)  op_push_loc(OCpushgnil,0,loc);
     break;
   case Gvoid:
@@ -540,13 +572,23 @@ static void
 compilecast(long n, int type, int mode) { compilecast_loc(type, mode, tree[n].str); }
 
 static entree *
+fetch_member_raw(const char *s, long len)
+{
+  pari_sp av = avma;
+  char *t = stack_malloc(len+2);
+  entree *ep;
+  t[0] = '_'; strncpy(t+1, s, len); t[++len] = 0; /* prepend '_' */
+  ep = fetch_entry_raw(t, len);
+  avma = av; return ep;
+}
+static entree *
 getfunc(long n)
 {
   long x=tree[n].x;
-  if (tree[x].x==CSTmember)
-    return do_alias(fetch_member(tree[x].str, tree[x].len));
+  if (tree[x].x==CSTmember) /* str-1 points to '.' */
+    return do_alias(fetch_member_raw(tree[x].str - 1, tree[x].len + 1));
   else
-    return do_alias(fetch_entry(tree[x].str, tree[x].len));
+    return do_alias(fetch_entry_raw(tree[x].str, tree[x].len));
 }
 
 static entree *
@@ -816,6 +858,8 @@ compilesmall(long n, long x, long mode)
     op_push(OCpushstoi, x, n);
   else
   {
+    if (mode==Gusmall && x < 0)
+      compile_err("this should be a small integer >=0",tree[n].str);
     op_push(OCpushlong, x, n);
     compilecast(n,Gsmall,mode);
   }
@@ -921,7 +965,7 @@ compilelambda(long n, long y, GEN vep, struct codepos *pos)
 }
 
 static void
-compilecall(long n, int mode)
+compilecall(long n, int mode, entree *ep)
 {
   pari_sp ltop=avma;
   long j;
@@ -929,14 +973,26 @@ compilecall(long n, int mode)
   long y=tree[n].y;
   GEN arg=listtogen(y,Flistarg);
   long nb=lg(arg)-1;
-  long lnc=first_safe_arg(arg, COsafelex);
+  long lnc=first_safe_arg(arg, COsafelex|COsafedyn);
+  long lnl=first_safe_arg(arg, COsafelex);
+  long fl = lnl==0? (lnc==0? FLnocopy: FLnocopylex): 0;
+  if (ep==NULL)
+    compilenode(x, Ggen, fl);
+  else
+  {
+    long vn=getmvar(ep);
+    if (vn)
+      op_push(OCpushlex,vn,n);
+    else
+      op_push(OCpushdyn,(long)ep,n);
+  }
   for (j=1;j<=nb;j++)
   {
     long x = tree[arg[j]].x, f = tree[arg[j]].f;
     if (f==Fseq)
       compile_err("unexpected ';'", tree[x].str+tree[x].len);
     else if (f!=Fnoarg)
-      compilenode(arg[j], Ggen,j>=lnc?FLnocopylex:0);
+      compilenode(arg[j], Ggen,j>=lnl?FLnocopylex:0);
     else
       op_push(OCpushlong,0,n);
   }
@@ -945,18 +1001,6 @@ compilecall(long n, int mode)
   avma=ltop;
 }
 
-static void
-compileuserfunc(entree *ep, long n, int mode)
-{
-  long vn=getmvar(ep);
-  if (tree[n].x<OPnboperator) compile_err("operator unknown",tree[n].str);
-  if (vn)
-    op_push(OCpushlex,vn,n);
-  else
-    op_push(OCpushdyn,(long)ep,n);
-  compilecall(n, mode);
-}
-
 static GEN
 compilefuncinline(long n, long c, long a, long flag, long isif, long lev, long *ev)
 {
@@ -1071,7 +1115,7 @@ compilemy(GEN arg, const char *str, int inl)
         GEN vars = listtogen(tree[x].x,Fmatrixelts);
         long nv = lg(vars)-1;
         compilenode(tree[a].y,Ggen,FLnocopy);
-        op_push(OCdup,nv-1,x);
+        if (nv > 1) op_push(OCdup,nv-1,x);
         for (j=1; j<=nv; j++)
         {
           long v = detag(vars[j]);
@@ -1124,7 +1168,7 @@ compilelocal(GEN arg)
         GEN vars = listtogen(tree[x].x,Fmatrixelts);
         long nv = lg(vars)-1;
         compilenode(tree[a].y,Ggen,FLnocopy);
-        op_push(OCdup,nv-1,x);
+        if (nv > 1) op_push(OCdup,nv-1,x);
         for (j=1; j<=nv; j++)
         {
           long v = detag(vars[j]);
@@ -1254,7 +1298,7 @@ compilefunc(entree *ep, long n, int mode, long flag)
     avma=ltop;
     return;
   }
-  else if (is_func_named(ep,"O") || (compatible==OLDALL && is_func_named(ep,"o")))
+  else if (is_func_named(ep,"O"))
   {
     if (nb!=1)
       compile_err("wrong number of arguments", tree[n].str+tree[n].len-1);
@@ -1318,10 +1362,11 @@ compilefunc(entree *ep, long n, int mode, long flag)
           break;
         case 'W':
           {
-            entree *ep = getlvalue(arg[j]);
+            long a = arg[j];
+            entree *ep = getlvalue(a);
             long vn = getmvar(ep);
-            if (vn) op_push(OCcowvarlex,vn,n);
-            else op_push(OCcowvardyn,(long)ep,n);
+            if (vn) op_push(OCcowvarlex, vn, a);
+            else op_push(OCcowvardyn, (long)ep, a);
             compilenode(arg[j++],Ggen,FLnocopy);
             break;
           }
@@ -1347,9 +1392,12 @@ compilefunc(entree *ep, long n, int mode, long flag)
             }
             break;
           }
-        case 'P': case 'L': /*Fall through*/
+        case 'P': case 'L':
           compilenode(arg[j++],Gsmall,0);
           break;
+        case 'U':
+          compilenode(arg[j++],Gusmall,0);
+          break;
         case 'n':
           compilenode(arg[j++],Gvar,0);
           break;
@@ -1375,9 +1423,9 @@ compilefunc(entree *ep, long n, int mode, long flag)
             }
             else
             {
-              compilenewptr(vn,ep,n);
+              compilenewptr(vn, ep, a);
               compilelvalue(a);
-              op_push(OCpushptr, 0,n);
+              op_push(OCpushptr, 0, a);
             }
             nbpointers++;
             break;
@@ -1507,6 +1555,9 @@ compilefunc(entree *ep, long n, int mode, long flag)
         case 'M':
           op_push(OCpushlong,strtol(q+1,NULL,10),n);
           break;
+        case 'U':
+          op_push(OCpushlong,(long)strtoul(q+1,NULL,10),n);
+          break;
         case 'r':
         case 's':
           str_defproto(p, q, tree[n].str);
@@ -1579,15 +1630,30 @@ compilefunc(entree *ep, long n, int mode, long flag)
   avma=ltop;
 }
 
+static void
+genclosurectx(const char *loc, long nbdata)
+{
+  long i;
+  GEN vep = cgetg(nbdata+1,t_VECSMALL);
+  for(i = 1; i <= nbdata; i++)
+  {
+    vep[i] = 0;
+    op_push_loc(OCpushlex,-i,loc);
+  }
+  frame_push(vep);
+}
+
 static GEN
 genclosure(entree *ep, const char *loc, long  nbdata, int check)
 {
+  pari_sp av = avma;
   struct codepos pos;
-  long i, nb=0;
+  long nb=0;
   const char *code=ep->code,*p,*q;
   char c;
+  GEN text;
   long index=ep->arity;
-  long arity=0, maskarg=0, maskarg0=0, stop=0;
+  long arity=0, maskarg=0, maskarg0=0, stop=0, dovararg=0;
   PPproto mod;
   Gtype ret_typ;
   long ret_flag;
@@ -1628,8 +1694,8 @@ genclosure(entree *ep, const char *loc, long  nbdata, int check)
   dbgstart = loc;
   if (nbdata > arity)
     pari_err(e_MISC,"too many parameters for closure `%s'", ep->name);
-  for(i=1; i<= nbdata; i++)
-    op_push_loc(OCpushgen,data_push(NULL),loc);
+  if (nbdata) genclosurectx(loc, nbdata);
+  text = strtoGENstr(ep->name);
   arity -= nbdata;
   if (maskarg)  op_push_loc(OCcheckargs,maskarg,loc);
   if (maskarg0) op_push_loc(OCcheckargs0,maskarg0,loc);
@@ -1675,6 +1741,9 @@ genclosure(entree *ep, const char *loc, long  nbdata, int check)
       case 'L':
         op_push_loc(OCitos,-index,loc);
         break;
+      case 'U':
+        op_push_loc(OCitou,-index,loc);
+        break;
       case 'n':
         op_push_loc(OCvarn,-index,loc);
         break;
@@ -1726,6 +1795,9 @@ genclosure(entree *ep, const char *loc, long  nbdata, int check)
         op_push_loc(OCpushlong,strtol(q+1,NULL,10),loc);
         op_push_loc(OCdefaultlong,-index,loc);
         break;
+      case 'U':
+        op_push_loc(OCpushlong,(long)strtoul(q+1,NULL,10),loc);
+        op_push_loc(OCdefaultulong,-index,loc);
       case 'r':
       case 's':
         str_defproto(p, q, loc);
@@ -1740,8 +1812,10 @@ genclosure(entree *ep, const char *loc, long  nbdata, int check)
     case PPstar:
       switch(c)
       {
-      case 'E':
       case 's':
+        dovararg = 1;
+        break;
+      case 'E':
         return NULL;
       default:
         pari_err(e_MISC,"Unknown prototype code `%c*' for `%s'",c,ep->name);
@@ -1756,7 +1830,8 @@ genclosure(entree *ep, const char *loc, long  nbdata, int check)
   op_push_loc(ret_op, (long) ep, loc);
   if (ret_flag==FLnocopy) op_push_loc(OCcopy,0,loc);
   compilecast_loc(ret_typ, Ggen, loc);
-  return getfunction(&pos,nb+arity,0,strtoGENstr(ep->name),0);
+  if (dovararg) nb|=VARARGBITS;
+  return gerepilecopy(av, getfunction(&pos,nb+arity,nbdata,text,0));
 }
 
 GEN
@@ -1766,7 +1841,7 @@ snm_closure(entree *ep, GEN data)
   long n = data ? lg(data)-1: 0;
   GEN C = genclosure(ep,ep->name,n,0);
   for(i=1; i<=n; i++)
-    gmael(C,4,i) = gel(data,i);
+    gmael(C,7,i) = gel(data,i);
   return C;
 }
 
@@ -1776,7 +1851,7 @@ strtoclosure(const char *s, long n,  ...)
   pari_sp av = avma;
   entree *ep = is_entry(s);
   GEN C;
-  if (!ep) pari_err(e_MISC,"no function named \"%s\"",s);
+  if (!ep) pari_err(e_NOTFUNC, strtoGENstr(s));
   ep = do_alias(ep);
   if ((!EpSTATIC(ep) && EpVALENCE(ep)!=EpINSTALL) || !ep->value)
     pari_err(e_MISC,"not a built-in/install'ed function: \"%s\"",s);
@@ -1788,7 +1863,7 @@ strtoclosure(const char *s, long n,  ...)
     long i;
     va_start(ap,n);
     for(i=1; i<=n; i++)
-      gmael(C,4,i) = va_arg(ap, GEN);
+      gmael(C,7,i) = va_arg(ap, GEN);
     va_end(ap);
   }
   return gerepilecopy(av, C);
@@ -1857,9 +1932,9 @@ compilenode(long n, int mode, long flag)
     if (tree[x].f==Fvec && tree[x].x>=0)
     {
       GEN vars = listtogen(tree[x].x,Fmatrixelts);
-      long i, l = lg(vars)-1;
+      long i, l = lg(vars)-1, d = mode==Gvoid? l-1: l;
       compilenode(y,Ggen,mode==Gvoid?FLnocopy:flag&FLsurvive);
-      op_push(OCdup,mode==Gvoid?l-1:l,x);
+      if (d) op_push(OCdup, d, x);
       for(i=1; i<=l; i++)
       {
         long a = detag(vars[i]);
@@ -1922,8 +1997,8 @@ compilenode(long n, int mode, long flag)
         op_push(OCpushgen,  data_push(strntoGENexp(tree[n].str,tree[n].len)),n);
         break;
       case CSTquote:
-        {
-          entree *ep = fetch_entry(tree[n].str+1,tree[n].len-1);
+        { /* skip ' */
+          entree *ep = fetch_entry_raw(tree[n].str+1,tree[n].len-1);
           if (EpSTATIC(ep)) compile_varerr(tree[n].str+1);
           op_push(OCpushvar, (long)ep,n);
           compilecast(n,Ggen, mode);
@@ -1973,21 +2048,24 @@ compilenode(long n, int mode, long flag)
     {
       entree *ep=getfunc(n);
       if (EpVALENCE(ep)==EpVAR || EpVALENCE(ep)==EpNEW)
-        compileuserfunc(ep,n,mode);
+      {
+        if (tree[n].x<OPnboperator) /* should not happen */
+          compile_err("operator unknown",tree[n].str);
+        compilecall(n,mode,ep);
+      }
       else
         compilefunc(ep,n,mode,flag);
       return;
     }
   case Fcall:
-    compilenode(x,Ggen,0);
-    compilecall(n,mode);
+    compilecall(n,mode,NULL);
     return;
   case Flambda:
     {
       pari_sp ltop=avma;
       struct codepos pos;
       GEN arg=listtogen(x,Flistarg);
-      long nb, lgarg, nbmvar, gap;
+      long nb, lgarg, nbmvar, dovararg=0, gap;
       long strict = GP_DATA->strictargs;
       GEN vep = cgetg_copy(arg, &lgarg);
       GEN text=cgetg(3,t_VEC);
@@ -2004,7 +2082,13 @@ compilenode(long n, int mode, long flag)
         for(i=1;i<=nb;i++)
         {
           long a=arg[i];
-          vep[i]=(long)getvar(tree[a].f==Fassign?tree[a].x:a);
+          if (i==nb && tree[a].f==Fvararg)
+          {
+            dovararg=1;
+            vep[i]=(long)getvar(tree[a].x);
+          }
+          else
+            vep[i]=(long)getvar(tree[a].f==Fassign?tree[a].x:a);
           var_push(NULL,Lmy);
         }
         checkdups(arg,vep);
@@ -2017,12 +2101,12 @@ compilenode(long n, int mode, long flag)
           if (tree[a].f==Fassign && (strict || !is_node_zero(y)))
           {
             if (tree[y].f==Fsmall)
-              compilenode(y,Ggen,a);
+              compilenode(y, Ggen, 0);
             else
             {
               struct codepos lpos;
               getcodepos(&lpos);
-              compilenode(y,Ggen,a);
+              compilenode(y, Ggen, 0);
               op_push(OCpushgen, data_push(getclosure(&lpos)),a);
             }
             op_push(OCdefaultarg,-nb+i-1,a);
@@ -2037,6 +2121,7 @@ compilenode(long n, int mode, long flag)
         compilenode(y,Ggen,FLsurvive|FLreturn);
       else
         compilecast(n,Gvoid,Ggen);
+      if (dovararg) nb|=VARARGBITS;
       op_push(OCpushgen, data_push(getfunction(&pos,nb,nbmvar,text,gap)),n);
       if (nbmvar) op_push(OCsaveframe,!!(flag&FLsurvive),n);
       compilecast(n, Gclosure, mode);
@@ -2072,7 +2157,9 @@ closure_deriv(GEN G)
   struct codepos pos;
   const char *code;
   GEN text;
-  long arity=G[1];
+  long arity=closure_arity(G);
+  if (arity==0 || closure_is_variadic(G))
+    pari_err_TYPE("derivfun",G);
   if (typ(gel(G,6))==t_STR)
   {
     code = GSTR(gel(G,6));
@@ -2198,6 +2285,7 @@ optimizefunc(entree *ep, long n)
         case 'n':
         case 'M':
         case 'L':
+        case 'U':
         case 'P':
           optimizenode(arg[j]);
           fl&=tree[arg[j++]].flags;
@@ -2366,6 +2454,9 @@ optimizenode(long n)
   case Frefarg:
     compile_err("unexpected character '&'",tree[n].str);
     return;
+  case Fvararg:
+    compile_err("unexpected characters '..'",tree[n].str);
+    return;
   case Ffunction:
     {
       entree *ep=getfunc(n);
diff --git a/src/language/default.c b/src/language/default.c
index 3b8f75b..bf7b337 100644
--- a/src/language/default.c
+++ b/src/language/default.c
@@ -13,21 +13,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 #include "pari.h"
 #include "paripriv.h"
 
-/* Simple-minded parsing utilities. These are forbidden to use the GP stack
- * which may not exist at this point [e.g upon GP initialization]  */
-
-#ifdef MAXPATHLEN
-#  define GET_SEP_SIZE MAXPATHLEN
-#else
-#  define GET_SEP_SIZE 128
+#ifdef _WIN32
+#  include "../systems/mingw/mingw.h"
 #endif
 
+
 /* Return all chars, up to next separator
  * [as strtok but must handle verbatim character string] */
 char*
 get_sep(const char *t)
 {
-  static char buf[GET_SEP_SIZE], *lim = buf + GET_SEP_SIZE;
+  char *buf = stack_malloc(strlen(t)+1);
   char *s = buf;
   int outer = 1;
 
@@ -43,11 +39,8 @@ get_sep(const char *t)
         if (outer) { s[-1] = 0; return buf; }
         break;
       case '\\': /* gobble next char */
-        if (s == lim) break;
         if (! (*s++ = *t++) ) return buf;
     }
-    if (s == lim)
-      pari_err(e_MISC,"get_sep: argument too long (< %ld chars)", GET_SEP_SIZE);
   }
 }
 
@@ -81,6 +74,9 @@ my_int(char *s)
       case 'k': case 'K': n = safe_mul(n,1000UL);       p++; break;
       case 'm': case 'M': n = safe_mul(n,1000000UL);    p++; break;
       case 'g': case 'G': n = safe_mul(n,1000000000UL); p++; break;
+#ifdef LONG_IS_64BIT
+      case 't': case 'T': n = safe_mul(n,1000000000000UL); p++; break;
+#endif
     }
     if (!n) pari_err(e_SYNTAX,"integer too large",s,s);
   }
@@ -91,24 +87,27 @@ my_int(char *s)
 long
 get_int(const char *s, long dflt)
 {
+  pari_sp av = avma;
   char *p = get_sep(s);
   long n;
   int minus = 0;
 
   if (*p == '-') { minus = 1; p++; }
-  if (!isdigit((int)*p)) return dflt;
+  if (!isdigit((int)*p)) { avma = av; return dflt; }
 
   n = (long)my_int(p);
   if (n < 0) pari_err(e_SYNTAX,"integer too large",s,s);
-  return minus? -n: n;
+  avma = av; return minus? -n: n;
 }
 
 ulong
 get_uint(const char *s)
 {
+  pari_sp av = avma;
   char *p = get_sep(s);
+  ulong u;
   if (*p == '-') pari_err(e_SYNTAX,"arguments must be positive integers",s,s);
-  return my_int(p);
+  u = my_int(p); avma = av; return u;
 }
 
 /********************************************************************/
@@ -206,11 +205,12 @@ sd_realprecision(const char *v, long flag)
   pariout_t *fmt = GP_DATA->fmt;
   if (v)
   {
-    ulong newnb = fmt->sigd, prec;
+    ulong newnb = fmt->sigd;
+    long prec;
     sd_ulong_init(v, "realprecision", &newnb, 1, prec2ndec(LGBITS));
     if (fmt->sigd == (long)newnb) return gnil;
     if (fmt->sigd >= 0) fmt->sigd = newnb;
-    prec = (ulong)ndec2prec(newnb);
+    prec = ndec2prec(newnb);
     if (prec == precreal) return gnil;
     precreal = prec;
   }
@@ -286,7 +286,7 @@ sd_colors(const char *v, long flag)
       v = "9, 13, 11, 15, 14, 10, 11";
     if (l <= 6 && strncmp(v, "boldfg", l) == 0)        /* Good for darkbg consoles */
       v = "[1,,1], [5,,1], [3,,1], [7,,1], [6,,1], , [2,,1]";
-    v0 = s = filtre(v, 0);
+    v0 = s = gp_filter(v);
     for (c=c_ERR; c < c_LAST; c++)
       gp_colors[c] = gp_get_color(&s);
     pari_free(v0);
@@ -358,16 +358,12 @@ sd_compatible(const char *v, long flag)
 {
   const char *msg[] = {
     "(no backward compatibility)",
-    "(warn when using obsolete functions)",
-    "(use old functions, don't ignore case)",
-    "(use old functions, ignore case)", NULL
+    "(no backward compatibility)",
+    "(no backward compatibility)",
+    "(no backward compatibility)", NULL
   };
-  ulong old = compatible;
-  GEN r = sd_ulong(v,flag,"compatible",&compatible, 0,3,msg);
-
-  if (old != compatible && flag != d_INITRC && gp_init_functions())
-    pari_warn(warner,"user functions re-initialized");
-  return r;
+  ulong junk = 0;
+  return sd_ulong(v,flag,"compatible",&junk, 0,3,msg);
 }
 
 GEN
@@ -522,20 +518,44 @@ sd_output(const char *v, long flag)
 }
 
 GEN
+sd_parisizemax(const char *v, long flag)
+{
+  ulong size = pari_mainstack->vsize, n = size;
+  GEN r = sd_ulong(v,flag,"parisizemax",&n, 0,LONG_MAX,NULL);
+  if (n != size) {
+    if (flag == d_INITRC)
+      paristack_alloc(pari_mainstack->rsize, n);
+    else
+      parivstack_resize(n);
+  }
+  return r;
+}
+
+GEN
 sd_parisize(const char *v, long flag)
 {
-  ulong size = top - bot, n = size;
+  ulong rsize = pari_mainstack->rsize, n = rsize;
   GEN r = sd_ulong(v,flag,"parisize",&n, 10000,LONG_MAX,NULL);
-  if (n != size) {
+  if (n != rsize) {
     if (flag == d_INITRC)
-      pari_init_stack(n, size);
+      paristack_alloc(n, pari_mainstack->vsize);
     else
-      allocatemem(n);
+      paristack_newrsize(n);
   }
   return r;
 }
 
 GEN
+sd_threadsizemax(const char *v, long flag)
+{
+  ulong size = GP_DATA->threadsizemax, n = size;
+  GEN r = sd_ulong(v,flag,"threadsizemax",&n, 0,LONG_MAX,NULL);
+  if (n != size)
+    GP_DATA->threadsizemax = n;
+  return r;
+}
+
+GEN
 sd_threadsize(const char *v, long flag)
 {
   ulong size = GP_DATA->threadsize, n = size;
@@ -696,15 +716,13 @@ compare_name(const void *s1, const void *s2) {
   entree *e1 = *(entree**)s1, *e2 = *(entree**)s2;
   return strcmp(e1->name, e2->name);
 }
-/* return all entries with class '16' */
 static void
 defaults_list(pari_stack *s)
 {
   entree *ep;
   long i;
   for (i = 0; i < functions_tblsz; i++)
-    for (ep = defaults_hash[i]; ep; ep = ep->next)
-      if (ep->menu == 16) pari_stack_pushp(s, ep);
+    for (ep = defaults_hash[i]; ep; ep = ep->next) pari_stack_pushp(s, ep);
 }
 /* ep associated to function f of arity 2. Call f(v,flag) */
 static GEN
@@ -726,7 +744,7 @@ setdefault(const char *s, const char *v, long flag)
     pari_stack_delete(&st);
     return gnil;
   }
-  ep = is_entry_intern(s, defaults_hash, NULL);
+  ep = pari_is_default(s);
   if (!ep)
   {
     pari_err(e_MISC,"unknown default: %s",s);
@@ -734,9 +752,6 @@ setdefault(const char *s, const char *v, long flag)
   }
   return call_f2(ep, v, flag);
 }
-int
-pari_is_default(const char *s)
-{ return !!is_entry_intern(s, defaults_hash, NULL); }
 
 GEN
 default0(const char *a, const char *b) { return setdefault(a,b, b? d_SILENT: d_RETURN); }
@@ -775,6 +790,44 @@ init_pp(gp_data *D)
   p->file = NULL;
 }
 
+static char *
+init_help(void)
+{
+  char *h = os_getenv("GPHELP");
+# ifdef GPHELP
+  if (!h) h = (char*)GPHELP;
+# endif
+#ifdef _WIN32
+  win32_set_pdf_viewer();
+#endif
+  if (h) h = pari_strdup(h);
+  return h;
+}
+
+static void
+init_graphs(gp_data *D)
+{
+  const char *cols[] = { "",
+    "white","black","blue","violetred","red","green","grey","gainsboro"
+  };
+  const long N = 8;
+  GEN c = cgetalloc(t_VECSMALL, 3), s;
+  long i;
+  c[1] = 4;
+  c[2] = 5;
+  D->graphcolors = c;
+  c = (GEN)pari_malloc((N+1 + 4*N)*sizeof(long));
+  c[0] = evaltyp(t_VEC)|evallg(N+1);
+  for (i = 1, s = c+N+1; i <= N; i++, s += 4)
+  {
+    GEN lp = s;
+    lp[0] = evaltyp(t_STR)|evallg(4);
+    strcpy(GSTR(lp), cols[i]);
+    gel(c,i) = lp;
+  }
+  D->colormap = c;
+}
+
 gp_data *
 default_gp_data(void)
 {
@@ -810,5 +863,12 @@ default_gp_data(void)
   init_path(D->path, pari_default_path());
   init_path(D->sopath, "");
   init_pp(D);
+  init_graphs(D);
+  D->prompt_comment = (char*)"comment> ";
+  D->prompt = pari_strdup("? ");
+  D->prompt_cont = pari_strdup("");
+  D->help = init_help();
+  D->readline_state = DO_ARGS_COMPLETE;
+  D->histfile = NULL;
   return D;
 }
diff --git a/src/language/default.h b/src/language/default.h
index 2472126..365fd2b 100644
--- a/src/language/default.h
+++ b/src/language/default.h
@@ -2,33 +2,49 @@
 /* See src/desc/gen_proto */
 /* Do not edit*/
 entree functions_default[]={
-{"TeXstyle",0,(void*)sd_TeXstyle,16,"",""},
-{"colors",0,(void*)sd_colors,16,"",""},
-{"compatible",0,(void*)sd_compatible,16,"",""},
-{"datadir",0,(void*)sd_datadir,16,"",""},
-{"debug",0,(void*)sd_debug,16,"",""},
-{"debugfiles",0,(void*)sd_debugfiles,16,"",""},
-{"debugmem",0,(void*)sd_debugmem,16,"",""},
-{"factor_add_primes",0,(void*)sd_factor_add_primes,16,"",""},
-{"factor_proven",0,(void*)sd_factor_proven,16,"",""},
-{"format",0,(void*)sd_format,16,"",""},
-{"histsize",0,(void*)sd_histsize,16,"",""},
-{"log",0,(void*)sd_log,16,"",""},
-{"logfile",0,(void*)sd_logfile,16,"",""},
-{"nbthreads",0,(void*)sd_nbthreads,16,"",""},
-{"new_galois_format",0,(void*)sd_new_galois_format,16,"",""},
-{"output",0,(void*)sd_output,16,"",""},
-{"parisize",0,(void*)sd_parisize,16,"",""},
-{"path",0,(void*)sd_path,16,"",""},
-{"prettyprinter",0,(void*)sd_prettyprinter,16,"",""},
-{"primelimit",0,(void*)sd_primelimit,16,"",""},
-{"realprecision",0,(void*)sd_realprecision,16,"",""},
-{"secure",0,(void*)sd_secure,16,"",""},
-{"seriesprecision",0,(void*)sd_seriesprecision,16,"",""},
-{"simplify",0,(void*)sd_simplify,16,"",""},
-{"sopath",0,(void*)sd_sopath,16,"",""},
-{"strictargs",0,(void*)sd_strictargs,16,"",""},
-{"strictmatch",0,(void*)sd_strictmatch,16,"",""},
-{"threadsize",0,(void*)sd_threadsize,16,"",""},
+{"TeXstyle",0,(void*)sd_TeXstyle,18,"",""},
+{"breakloop",0,(void*)sd_breakloop,18,"",""},
+{"colors",0,(void*)sd_colors,18,"",""},
+{"compatible",0,(void*)sd_compatible,18,"",""},
+{"datadir",0,(void*)sd_datadir,18,"",""},
+{"debug",0,(void*)sd_debug,18,"",""},
+{"debugfiles",0,(void*)sd_debugfiles,18,"",""},
+{"debugmem",0,(void*)sd_debugmem,18,"",""},
+{"echo",0,(void*)sd_echo,18,"",""},
+{"factor_add_primes",0,(void*)sd_factor_add_primes,18,"",""},
+{"factor_proven",0,(void*)sd_factor_proven,18,"",""},
+{"format",0,(void*)sd_format,18,"",""},
+{"graphcolormap",0,(void*)sd_graphcolormap,18,"",""},
+{"graphcolors",0,(void*)sd_graphcolors,18,"",""},
+{"help",0,(void*)sd_help,18,"",""},
+{"histfile",0,(void*)sd_histfile,18,"",""},
+{"histsize",0,(void*)sd_histsize,18,"",""},
+{"lines",0,(void*)sd_lines,18,"",""},
+{"linewrap",0,(void*)sd_linewrap,18,"",""},
+{"log",0,(void*)sd_log,18,"",""},
+{"logfile",0,(void*)sd_logfile,18,"",""},
+{"nbthreads",0,(void*)sd_nbthreads,18,"",""},
+{"new_galois_format",0,(void*)sd_new_galois_format,18,"",""},
+{"output",0,(void*)sd_output,18,"",""},
+{"parisize",0,(void*)sd_parisize,18,"",""},
+{"parisizemax",0,(void*)sd_parisizemax,18,"",""},
+{"path",0,(void*)sd_path,18,"",""},
+{"prettyprinter",0,(void*)sd_prettyprinter,18,"",""},
+{"primelimit",0,(void*)sd_primelimit,18,"",""},
+{"prompt",0,(void*)sd_prompt,18,"",""},
+{"prompt_cont",0,(void*)sd_prompt_cont,18,"",""},
+{"psfile",0,(void*)sd_psfile,18,"",""},
+{"readline",0,(void*)sd_readline,18,"",""},
+{"realprecision",0,(void*)sd_realprecision,18,"",""},
+{"recover",0,(void*)sd_recover,18,"",""},
+{"secure",0,(void*)sd_secure,18,"",""},
+{"seriesprecision",0,(void*)sd_seriesprecision,18,"",""},
+{"simplify",0,(void*)sd_simplify,18,"",""},
+{"sopath",0,(void*)sd_sopath,18,"",""},
+{"strictargs",0,(void*)sd_strictargs,18,"",""},
+{"strictmatch",0,(void*)sd_strictmatch,18,"",""},
+{"threadsize",0,(void*)sd_threadsize,18,"",""},
+{"threadsizemax",0,(void*)sd_threadsizemax,18,"",""},
+{"timer",0,(void*)sd_timer,18,"",""},
 {NULL,0,NULL,0,NULL,NULL} /* sentinel */
 };
diff --git a/src/language/es.c b/src/language/es.c
index 0c11602..5482bb1 100644
--- a/src/language/es.c
+++ b/src/language/es.c
@@ -63,11 +63,19 @@ pari_ask_confirm(const char *s)
 #define MULTI_LINE_COMMENT 1
 #define LBRACE '{'
 #define RBRACE '}'
+
+static int
+in_help(filtre_t *F)
+{
+  char c;
+  if (!F->buf) return (*F->s == '?');
+  c = *F->buf->buf;
+  return c? (c == '?'): (*F->s == '?');
+}
 /* Filter F->s into F->t */
 static char *
 filtre0(filtre_t *F)
 {
-  const int downcase = F->downcase;
   const char *s = F->s;
   char *t;
   char c;
@@ -76,7 +84,6 @@ filtre0(filtre_t *F)
   t = F->t;
 
   if (F->more_input == 1) F->more_input = 0;
-
   while ((c = *s++))
   {
     if (F->in_string)
@@ -117,8 +124,7 @@ filtre0(filtre_t *F)
     /* weed out comments and spaces */
     if (c=='\\' && *s=='\\') { F->in_comment = ONE_LINE_COMMENT; continue; }
     if (isspace((int)c)) continue;
-    *t++ = downcase? tolower((int)c): c;
-
+    *t++ = c;
     switch(c)
     {
       case '/':
@@ -127,14 +133,14 @@ filtre0(filtre_t *F)
 
       case '\\':
         if (!*s) {
-          if (*F->buf->buf == '?') break; /* '?...\' */
+          if (in_help(F)) break; /* '?...\' */
           t--;
           if (!F->more_input) F->more_input = 1;
           goto END;
         }
         if (*s == '\r') s++; /* DOS */
         if (*s == '\n') {
-          if (*F->buf->buf == '?') break; /* '?...\' */
+          if (in_help(F)) break; /* '?...\' */
           t--; s++;
           if (!*s)
           {
@@ -165,8 +171,7 @@ filtre0(filtre_t *F)
   if (t != F->t) /* non empty input */
   {
     c = t[-1]; /* last char */
-    if (c == '=')
-    { if (*F->buf->buf != '?') F->more_input = 2; }
+    if (c == '=') { if (!in_help(F)) F->more_input = 2; }
     else if (! F->wait_for_brace) F->more_input = 0;
     else if (c == RBRACE)       { F->more_input = 0; t--; F->wait_for_brace--;}
   }
@@ -178,12 +183,12 @@ END:
 #undef MULTI_LINE_COMMENT
 
 char *
-filtre(const char *s, int downcase)
+gp_filter(const char *s)
 {
   filtre_t T;
+  T.buf = NULL;
   T.s = s;    T.in_string = 0; T.more_input = 0;
   T.t = NULL; T.in_comment= 0; T.wait_for_brace = 0;
-  T.downcase = downcase;
   return filtre0(&T);
 }
 
@@ -193,7 +198,6 @@ init_filtre(filtre_t *F, Buffer *buf)
   F->buf = buf;
   F->in_string  = 0;
   F->in_comment = 0;
-  F->downcase = 0;
 }
 
 /********************************************************************/
@@ -249,14 +253,16 @@ gp_read_stream(FILE *fi)
 }
 
 GEN
-gp_read_file(char *s)
+gp_read_file(const char *s)
 {
   GEN x = gnil;
   FILE *f = switchin(s);
-  if (file_is_binary(f)) {
-    int junk;
-    x = readbin(s,f, &junk);
-  } else {
+  if (file_is_binary(f))
+  {
+    x = readbin(s,f, NULL);
+    if (!x) pari_err_FILE("input file",s);
+  }
+  else {
     Buffer *b = new_buffer();
     x = gnil;
     for (;;) {
@@ -300,6 +306,7 @@ gp_readvec_file(char *s)
   if (file_is_binary(f)) {
     int junk;
     x = readbin(s,f,&junk);
+    if (!x) pari_err_FILE("input file",s);
   } else
     x = gp_readvec_stream(f);
   popinfile(); return x;
@@ -352,7 +359,20 @@ input_loop(filtre_t *F, input_method *IM)
   char *to_read, *s = b->buf;
 
   /* read first line */
-  if (! (to_read = IM->getline(&s,1, IM, F)) ) { check_filtre(F); return 0; }
+  if (! (to_read = IM->getline(&s,1, IM, F)) )
+  {
+    if (F->in_string)
+    {
+      pari_warn(warner,"run-away string. Closing it");
+      F->in_string = 0;
+    }
+    if (F->in_comment)
+    {
+      pari_warn(warner,"run-away comment. Closing it");
+      F->in_comment = 0;
+    }
+    return 0;
+  }
 
   /* buffer is not empty, init filter */
   F->in_string = 0;
@@ -1375,6 +1395,7 @@ out_term_color(PariOUT *out, long c)
 void
 term_color(long c) { out_term_color(pariOut, c); }
 
+/* s must be able to store 12 chars (including final \0) */
 char *
 term_get_color(char *s, long n)
 {
@@ -1435,7 +1456,6 @@ strlen_real(const char *s)
 static int
 term_width_intern(void)
 {
-  if (GP_DATA->flags & gpd_TEST) return 0;
 #ifdef _WIN32
   return win32_terminal_width();
 #endif
@@ -1462,7 +1482,6 @@ term_width_intern(void)
 static int
 term_height_intern(void)
 {
-  if (GP_DATA->flags & gpd_TEST) return 0;
 #ifdef _WIN32
   return win32_terminal_height();
 #endif
@@ -1972,6 +1991,7 @@ type_name(long t)
     case t_VECSMALL:s="t_VECSMALL";break;
     case t_CLOSURE: s="t_CLOSURE"; break;
     case t_ERROR:   s="t_ERROR";   break;
+    case t_INFINITY:s="t_INFINITY";break;
     default: pari_err(e_MISC,"unknown type %ld",t);
       s = NULL; /* not reached */
   }
@@ -2035,14 +2055,15 @@ dbg(GEN x, long nb, long bl)
     pari_printf("(%c,varn=%ld):", vsigne(x), varn(x));
   else if (tx == t_SER)
     pari_printf("(%c,varn=%ld,prec=%ld,valp=%ld):",
-               vsigne(x), varn(x), lgpol(x), valp(x));
+               vsigne(x), varn(x), lg(x)-2, valp(x));
   else if (tx == t_LIST)
   {
     pari_printf("(lmax=%ld):", list_nmax(x));
     x = list_data(x); lx = x? lg(x): 1;
     tx = t_VEC; /* print list_data as vec */
   } else if (tx == t_CLOSURE)
-    pari_printf("(arity=%ld):", closure_arity(x));
+    pari_printf("(arity=%ld%s):", closure_arity(x),
+                                  closure_is_variadic(x)?"+":"");
   for (i=1; i<lx; i++) dbg_word(x[i]);
   bl+=2; pari_putc('\n');
   switch(tx)
@@ -2114,6 +2135,11 @@ dbg(GEN x, long nb, long bl)
       }
       break;
 
+    case t_INFINITY:
+      blancs(bl); pari_printf("1st component = ");
+      dbg(gel(x,1),nb,bl);
+      break;
+
     case t_MAT:
     {
       GEN c = gel(x,1);
@@ -2144,11 +2170,12 @@ void
 dbgGEN(GEN x, long nb) { dbg(x,nb,0); }
 
 static void
-print_entree(entree *ep, long hash)
+print_entree(entree *ep)
 {
   pari_printf(" %s ",ep->name); dbg_addr((ulong)ep);
-  pari_printf(":\n   hash = %3ld, menu = %2ld, code = %-10s",
-            hash, ep->menu, ep->code? ep->code: "NULL");
+  pari_printf(": hash = %ld [%ld]\n", ep->hash % functions_tblsz, ep->hash);
+  pari_printf("   menu = %2ld, code = %-10s",
+              ep->menu, ep->code? ep->code: "NULL");
   if (ep->next)
   {
     pari_printf("next = %s ",(ep->next)->name);
@@ -2183,16 +2210,15 @@ print_functions_hash(const char *s)
     for(; n<=m; n++)
     {
       pari_printf("*** hashcode = %lu\n",n);
-      for (ep=functions_hash[n]; ep; ep=ep->next)
-        print_entree(ep,n);
+      for (ep=functions_hash[n]; ep; ep=ep->next) print_entree(ep);
     }
     return;
   }
   if (is_keyword_char((int)*s))
   {
-    ep = is_entry_intern(s,functions_hash,&n);
+    ep = is_entry(s);
     if (!ep) pari_err(e_MISC,"no such function");
-    print_entree(ep,n); return;
+    print_entree(ep); return;
   }
   if (*s=='-')
   {
@@ -2209,11 +2235,7 @@ print_functions_hash(const char *s)
   for (n=0; n<functions_tblsz; n++)
   {
     long cnt = 0;
-    for (ep=functions_hash[n]; ep; ep=ep->next)
-    {
-      print_entree(ep,n);
-      cnt++;
-    }
+    for (ep=functions_hash[n]; ep; ep=ep->next) { print_entree(ep); cnt++; }
     Total += cnt;
     if (cnt > Max) Max = cnt;
   }
@@ -2229,10 +2251,8 @@ static const char *
 get_var(long v, char *buf)
 {
   entree *ep = varentries[v];
-
   if (ep) return (char*)ep->name;
-  if (v==MAXVARN) return "#";
-  sprintf(buf,"#<%d>",(int)v); return buf;
+  sprintf(buf,"t%d",(int)v); return buf;
 }
 
 static void
@@ -2299,9 +2319,10 @@ dbg_pari_heap(void)
   long nu, l, u, s;
   pari_sp av = avma;
   GEN adr = getheap();
+  pari_sp top = pari_mainstack->top, bot = pari_mainstack->bot;
 
   nu = (top-avma)/sizeof(long);
-  l = (top-bot)/sizeof(long);
+  l = pari_mainstack->size/sizeof(long);
   pari_printf("\n Top : %lx   Bottom : %lx   Current stack : %lx\n",
               top, bot, avma);
   pari_printf(" Used :                         %ld  long words  (%ld K)\n",
@@ -2318,8 +2339,6 @@ dbg_pari_heap(void)
   avma = av;
 }
 
-#define isnull_for_pol(g)  ((typ(g)==t_INTMOD)? !signe(gel(g,2)): isnull(g))
-
 /* is to be printed as '0' */
 static long
 isnull(GEN g)
@@ -2337,8 +2356,6 @@ isnull(GEN g)
       return isnull(gel(g,2)) && isnull(gel(g,3));
     case t_FRAC: case t_RFRAC:
       return isnull(gel(g,1));
-    case t_POLMOD:
-      return isnull(gel(g,2));
     case t_POL:
       for (i=lg(g)-1; i>1; i--)
         if (!isnull(gel(g,i))) return 0;
@@ -2346,6 +2363,17 @@ isnull(GEN g)
   }
   return 0;
 }
+/* 0 coeff to be omitted in t_POL ? */
+static int
+isnull_for_pol(GEN g)
+{
+  switch(typ(g))
+  {
+    case t_INTMOD: return !signe(gel(g,2));
+    case t_POLMOD: return isnull(gel(g,2));
+    default:       return isnull(g);
+  }
+}
 
 /* return 1 or -1 if g is 1 or -1, 0 otherwise*/
 static long
@@ -2508,11 +2536,7 @@ texparen(pariout_t *T, outString *S, GEN a)
 static void
 times_texnome(outString *S, const char *v, long d)
 {
-  if (d)
-  {
-    if (GP_DATA->flags & gpd_TEXMACS) str_puts(S, "\\*"); else str_putc(S, ' ');
-    texnome(S,v,d);
-  }
+  if (d) { str_puts(S, "\\*"); texnome(S,v,d); }
 }
 static void
 times_monome(outString *S, const char *v, long d)
@@ -2621,12 +2645,35 @@ print_0_or_pm1(GEN g, outString *S, int addsign)
   }
   return 0;
 }
+
+static void
+print_precontext(GEN g, outString *S, long tex)
+{
+  if (lg(g)<8 || lg(gel(g,7))==1) return;
+  else
+  {
+    long i, n  = closure_arity(g);
+    str_puts(S,"(");
+    for(i=1; i<=n; i++)
+    {
+      str_puts(S,"v");
+      if (tex) str_puts(S,"_{");
+      str_ulong(S,i);
+      if (tex) str_puts(S,"}");
+      if (i < n) str_puts(S,",");
+    }
+    str_puts(S,")->");
+  }
+}
+
 static void
 print_context(GEN g, pariout_t *T, outString *S, long tex)
 {
-  if (lg(g)>=8 && lg(gel(g,7))>1 && lg(gmael(g,5,3))>=2)
+  GEN str = closure_get_text(g);
+  if (lg(g)<8 || lg(gel(g,7))==1) return;
+  if (typ(str)==t_VEC && lg(gel(closure_get_dbg(g),3)) >= 2)
   {
-    GEN v = gel(g,7), d = gmael3(g,5,3,1);
+    GEN v = closure_get_frame(g), d = gmael(closure_get_dbg(g),3,1);
     long i, l = lg(v), n=0;
     for(i=1; i<l; i++)
       if (gel(d,i))
@@ -2645,6 +2692,27 @@ print_context(GEN g, pariout_t *T, outString *S, long tex)
       }
     str_puts(S,");");
   }
+  else
+  {
+    GEN v = closure_get_frame(g);
+    long i, l = lg(v), n  = closure_arity(g);
+    str_puts(S,"(");
+    for(i=1; i<=n; i++)
+    {
+      str_puts(S,"v");
+      if (tex) str_puts(S,"_{");
+      str_ulong(S,i);
+      if (tex) str_puts(S,"}");
+      str_puts(S,",");
+    }
+    for(i=1; i<l; i++)
+    {
+      if (tex) texi(gel(v,i),T,S); else bruti(gel(v,i),T,S);
+      if (i<l-1)
+        str_putc(S,',');
+    }
+    str_puts(S,")");
+  }
 }
 
 static void
@@ -2671,7 +2739,7 @@ bruti_intern(GEN g, pariout_t *T, outString *S, int addsign)
     }
 
     case t_INTMOD: case t_POLMOD:
-      str_puts(S, new_fun_set? "Mod(": "mod(");
+      str_puts(S, "Mod(");
       bruti(gel(g,2),T,S); comma_sp(T,S);
       bruti(gel(g,1),T,S); str_putc(S, ')'); break;
 
@@ -2713,7 +2781,7 @@ bruti_intern(GEN g, pariout_t *T, outString *S, int addsign)
 
     case t_SER: v = get_var(varn(g), buf);
       i = valp(g);
-      l = lgpol(g);
+      l = lg(g)-2;
       if (l)
       {
         /* See normalize(): Mod(0,2)*x^i*(1+O(x)), has valp = i+1 */
@@ -2760,7 +2828,7 @@ bruti_intern(GEN g, pariout_t *T, outString *S, int addsign)
     }
 
     case t_QFR: case t_QFI: r = (tg == t_QFR);
-      if (new_fun_set) str_puts(S, "Qfb("); else str_puts(S, r? "qfr(": "qfi(");
+      str_puts(S, "Qfb(");
       bruti(gel(g,1),T,S); comma_sp(T,S);
       bruti(gel(g,2),T,S); comma_sp(T,S);
       bruti(gel(g,3),T,S);
@@ -2803,7 +2871,11 @@ bruti_intern(GEN g, pariout_t *T, outString *S, int addsign)
       {
         GEN str = closure_get_text(g);
         if (typ(str)==t_STR)
+        {
+          print_precontext(g, S, 0);
           str_puts(S, GSTR(str));
+          print_context(g, T, S, 0);
+        }
         else
         {
           str_putc(S,'(');   str_puts(S,GSTR(gel(str,1)));
@@ -2821,6 +2893,8 @@ bruti_intern(GEN g, pariout_t *T, outString *S, int addsign)
         str_putc(S,'}');
       }
       break;
+    case t_INFINITY: str_puts(S, inf_get_sign(g) == 1? "+oo": "-oo");
+      break;
 
     case t_MAT:
     {
@@ -2832,16 +2906,13 @@ bruti_intern(GEN g, pariout_t *T, outString *S, int addsign)
       {
         str_puts(S, "matrix(0,");
         str_long(S, r-1);
-        if (new_fun_set)
-          str_putc(S, ')');
-        else
-          str_puts(S, ",j,k,0)");
+        str_putc(S, ')');
         return;
       }
       print = (typ(gel(g,1)) == t_VECSMALL)? prints: bruti;
       if (l==2)
       {
-        str_puts(S, new_fun_set? "Mat(": "mat(");
+        str_puts(S, "Mat(");
         if (r == 2) { print(gcoeff(g,1,1),T,S); str_putc(S, ')'); return; }
       }
       str_putc(S, '[');
@@ -2995,9 +3066,9 @@ texi_sign(GEN g, pariout_t *T, outString *S, int addsign)
 
     case t_SER: v = get_texvar(varn(g), buf, sizeof(buf));
       i = valp(g);
-      if (lgpol(g))
+      if (lg(g)-2)
       { /* hack: we want g[i] = coeff of degree i. */
-        l = i + lgpol(g); g -= i-2;
+        l = i + lg(g)-2; g -= i-2;
         wr_lead_texnome(T,S,gel(g,i),v,i,addsign);
         while (++i < l)
         {
@@ -3077,7 +3148,11 @@ texi_sign(GEN g, pariout_t *T, outString *S, int addsign)
       {
         GEN str = closure_get_text(g);
         if (typ(str)==t_STR)
+        {
+          print_precontext(g, S, 1);
           str_puts(S, GSTR(str));
+          print_context(g, T, S ,1);
+        }
         else
         {
           str_putc(S,'(');          str_puts(S,GSTR(gel(str,1)));
@@ -3093,6 +3168,8 @@ texi_sign(GEN g, pariout_t *T, outString *S, int addsign)
         str_putc(S,',');   texi(gel(g,5),T,S); str_puts(S,"\\}");
       }
       break;
+    case t_INFINITY: str_puts(S, inf_get_sign(g) == 1? "+\\infty": "-\\infty");
+      break;
 
     case t_MAT:
     {
@@ -3331,21 +3408,6 @@ pari_unlink(const char *s)
     err_printf("I/O: removed file %s\n", s);
 }
 
-void
-check_filtre(filtre_t *T)
-{
-  if (T && T->in_string)
-  {
-    pari_warn(warner,"run-away string. Closing it");
-    T->in_string = 0;
-  }
-  if (T && T->in_comment)
-  {
-    pari_warn(warner,"run-away comment. Closing it");
-    T->in_comment = 0;
-  }
-}
-
 /* Remove one INFILE from the stack. Reset pari_infile (to the most recent
  * infile)
  * Return -1, if we're trying to pop out stdin itself; 0 otherwise
@@ -3992,7 +4054,8 @@ switchin(const char *name)
     forpath_t T;
     forpath_init(&T, GP_DATA->path, s);
     while ( (t = forpath_next(&T)) )
-      if ((f = try_name(t))) return f;
+      if ((f = try_name(t))) { pari_free(s); return f; }
+    pari_free(s);
   }
   pari_err_FILE("input file",name);
   return NULL; /*not reached*/
@@ -4034,6 +4097,81 @@ switchout(const char *name)
 
 /*******************************************************************/
 /**                                                               **/
+/**                SYSTEM, READSTR/EXTERNSTR/EXTERN               **/
+/**                                                               **/
+/*******************************************************************/
+static void
+check_secure(const char *s)
+{
+  if (GP_DATA->secure)
+    pari_err(e_MISC, "[secure mode]: system commands not allowed\nTried to run '%s'",s);
+}
+
+void
+gpsystem(const char *s)
+{
+#ifdef HAS_SYSTEM
+  check_secure(s);
+  if (system(s) < 0)
+    pari_err(e_MISC, "system(\"%s\") failed", s);
+#else
+  pari_err(e_ARCH,"system");
+#endif
+}
+
+static GEN
+get_lines(FILE *F)
+{
+  pari_sp av = avma;
+  long i, nz = 16;
+  GEN z = cgetg(nz + 1, t_VEC);
+  Buffer *b = new_buffer();
+  input_method IM;
+  IM.fgets = &fgets;
+  IM.file = F;
+  for(i = 1;;)
+  {
+    char *s = b->buf, *e;
+    if (!file_getline(b, &s, &IM)) break;
+    if (i > nz) { nz <<= 1; z = vec_lengthen(z, nz); }
+    e = s + strlen(s)-1;
+    if (*e == '\n') *e = 0;
+    gel(z,i++) = strtoGENstr(s);
+  }
+  delete_buffer(b); setlg(z, i);
+  return gerepilecopy(av, z);
+}
+
+GEN
+externstr(const char *s)
+{
+  pariFILE *F;
+  GEN z;
+  check_secure(s);
+  F = try_pipe(s, mf_IN);
+  z = get_lines(F->file);
+  pari_fclose(F); return z;
+}
+GEN
+gpextern(const char *s)
+{
+  pariFILE *F;
+  GEN z;
+  check_secure(s);
+  F = try_pipe(s, mf_IN);
+  z = gp_read_stream(F->file);
+  pari_fclose(F); return z;
+}
+
+GEN
+readstr(const char *s)
+{
+  GEN z = get_lines(switchin(s));
+  popinfile(); return z;
+}
+
+/*******************************************************************/
+/**                                                               **/
 /**                    I/O IN BINARY FORM                         **/
 /**                                                               **/
 /*******************************************************************/
@@ -4153,11 +4291,11 @@ readobj(FILE *f, int *ptc, hashtable *H)
         x = rdGEN(f);
         if (H) gen_relink(x, H);
         err_printf("setting %s\n",s);
-        changevalue(fetch_named_var(s), x);
+        changevalue(varentries[fetch_user_var(s)], x);
       }
       else
       {
-        pari_var_create(fetch_entry(s, strlen(s)));
+        pari_var_create(fetch_entry(s));
         x = gnil;
       }
       break;
@@ -4546,41 +4684,31 @@ void gpwritebin(const char *s, GEN x) { char *t=wr_check(s); writebin(t, x); par
  *   p > 0, called from %p or %#p
  *   p <= 0, called from %` or %#` (|p| backquotes, possibly 0) */
 static gp_hist_cell *
-history(gp_hist *H, long p, char *old, char *entry)
+history(long p)
 {
+  gp_hist *H = GP_DATA->hist;
   ulong t = H->total, s = H->size;
   gp_hist_cell *c;
 
-  if (!t)
-    pari_err(old?e_SYNTAX:e_MISC,"The result history is empty", old, entry);
+  if (!t) pari_err(e_MISC,"The result history is empty");
 
   if (p <= 0) p += t; /* count |p| entries starting from last */
   if (p <= 0 || p <= (long)(t - s) || (ulong)p > t)
   {
-    char *str = stack_malloc(128);
     long pmin = (long)(t - s) + 1;
     if (pmin <= 0) pmin = 1;
-    sprintf(str, "History result %%%ld not available [%%%ld-%%%lu]", p,pmin,t);
-    pari_err(e_SYNTAX, str, old, entry);
+    pari_err(e_MISC,"History result %%%ld not available [%%%ld-%%%lu]",
+             p,pmin,t);
   }
   c = H->v + ((p-1) % s);
   if (!c->z)
-  {
-    char *str = stack_malloc(128);
-    sprintf(str, "History result %%%ld has been deleted (histsize changed)", p);
-    pari_err(e_SYNTAX, str, old, entry);
-  }
+    pari_err(e_MISC,"History result %%%ld has been deleted (histsize changed)", p);
   return c;
 }
 GEN
-gp_history(gp_hist *H, long p, char *old, char *entry)
-{ return history(H,p,old,entry)->z; }
-GEN
-pari_get_hist(long p)
-{ return history(GP_DATA->hist, p, NULL,NULL)->z; }
+pari_get_hist(long p) { return history(p)->z; }
 long
-pari_get_histtime(long p)
-{ return history(GP_DATA->hist, p, NULL,NULL)->t; }
+pari_get_histtime(long p) { return history(p)->t; }
 
 void
 pari_add_hist(GEN x, long time)
@@ -4823,9 +4951,10 @@ gp_dlopen(const char *name, int flag)
     forpath_init(&T, GP_DATA->sopath, s);
     while ( (t = forpath_next(&T)) )
     {
-      if ( (handle = try_dlopen(t,flag)) ) return handle;
+      if ( (handle = try_dlopen(t,flag)) ) { pari_free(s); return handle; }
       (void)dlerror(); /* clear error message */
     }
+    pari_free(s);
   }
   return NULL;
 }
@@ -4871,7 +5000,8 @@ gp_LoadLibrary(const char *name)
     char *t;
     forpath_init(&T, GP_DATA->sopath, s);
     while ( (t = forpath_next(&T)) )
-      if ( (handle = try_LoadLibrary(t)) ) return handle;
+      if ( (handle = try_LoadLibrary(t)) ) { pari_free(s); return handle; }
+    pari_free(s);
   }
   return NULL;
 }
diff --git a/src/language/eval.c b/src/language/eval.c
index 426c4d5..94d2481 100644
--- a/src/language/eval.c
+++ b/src/language/eval.c
@@ -213,21 +213,38 @@ copyvalue(entree *ep)
 INLINE void
 err_var(GEN x) { pari_err_TYPE("evaluator [variable name expected]", x); }
 
+enum chk_VALUE { chk_ERROR, chk_NOCREATE, chk_CREATE };
+
 INLINE void
-checkvalue(entree *ep)
+checkvalue(entree *ep, enum chk_VALUE flag)
 {
   if (MT_IS_THREAD)
     pari_err(e_MISC,"mt: global variable not supported: %s",ep->name);
   if (ep->valence==EpNEW)
-  {
-    pari_var_create(ep);
-    ep->valence = EpVAR;
-    ep->value = initial_value(ep);
-  }
+    switch(flag)
+    {
+      case chk_ERROR:
+        /* Do nothing until we can report a meaningful error message
+           The extra variable will be cleaned-up anyway */
+      case chk_CREATE:
+        pari_var_create(ep);
+        ep->valence = EpVAR;
+        ep->value = initial_value(ep);
+        break;
+      case chk_NOCREATE:
+        break;
+    }
   else if (ep->valence!=EpVAR)
     err_var(strtoGENstr(ep->name));
 }
 
+INLINE GEN
+checkvalueptr(entree *ep)
+{
+  checkvalue(ep, chk_NOCREATE);
+  return ep->valence==EpNEW? gen_0: (GEN)ep->value;
+}
+
 /* make GP variables safe for avma = top */
 static void
 lvar_make_safe(void)
@@ -363,12 +380,12 @@ struct trace
 };
 
 static THREAD long sp, rp, dbg_level;
-static THREAD long *st;
+static THREAD long *st, *precs;
 static THREAD gp_pointer *ptrs;
 static THREAD entree **lvars;
 static THREAD struct var_lex *var;
 static THREAD struct trace *trace;
-static THREAD pari_stack s_st, s_ptrs, s_var, s_lvars, s_trace;
+static THREAD pari_stack s_st, s_ptrs, s_var, s_lvars, s_trace, s_prec;
 
 static void
 changelex(long vn, GEN x)
@@ -496,6 +513,7 @@ pari_init_evaluator(void)
   pari_stack_init(&s_trace,sizeof(*trace),(void**)&trace);
   br_res = NULL;
   pari_stack_init(&s_relocs,sizeof(*relocs),(void**)&relocs);
+  pari_stack_init(&s_prec,sizeof(*precs),(void**)&precs);
 }
 void
 pari_close_evaluator(void)
@@ -505,6 +523,8 @@ pari_close_evaluator(void)
   pari_stack_delete(&s_var);
   pari_stack_delete(&s_lvars);
   pari_stack_delete(&s_trace);
+  pari_stack_delete(&s_relocs);
+  pari_stack_delete(&s_prec);
 }
 
 static gp_pointer *
@@ -525,10 +545,38 @@ new_ptr(void)
   return &ptrs[rp++];
 }
 
+void
+push_localprec(long p)
+{
+  long n = pari_stack_new(&s_prec);
+  precs[n] = p;
+}
+
+void
+pop_localprec(void)
+{
+  s_prec.n--;
+}
+
+long
+get_localprec(void)
+{
+  return s_prec.n? precs[s_prec.n-1]: precreal;
+}
+
+void
+localprec(long p)
+{
+  if (p < 1) pari_err_DOMAIN("localprec", "p", "<", gen_1, stoi(p));
+  if (p > prec2ndec(LGBITS))
+    pari_err_DOMAIN("localprec", "p", "==", utoi(LONG_MAX), stoi(p));
+  push_localprec(ndec2prec(p));
+}
+
 INLINE GEN
 copyupto(GEN z, GEN t)
 {
-  if (is_universal_constant(z) || (z>(GEN)bot && z<=t))
+  if (is_universal_constant(z) || (z>(GEN)pari_mainstack->bot && z<=t))
     return z;
   else
     return gcopy(z);
@@ -586,6 +634,9 @@ closure_castgen(GEN z, long mode)
   case Gsmall:
     st[sp++]=gtos(z);
     break;
+  case Gusmall:
+    st[sp++]=gtou(z);
+    break;
   case Gvar:
     st[sp++]=closure_varn(z);
     break;
@@ -703,6 +754,14 @@ closure_err(long level)
   }
 }
 
+GEN
+pari_self(void)
+{
+  long fun = s_trace.n - 1;
+  if (fun > 0) while (lg(trace[fun].closure)==6) fun--;
+  return trace[fun].closure;
+}
+
 long
 closure_context(long start, long level)
 {
@@ -748,7 +807,7 @@ closure_eval(GEN C)
   GEN data=closure_get_data(C);
   long loper=lg(oper);
   long saved_sp=sp-closure_arity(C);
-  long saved_rp=rp;
+  long saved_rp=rp, saved_prec=s_prec.n;
   long j, nbmvar=0, nblvar=0;
   long pc, t;
   clone_lock(C);
@@ -787,7 +846,7 @@ closure_eval(GEN C)
       gel(st,sp++)=gel(data,operand);
       break;
     case OCpushreal:
-      gel(st,sp++)=strtor(GSTR(data[operand]),precreal);
+      gel(st,sp++)=strtor(GSTR(data[operand]),get_localprec());
       break;
     case OCpushstoi:
       gel(st,sp++)=stoi(operand);
@@ -795,14 +854,13 @@ closure_eval(GEN C)
     case OCpushvar:
       {
         entree *ep = (entree *)operand;
-        pari_var_create(ep);
-        gel(st,sp++)=(GEN)initial_value(ep);
+        gel(st,sp++)=pol_x(pari_var_create(ep));
         break;
       }
     case OCpushdyn:
       {
         entree *ep = (entree *)operand;
-        checkvalue(ep);
+        checkvalue(ep, chk_CREATE);
         gel(st,sp++)=(GEN)ep->value;
         break;
       }
@@ -814,8 +872,7 @@ closure_eval(GEN C)
         gp_pointer *g = new_ptr();
         g->vn=0;
         g->ep = (entree*) operand;
-        checkvalue(g->ep);
-        g->x = (GEN) g->ep->value;
+        g->x = checkvalueptr(g->ep);
         g->ox = g->x; clone_lock(g->ox);
         g->sp = sp;
         gel(st,sp++) = (GEN)&(g->x);
@@ -837,7 +894,7 @@ closure_eval(GEN C)
         entree *ep = (entree *)operand;
         gp_pointer *g = new_ptr();
         matcomp *C;
-        checkvalue(ep);
+        checkvalue(ep, chk_ERROR);
         g->sp = -1;
         g->x = copyvalue(ep);
         g->ox = g->x; clone_lock(g->ox);
@@ -889,7 +946,7 @@ closure_eval(GEN C)
     case OCstoredyn:
       {
         entree *ep = (entree *)operand;
-        checkvalue(ep);
+        checkvalue(ep, chk_NOCREATE);
         changevalue(ep, gel(st,--sp));
         break;
       }
@@ -912,7 +969,7 @@ closure_eval(GEN C)
         break;
       }
     case OCprecreal:
-      st[sp++]=precreal;
+      st[sp++]=get_localprec();
       break;
     case OCprecdl:
       st[sp++]=precdl;
@@ -923,7 +980,7 @@ closure_eval(GEN C)
     case OCcowvardyn:
       {
         entree *ep = (entree *)operand;
-        checkvalue(ep);
+        checkvalue(ep, chk_ERROR);
         (void)copyvalue(ep);
         break;
       }
@@ -933,9 +990,15 @@ closure_eval(GEN C)
     case OCstoi:
       gel(st,sp-1)=stoi(st[sp-1]);
       break;
+    case OCutoi:
+      gel(st,sp-1)=utoi(st[sp-1]);
+      break;
     case OCitos:
       st[sp+operand]=gtos(gel(st,sp+operand));
       break;
+    case OCitou:
+      st[sp+operand]=gtou(gel(st,sp+operand));
+      break;
     case OCtostr:
       {
         GEN z = gel(st,sp+operand);
@@ -1129,7 +1192,7 @@ closure_eval(GEN C)
       {
         long n = pari_stack_new(&s_lvars);
         entree *ep = (entree *)operand;
-        checkvalue(ep);
+        checkvalue(ep, chk_NOCREATE);
         lvars[n] = ep;
         nblvar++;
         pushvalue(ep,gel(st,--sp));
@@ -1139,7 +1202,7 @@ closure_eval(GEN C)
       {
         long n = pari_stack_new(&s_lvars);
         entree *ep = (entree *)operand;
-        checkvalue(ep);
+        checkvalue(ep, chk_NOCREATE);
         lvars[n] = ep;
         nblvar++;
         zerovalue(ep);
@@ -1227,17 +1290,29 @@ closure_eval(GEN C)
       {
         long n=operand;
         GEN fun = gel(st,sp-1-n);
-        long arity;
+        long arity, isvar;
         GEN z;
         if (typ(fun)!=t_CLOSURE) pari_err(e_NOTFUNC, fun);
+        isvar = closure_is_variadic(fun);
         arity = closure_arity(fun);
-        if (n!=arity)
+        if (!isvar || n < arity)
         {
+          st_alloc(arity-n);
           if (n>arity)
             pari_err(e_MISC,"too many parameters in user-defined function call");
-          st_alloc(arity-n);
           for (j=n+1;j<=arity;j++)
             gel(st,sp++)=0;
+          if (isvar) gel(st,sp-1) = cgetg(1,t_VEC);
+        }
+        else
+        {
+          GEN v;
+          long j, m = n-arity+1;
+          v = cgetg(m+1,t_VEC);
+          sp-=m;
+          for (j=1; j<=m; j++)
+            gel(v,j) = gel(st,sp+j-1)? gcopy(gel(st,sp+j-1)): gen_0;
+          gel(st,sp++)=v;
         }
 #ifdef STACK_CHECK
         if (PARI_stack_limit && (void*) &z <= PARI_stack_limit)
@@ -1312,6 +1387,13 @@ closure_eval(GEN C)
       else
         st[sp+operand]=st[sp];
       break;
+    case OCdefaultulong:
+      sp--;
+      if (st[sp+operand])
+        st[sp+operand]=gtou(gel(st,sp+operand));
+      else
+        st[sp+operand]=st[sp];
+      break;
     case OCdefaultgen:
       sp--;
       if (!st[sp+operand])
@@ -1359,6 +1441,7 @@ endeval:
       clone_unlock(g->ox);
     }
   }
+  s_prec.n = saved_prec;
   s_trace.n--;
   restore_vars(nbmvar, nblvar);
   clone_unlock(C);
@@ -1379,6 +1462,7 @@ evalstate_save(struct pari_evalstate *state)
   state->avma = avma;
   state->sp   = sp;
   state->rp   = rp;
+  state->prec = s_prec.n;
   state->var  = s_var.n;
   state->lvars= s_lvars.n;
   state->trace= s_trace.n;
@@ -1393,6 +1477,7 @@ evalstate_restore(struct pari_evalstate *state)
   mtstate_restore(&state->pending_threads);
   sp = state->sp;
   rp = state->rp;
+  s_prec.n = state->prec;
   restore_vars(s_var.n-state->var,s_lvars.n-state->lvars);
   restore_trace(s_trace.n-state->trace);
   reset_break();
@@ -1419,7 +1504,7 @@ evalstate_reset(void)
   reset_break();
   compilestate_reset();
   parsestate_reset();
-  avma = top;
+  avma = pari_mainstack->top;
 }
 
 void
@@ -1477,24 +1562,6 @@ closure_returnupto(GEN C)
   return copyupto(closure_return(C),(GEN)av);
 }
 
-void
-closure_callvoid1(GEN C, GEN x)
-{
-  long i, ar = closure_arity(C);
-  gel(st,sp++) = x;
-  for(i=2; i <= ar; i++) gel(st,sp++) = NULL;
-  closure_evalvoid(C);
-}
-
-GEN
-closure_callgen1(GEN C, GEN x)
-{
-  long i, ar = closure_arity(C);
-  gel(st,sp++) = x;
-  for(i=2; i<= ar; i++) gel(st,sp++) = NULL;
-  return closure_returnupto(C);
-}
-
 GEN
 pareval_worker(GEN C)
 {
@@ -1561,7 +1628,7 @@ parvector(long n, GEN code)
 GEN
 parsum(GEN a, GEN b, GEN code, GEN x)
 {
-  pari_sp av = avma, av2, lim;
+  pari_sp av = avma, av2;
   long pending = 0;
   GEN worker = snm_closure(is_entry("_parvector_worker"), mkvec(code));
   GEN done;
@@ -1573,7 +1640,7 @@ parsum(GEN a, GEN b, GEN code, GEN x)
   mt_queue_start(&pt, worker);
   b = gfloor(b);
   a = mkvec(setloop(a));
-  av2=avma; lim = stack_lim(av2,1);
+  av2=avma;
   for (; cmpii(gel(a,1),b) <= 0 || pending; gel(a,1) = incloop(gel(a,1)))
   {
     mt_queue_submit(&pt, 0, cmpii(gel(a,1),b) <= 0? a: NULL);
@@ -1581,7 +1648,7 @@ parsum(GEN a, GEN b, GEN code, GEN x)
     if (done)
     {
       x = gadd(x, done);
-      if (low_stack(lim, stack_lim(av2,1)))
+      if (gc_needed(av2,1))
       {
         if (DEBUGMEM>1) pari_warn(warnmem,"sum");
         x = gerepileupto(av2,x);
@@ -1593,7 +1660,7 @@ parsum(GEN a, GEN b, GEN code, GEN x)
 }
 
 void
-parfor(GEN a, GEN b, GEN code, GEN code2)
+parfor(GEN a, GEN b, GEN code, void *E, long call(void*, GEN, GEN))
 {
   pari_sp av = avma, av2;
   long running, pending = 0;
@@ -1612,19 +1679,13 @@ parfor(GEN a, GEN b, GEN code, GEN code2)
   {
     mt_queue_submit(&pt, 0, running ? a: NULL);
     done = mt_queue_get(&pt, NULL, &pending);
-    if (code2 && done && (!stop || cmpii(gel(done,1),stop) < 0))
-    {
-      push_lex(gel(done,1), code2);
-      push_lex(gel(done,2), NULL);
-      closure_evalvoid(code2);
-      pop_lex(2);
-      if (loop_break())
+    if (call && done && (!stop || cmpii(gel(done,1),stop) < 0))
+      if (call(E, gel(done,1), gel(done,2)))
       {
         status = br_status;
         br_status = br_NONE;
         stop = gerepileuptoint(av2, gel(done,1));
       }
-    }
     gel(a,1) = incloop(gel(a,1));
     if (!stop) avma = av2;
   }
@@ -1634,8 +1695,25 @@ parfor(GEN a, GEN b, GEN code, GEN code2)
   avma = av;
 }
 
+static long
+gp_evalvoid2(void *E, GEN x, GEN y)
+{
+  GEN code =(GEN) E;
+  push_lex(x, code);
+  push_lex(y, NULL);
+  closure_evalvoid(code);
+  pop_lex(2);
+  return loop_break();
+}
+
+void
+parfor0(GEN a, GEN b, GEN code, GEN code2)
+{
+  parfor(a, b, code, (void*)code2, code2 ? gp_evalvoid2: NULL);
+}
+
 void
-parforprime(GEN a, GEN b, GEN code, GEN code2)
+parforprime(GEN a, GEN b, GEN code, void *E, long call(void*, GEN, GEN))
 {
   pari_sp av = avma, av2;
   long running, pending = 0;
@@ -1652,19 +1730,13 @@ parforprime(GEN a, GEN b, GEN code, GEN code2)
   {
     mt_queue_submit(&pt, 0, running ? mkvec(T.pp): NULL);
     done = mt_queue_get(&pt, NULL, &pending);
-    if (code2 && done && (!stop || cmpii(gel(done,1),stop) < 0))
-    {
-      push_lex(gel(done,1), code2);
-      push_lex(gel(done,2), NULL);
-      closure_evalvoid(code2);
-      pop_lex(2);
-      if (loop_break())
+    if (call && done && (!stop || cmpii(gel(done,1),stop) < 0))
+      if (call(E, gel(done,1), gel(done,2)))
       {
         status = br_status;
         br_status = br_NONE;
         stop = gerepileuptoint(av2, gel(done,1));
       }
-    }
     if (!stop) avma = av2;
   }
   avma = av2;
@@ -1673,6 +1745,30 @@ parforprime(GEN a, GEN b, GEN code, GEN code2)
   avma = av;
 }
 
+void
+parforprime0(GEN a, GEN b, GEN code, GEN code2)
+{
+  parforprime(a, b, code, (void*)code2, code2? gp_evalvoid2: NULL);
+}
+
+void
+closure_callvoid1(GEN C, GEN x)
+{
+  long i, ar = closure_arity(C);
+  gel(st,sp++) = x;
+  for(i=2; i <= ar; i++) gel(st,sp++) = NULL;
+  closure_evalvoid(C);
+}
+
+GEN
+closure_callgen1(GEN C, GEN x)
+{
+  long i, ar = closure_arity(C);
+  gel(st,sp++) = x;
+  for(i=2; i<= ar; i++) gel(st,sp++) = NULL;
+  return closure_returnupto(C);
+}
+
 GEN
 closure_callgen2(GEN C, GEN x, GEN y)
 {
@@ -1689,6 +1785,8 @@ closure_callgenvec(GEN C, GEN args)
 {
   long i, l = lg(args), ar = closure_arity(C);
   st_alloc(ar);
+  if (l-1 > ar)
+    pari_err(e_MISC,"too many parameters in user-defined function call");
   for (i = 1; i < l;   i++) gel(st,sp++) = gel(args,i);
   for(      ; i <= ar; i++) gel(st,sp++) = NULL;
   return closure_returnupto(C);
@@ -1700,6 +1798,8 @@ closure_callgenall(GEN C, long n, ...)
   va_list ap;
   long i, ar = closure_arity(C);
   va_start(ap,n);
+  if (n > ar)
+    pari_err(e_MISC,"too many parameters in user-defined function call");
   st_alloc(ar);
   for (i = 1; i <=n;  i++) gel(st,sp++) = va_arg(ap, GEN);
   for(      ; i <=ar; i++) gel(st,sp++) = NULL;
@@ -1746,6 +1846,13 @@ gp_call(void *E, GEN x)
   return closure_callgen1(code, x);
 }
 
+GEN
+gp_call2(void *E, GEN x, GEN y)
+{
+  GEN code = (GEN)E;
+  return closure_callgen2(code, x, y);
+}
+
 long
 gp_callbool(void *E, GEN x)
 {
@@ -1875,9 +1982,15 @@ closure_disassemble(GEN C)
     case OCstoi:
       pari_printf("stoi\n");
       break;
+    case OCutoi:
+      pari_printf("utoi\n");
+      break;
     case OCitos:
       pari_printf("itos\t\t%ld\n",operand);
       break;
+    case OCitou:
+      pari_printf("itou\t\t%ld\n",operand);
+      break;
     case OCtostr:
       pari_printf("tostr\t\t%ld\n",operand);
       break;
@@ -1926,6 +2039,9 @@ closure_disassemble(GEN C)
     case OCdefaultlong:
       pari_printf("defaultlong\t%ld\n",operand);
       break;
+    case OCdefaultulong:
+      pari_printf("defaultulong\t%ld\n",operand);
+      break;
     case OCdefaultgen:
       pari_printf("defaultgen\t%ld\n",operand);
       break;
@@ -2041,7 +2157,9 @@ opcode_need_relink(op_code opcode)
   case OCprecreal:
   case OCprecdl:
   case OCstoi:
+  case OCutoi:
   case OCitos:
+  case OCitou:
   case OCtostr:
   case OCvarn:
   case OCcopy:
@@ -2061,6 +2179,7 @@ opcode_need_relink(op_code opcode)
   case OCdefaultarg:
   case OCdefaultgen:
   case OCdefaultlong:
+  case OCdefaultulong:
   case OCcalluser:
   case OCvec:
   case OCcol:
@@ -2204,11 +2323,6 @@ copybin_unlink(GEN C)
   return res;
 }
 
-static ulong
-hash_id(void *x) { return (ulong)x; }
-static int
-eq_id(void *x, void *y) { return x == y; }
-
 /* e = t_VECSMALL of entree *ep [ addresses ],
  * names = t_VEC of strtoGENstr(ep.names),
  * Return hashtable : ep => is_entry(ep.name) */
@@ -2216,12 +2330,12 @@ hashtable *
 hash_from_link(GEN e, GEN names, int use_stack)
 {
   long i, l = lg(e);
-  hashtable *h = hash_create(l-1, &hash_id, &eq_id, use_stack);
+  hashtable *h = hash_create_ulong(l-1, use_stack);
   if (lg(names) != l) pari_err_DIM("hash_from_link");
   for (i = 1; i < l; i++)
   {
     char *s = GSTR(gel(names,i));
-    hash_insert(h, (void*)e[i], (void*)fetch_entry(s, strlen(s)));
+    hash_insert(h, (void*)e[i], (void*)fetch_entry(s));
   }
   return h;
 }
diff --git a/src/gp/gp.c b/src/language/gplib.c
similarity index 60%
copy from src/gp/gp.c
copy to src/language/gplib.c
index c7af7e2..82ce33c 100644
--- a/src/gp/gp.c
+++ b/src/language/gplib.c
@@ -13,12 +13,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 
 /*******************************************************************/
 /**                                                               **/
-/**                        PARI CALCULATOR                        **/
+/**            LIBRARY ROUTINES FOR PARI CALCULATOR               **/
 /**                                                               **/
 /*******************************************************************/
 #include "pari.h"
 #include "paripriv.h"
-#include "gp.h"
 
 #ifdef _WIN32
 #  include <windows.h>
@@ -34,161 +33,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 /**                                                                **/
 /********************************************************************/
 
-static void
-skip_space(char **s) {
+void
+pari_skip_space(char **s) {
   char *t = *s;
   while (isspace((int)*t)) t++;
   *s = t;
 }
-static void
-skip_alpha(char **s) {
+void
+pari_skip_alpha(char **s) {
   char *t = *s;
   while (isalpha((int)*t)) t++;
   *s = t;
 }
 
-static char *
-translate(char **src, char *s, char *entry)
-{
-  char *t = *src;
-  while (*t)
-  {
-    while (*t == '\\')
-    {
-      switch(*++t)
-      {
-        case 'e':  *s='\033'; break; /* escape */
-        case 'n':  *s='\n'; break;
-        case 't':  *s='\t'; break;
-        default:   *s=*t;
-                   if (!*t) pari_err(e_SYNTAX,"unfinished string",s,entry);
-      }
-      t++; s++;
-    }
-    if (*t == '"')
-    {
-      if (t[1] != '"') break;
-      t += 2; continue;
-    }
-    *s++ = *t++;
-  }
-  *s=0; *src=t; return s;
-}
-
-static void
-matchQ(char *s, char *entry)
-{
-  if (*s != '"')
-    pari_err(e_SYNTAX,"expected character: '\"' instead of",s,entry);
-}
-
-/*  Read a "string" from src. Format then copy it, starting at s. Return
- *  pointer to char following the end of the input string */
-static char *
-readstring(char *src, char *s, char *entry)
-{
-  matchQ(src, entry); src++; s = translate(&src, s, entry);
-  matchQ(src, entry); return src+1;
-}
-/*******************************************************************/
-/**                                                               **/
-/**                    TEXMACS-SPECIFIC STUFF                     **/
-/**                                                               **/
-/*******************************************************************/
-static int tm_is_waiting = 0, tm_did_complete = 0;
-
-/* tell TeXmacs GP will start outputing data */
-static void
-tm_start_output(void)
-{
-  if (!tm_is_waiting) { printf("%cverbatim:",DATA_BEGIN); fflush(stdout); }
-  tm_is_waiting = 1;
-}
-/* tell TeXmacs GP is done and is waiting for new data */
-static void
-tm_end_output(void)
-{
-  if (tm_is_waiting) { printf("%c", DATA_END); fflush(stdout); }
-  tm_is_waiting = 0;
-}
-static char *
-fgets_texmacs(char *s, int n, FILE *f)
-{
-  if (!tm_did_complete)
-  {
-    tm_start_output(); tm_end_output(); /* tell TeXmacs we need input */
-  }
-  return fgets(s,n,f);
-}
-
-#ifdef READLINE
-typedef struct {
-  char *cmd;
-  long n; /* number of args */
-  char **v; /* args */
-} tm_cmd;
-
-static void
-parse_texmacs_command(tm_cmd *c, const char *ch)
-{
-  long l = strlen(ch);
-  char *t, *s = (char*)ch, *send = s+l-1;
-  char **A;
-  pari_stack s_A;
-
-  if (*s != DATA_BEGIN || *send-- != DATA_END)
-    pari_err(e_MISC, "missing DATA_[BEGIN | END] in TeXmacs command");
-  s++;
-  if (strncmp(s, "special:", 8)) pari_err(e_MISC, "unrecognized TeXmacs command");
-  s += 8;
-  if (*s != '(' || *send-- != ')')
-    pari_err(e_MISC, "missing enclosing parentheses for TeXmacs command");
-  s++; t = s;
-  skip_alpha(&s);
-  c->cmd = pari_strndup(t, s - t);
-  pari_stack_init(&s_A,sizeof(*A),(void**)&A);
-  for (c->n = 0; s <= send; c->n++)
-  {
-    char *u = (char*)pari_malloc(strlen(s) + 1);
-    skip_space(&s);
-    if (*s == '"') s = readstring(s, u, t);
-    else
-    { /* read integer */
-      t = s;
-      while (isdigit((int)*s)) s++;
-      strncpy(u, t, s - t); u[s-t] = 0;
-    }
-    pari_stack_pushp(&s_A, u);
-  }
-  c->v = A;
-}
-
-static void
-free_cmd(tm_cmd *c)
-{
-  while (c->n--) pari_free((void*)c->v[c->n]);
-  pari_free((void*)c->v);
-}
-
-static void
-handle_texmacs_command(const char *s)
-{
-  tm_cmd c;
-  parse_texmacs_command(&c, s);
-  if (strcmp(c.cmd, "complete"))
-    pari_err(e_MISC,"Texmacs_stdin command %s not implemented", c.cmd);
-  if (c.n != 2)
-    pari_err(e_MISC,"was expecting 2 arguments for Texmacs_stdin command");
-  texmacs_completion(c.v[0], atol(c.v[1]));
-  free_cmd(&c);
-  tm_did_complete = 1;
-}
-#else
-static void
-handle_texmacs_command(const char *s)
-{ (void)s;pari_err(e_MISC, "readline not available"); }
-#endif
-
 /*******************************************************************/
 /**                                                               **/
 /**                          BUFFERS                              **/
@@ -196,8 +53,11 @@ handle_texmacs_command(const char *s)
 /*******************************************************************/
 static Buffer **bufstack;
 static pari_stack s_bufstack;
+void
+pari_init_buffers(void)
+{ pari_stack_init(&s_bufstack, sizeof(Buffer*), (void**)&bufstack); }
 
-static void
+void
 pop_buffer(void)
 {
   if (s_bufstack.n)
@@ -205,7 +65,7 @@ pop_buffer(void)
 }
 
 /* kill all buffers until B is met or nothing is left */
-static void
+void
 kill_buffers_upto(Buffer *B)
 {
   while (s_bufstack.n) {
@@ -213,7 +73,7 @@ kill_buffers_upto(Buffer *B)
     pop_buffer();
   }
 }
-static void
+void
 kill_buffers_upto_including(Buffer *B)
 {
   while (s_bufstack.n) {
@@ -222,11 +82,6 @@ kill_buffers_upto_including(Buffer *B)
   }
 }
 
-/********************************************************************/
-/**                                                                **/
-/**                             HELP                               **/
-/**                                                                **/
-/********************************************************************/
 static int disable_exception_handler = 0;
 #define BLOCK_EH_START                \
 {                                     \
@@ -236,24 +91,25 @@ static int disable_exception_handler = 0;
 #define BLOCK_EH_END                \
   disable_exception_handler = block;\
 }
-static char *Help;
-
-static char *
-init_help(void)
+/* numerr < 0: from SIGINT */
+int
+gp_handle_exception(long numerr)
 {
-  char *h = os_getenv("GPHELP");
-# ifdef GPHELP
-  if (!h) h = (char*)GPHELP;
-# endif
-#ifdef _WIN32
-  win32_set_pdf_viewer();
-#endif
-  if (h) h = pari_strdup(h);
-  return h;
+  if (disable_exception_handler)
+    disable_exception_handler = 0;
+  else if (GP_DATA->breakloop && cb_pari_break_loop
+                              && cb_pari_break_loop(numerr))
+    return 1;
+  return 0;
 }
 
-static void
-hit_return(void)
+/********************************************************************/
+/**                                                                **/
+/**                             HELP                               **/
+/**                                                                **/
+/********************************************************************/
+void
+pari_hit_return(void)
 {
   int c;
   if (GP_DATA->flags & (gpd_EMACS|gpd_TEXMACS)) return;
@@ -265,16 +121,9 @@ hit_return(void)
   pari_putc('\n');
   BLOCK_EH_END
 }
-static void
-gp_ask_confirm(const char *s)
-{
-  err_printf(s);
-  err_printf(". OK ? (^C if not)\n");
-  hit_return();
-}
 
 static int
-has_ext_help(void) { return (Help && *Help); }
+has_ext_help(void) { return (GP_DATA->help && *GP_DATA->help); }
 
 static int
 compare_str(char **s1, char **s2) { return strcmp(*s1, *s2); }
@@ -308,7 +157,7 @@ print_fun_list(char **list, long nbli)
     if (i >= nbcol)
     {
       i=0; pari_putc('\n');
-      if (nbli && j++ > nbli) { j = 0; hit_return(); }
+      if (nbli && j++ > nbli) { j = 0; pari_hit_return(); }
       continue;
     }
     len = maxlen - strlen(*l);
@@ -317,6 +166,7 @@ print_fun_list(char **list, long nbli)
   if (i) pari_putc('\n');
 }
 
+static const long MAX_SECTION = 13;
 static void
 commands(long n)
 {
@@ -338,43 +188,27 @@ commands(long n)
         case EpNEW: continue;
       }
       m = ep->menu;
-      if ((n < 0 && m && m < 13) || m == n) pari_stack_pushp(&s_L, (void*)ep->name);
+      if (m == n || (n < 0 && m && m <= MAX_SECTION))
+        pari_stack_pushp(&s_L, (void*)ep->name);
     }
   pari_stack_pushp(&s_L, NULL);
   print_fun_list(t_L, term_height()-4);
   pari_stack_delete(&s_L);
 }
 
-static void
-center(const char *s)
+void
+pari_center(const char *s)
 {
+  pari_sp av = avma;
   long i, l = strlen(s), pad = term_width() - l;
   char *buf, *u;
 
   if (pad<0) pad=0; else pad >>= 1;
-  u = buf = (char*)pari_malloc(l + pad + 2);
+  u = buf = stack_malloc(l + pad + 2);
   for (i=0; i<pad; i++) *u++ = ' ';
   while (*s) *u++ = *s++;
   *u++ = '\n'; *u = 0;
-  pari_puts(buf); pari_free(buf);
-}
-
-static void
-usage(char *s)
-{
-  printf("### Usage: %s [options] [GP files]\n", s);
-  printf("Available options:\n");
-  printf("  [-f,--fast]\t\tFast start: do not read .gprc\n");
-  printf("  [-q,--quiet]\t\tQuiet mode: do not print banner and history numbers\n");
-  printf("  [-s stacksize]\tStart with the PARI stack of given size (in bytes)\n");
-  printf("  [--default key=val]\tExecute default(key,val) on startup\n");
-  printf("  [--emacs]\t\tRun as if in Emacs shell\n");
-  printf("  [--help]\t\tPrint this message\n");
-  printf("  [--test]\t\tTest mode. No history, wrap long lines (bench only)\n");
-  printf("  [--texmacs]\t\tRun as if using TeXmacs frontend\n");
-  printf("  [--version]\t\tOutput version info and exit\n");
-  printf("  [--version-short]\tOutput version number and exit\n\n");
-  exit(0);
+  pari_puts(buf); avma = av;
 }
 
 static void
@@ -424,6 +258,7 @@ gentypes(void)
   t_VECSMALL: vec. small ints  [ code ] [ x_1 ] ... [ x_k ]\n\
   t_CLOSURE: functions [ code ] [ arity ] [ code ] [ operand ] [ data ] [ text ]\n\
   t_ERROR  : error context     [ code ] [ errnum ] [ dat_1 ] ... [ dat_k ]\n\
+  t_INFINITY: a*infinity       [ code ] [ a ]\n\
 \n");
 }
 
@@ -437,13 +272,15 @@ menu_commands(void)
   3: TRANSCENDENTAL functions\n\
   4: NUMBER THEORETICAL functions\n\
   5: Functions related to ELLIPTIC CURVES\n\
-  6: Functions related to general NUMBER FIELDS\n\
-  7: POLYNOMIALS and power series\n\
-  8: Vectors, matrices, LINEAR ALGEBRA and sets\n\
-  9: SUMS, products, integrals and similar functions\n\
- 10: GRAPHIC functions\n\
- 11: PROGRAMMING under GP\n\
- 12: The PARI community\n\
+  6: Functions related to MODULAR FORMS and MODULAR SYMBOLS\n\
+  7: Functions related to general NUMBER FIELDS\n\
+  8: Functions related to central simple ALGEBRAS\n\
+  9: POLYNOMIALS and power series\n\
+ 10: Vectors, matrices, LINEAR ALGEBRA and sets\n\
+ 11: SUMS, products, integrals and similar functions\n\
+ 12: GRAPHIC functions\n\
+ 13: PROGRAMMING under GP\n\
+ 14: The PARI community\n\
 \n\
 Also:\n\
   ? functionname (short on-line help)\n\
@@ -582,7 +419,7 @@ external_help(const char *s, int num)
   long nbli = term_height()-3, li = 0;
   char buf[256], *str;
   const char *opt = "", *ar = "", *cdir = "";
-  char *t, *help = Help;
+  char *t, *help = GP_DATA->help;
   pariFILE *z;
   FILE *f;
 
@@ -608,7 +445,7 @@ external_help(const char *s, int num)
   {
     if (!strncmp("ugly_kludge_done",buf,16)) break;
     pari_puts(buf);
-    if (nl_read(buf) && ++li > nbli) { hit_return(); li = 0; }
+    if (nl_read(buf) && ++li > nbli) { pari_hit_return(); li = 0; }
   }
   pari_fclose(z);
 }
@@ -661,8 +498,9 @@ static void
 digit_help(char *s, long flag)
 {
   long n = atoi(s);
-  if (n < 0 || n > 15) pari_err(e_SYNTAX,"no such section in help: ?",s,s);
-  if (n == 12)
+  if (n < 0 || n > MAX_SECTION+4)
+    pari_err(e_SYNTAX,"no such section in help: ?",s,s);
+  if (n == MAX_SECTION+1)
     community();
   else if (flag & h_LONG)
     external_help(s,3);
@@ -684,7 +522,7 @@ default_help(char *s, long flag)
 }
 
 static void
-aide0(const char *s0, int flag)
+help(const char *s0, int flag)
 {
   const long long_help = flag & h_LONG;
   long n;
@@ -694,16 +532,16 @@ aide0(const char *s0, int flag)
   if (isdigit((int)*s)) { digit_help(s,flag); return; }
   if (flag & h_APROPOS) { external_help(s,-1); return; }
   /* Get meaningful answer on '\ps 5' (e.g. from <F1>) */
-  if (*s == '\\') { char *t = s+1; skip_alpha(&t); *t = '\0'; }
+  if (*s == '\\') { char *t = s+1; pari_skip_alpha(&t); *t = '\0'; }
   if (isalpha((int)*s))
   {
     if (!strncmp(s, "default", 7))
     { /* special-case ?default(dft_name), e.g. default(log) */
       char *t = s+7;
-      skip_space(&t);
+      pari_skip_space(&t);
       if (*t == '(')
       {
-        t++; skip_space(&t);
+        t++; pari_skip_space(&t);
         cut_trailing_garbage(t);
         if (pari_is_default(t)) { default_help(t,flag); return; }
       }
@@ -726,7 +564,7 @@ aide0(const char *s0, int flag)
       default_help(s,flag);
     else if (long_help)
       external_help(s,3);
-    else if (!cb_pari_whatnow(pariOut, s,1))
+    else if (!cb_pari_whatnow || !cb_pari_whatnow(pariOut, s,1))
       simple_help(s,"unknown identifier");
     return;
   }
@@ -762,14 +600,14 @@ aide0(const char *s0, int flag)
       break;
 
     default: /* built-in function */
-      if (!ep->help) pari_err_BUG("aide (no help found)"); /*paranoia*/
+      if (!ep->help) pari_err_BUG("gp_help (no help found)"); /*paranoia*/
       if (long_help) { external_help(ep->name,3); return; }
   }
   print_text(ep->help);
 }
 
 void
-aide(const char *s, long flag)
+gp_help(const char *s, long flag)
 {
   pari_sp av = avma;
   if ((flag & h_RL) == 0)
@@ -777,7 +615,7 @@ aide(const char *s, long flag)
     if (*s == '?') { flag |= h_LONG; s++; }
     if (*s == '?') { flag |= h_APROPOS; s++; }
   }
-  term_color(c_HELP); aide0(s,flag); term_color(c_NONE);
+  term_color(c_HELP); help(s,flag); term_color(c_NONE);
   if ((flag & h_RL) == 0) pari_putc('\n');
   avma = av;
 }
@@ -800,18 +638,6 @@ what_readline(void)
 #endif
 }
 
-static void
-print_shortversion(void)
-{
-  const ulong mask = (1UL<<PARI_VERSION_SHIFT) - 1;
-  ulong n = paricfg_version_code, major, minor, patch;
-
-  patch = n & mask; n >>= PARI_VERSION_SHIFT;
-  minor = n & mask; n >>= PARI_VERSION_SHIFT;
-  major = n;
-  printf("%lu.%lu.%lu\n", major,minor,patch); exit(0);
-}
-
 static char *
 what_cc(void)
 {
@@ -836,202 +662,6 @@ what_cc(void)
 }
 
 static void
-print_version(void)
-{
-  pari_sp av = avma;
-  char *buf, *ver = what_cc();
-  const char *date = paricfg_compiledate;
-
-  center(paricfg_version);
-  center(paricfg_buildinfo);
-  buf = stack_malloc(strlen(date) +  32 + (ver? strlen(ver): 0));
-  if (ver) (void)sprintf(buf, "compiled: %s, %s", date, ver);
-  else     (void)sprintf(buf, "compiled: %s", date);
-  center(buf);
-  sprintf(buf, "threading engine: %s",paricfg_mt_engine);
-  center(buf);
-  ver = what_readline();
-  buf = stack_malloc(strlen(ver) + 64);
-  (void)sprintf(buf, "(readline %s, extended help%s enabled)", ver,
-                has_ext_help()? "": " not");
-  center(buf); avma = av;
-}
-
-static void
-gp_head(void)
-{
-#ifdef READLINE
-  if (GP_DATA->flags & gpd_TEXMACS)
-    printf("%ccommand:(cas-supports-completions-set! \"pari\")%c\n",
-           DATA_BEGIN, DATA_END);
-#endif
-  print_version();
-  pari_putc('\n');
-  center("Copyright (C) 2000-2014 The PARI Group");
-  pari_putc('\n');
-  print_text("PARI/GP is free software, covered by the GNU General Public \
-License, and comes WITHOUT ANY WARRANTY WHATSOEVER.");
-  pari_puts("\nType ? for help, \\q to quit.\n");
-  print_text("Type ?12 for how to get moral (and possibly technical) support.");
-  pari_printf("\nparisize = %lu, primelimit = %lu\n",
-              top - bot, GP_DATA->primelimit);
-}
-
-/********************************************************************/
-/**                                                                **/
-/**                         METACOMMANDS                           **/
-/**                                                                **/
-/********************************************************************/
-#define pariputs_opt(s) if (!(GP_DATA->flags & gpd_QUIET)) pari_puts(s)
-
-void
-gp_quit(long exitcode)
-{
-  if (Help) pari_free((void*)Help);
-  free_graph();
-  pari_close();
-  kill_buffers_upto(NULL);
-  pariputs_opt("Goodbye!\n");
-  if (GP_DATA->flags & gpd_TEXMACS) tm_end_output();
-  exit(exitcode);
-}
-
-static GEN
-gpreadbin(const char *s, int *vector)
-{
-  GEN x = readbin(s,pari_infile, vector);
-  popinfile();
-  if (!x) pari_err_FILE("input file",s);
-  return x;
-}
-
-static void
-escape(char *tch, int ismain)
-{
-  const char *s;
-  char c;
-
-  if (compatible != NONE)
-  {
-    s = tch;
-    while (*s)
-      if (*s++ == '=')
-      {
-        GEN (*f)(const char *v, long flag) = NULL;
-        long len = (s-tch) - 1;
-        if      (!strncmp(tch,"precision",len))    f = sd_realprecision;
-        else if (!strncmp(tch,"serieslength",len)) f = sd_seriesprecision;
-        else if (!strncmp(tch,"format",len))       f = sd_format;
-        else if (!strncmp(tch,"prompt",len))       f = sd_prompt;
-        if (f) { (void)f(s, d_ACKNOWLEDGE); return; }
-        break;
-      }
-  }
-  s = tch;
-  switch ((c = *s++))
-  {
-    case 'w': case 'x': case 'a': case 'b': case 'B': case 'm':
-    { /* history things */
-      long d;
-      GEN x;
-      if (c != 'w' && c != 'x') d = get_int(s,0);
-      else
-      {
-        d = atol(s); if (*s == '-') s++;
-        while (isdigit((int)*s)) s++;
-      }
-      x = gp_history(GP_DATA->hist, d, tch+1,tch-1);
-      switch (c)
-      {
-        case 'B':
-        { /* prettyprinter */
-          gp_data G = *GP_DATA; /* copy */
-          gp_hist   h = *(G.hist); /* copy */
-          pariout_t f = *(G.fmt);  /* copy */
-
-          G.hist = &h; h.total = 0; /* no hist number */
-          G.fmt  = &f; f.prettyp = f_PRETTY;
-          G.flags &= ~(gpd_TEST|gpd_TEXMACS);
-          G.lim_lines = 0;
-          gp_output(x, &G); break;
-        }
-        case 'a': brute   (x, GP_DATA->fmt->format, -1); break;
-        case 'b': /* fall through */
-        case 'm': matbrute(x, GP_DATA->fmt->format, -1); break;
-        case 'x': dbgGEN(x, get_int(s, -1)); break;
-        case 'w':
-          s = get_sep(s); if (!*s) s = current_logfile;
-          write0(s, mkvec(x)); return;
-      }
-      pari_putc('\n'); return;
-    }
-
-    case 'c': commands(-1); break;
-    case 'd': (void)setdefault(NULL,NULL,d_SILENT); break;
-    case 'e':
-      s = get_sep(s);
-      if (!*s) s = (GP_DATA->echo)? "0": "1";
-      (void)sd_echo(s,d_ACKNOWLEDGE); break;
-    case 'g':
-      switch (*s)
-      {
-        case 'm': s++; (void)sd_debugmem(*s? s: NULL,d_ACKNOWLEDGE); break;
-        case 'f': s++; (void)sd_debugfiles(*s? s: NULL,d_ACKNOWLEDGE); break;
-        default : (void)sd_debug(*s? s: NULL,d_ACKNOWLEDGE); break;
-      }
-      break;
-    case 'h': print_functions_hash(s); break;
-    case 'l':
-      s = get_sep(s);
-      if (*s)
-      {
-        (void)sd_logfile(s,d_ACKNOWLEDGE);
-        if (pari_logfile) break;
-      }
-      (void)sd_log(pari_logfile?"0":"1",d_ACKNOWLEDGE);
-      break;
-    case 'o': (void)sd_output(*s? s: NULL,d_ACKNOWLEDGE); break;
-    case 'p':
-      switch (*s)
-      {
-        case 's': s++;
-          (void)sd_seriesprecision(*s? s: NULL,d_ACKNOWLEDGE); break;
-        default :
-          (void)sd_realprecision(*s? s: NULL,d_ACKNOWLEDGE); break;
-      }
-      break;
-    case 'q': gp_quit(0); break;
-    case 'r':
-      s = get_sep(s);
-      if (!ismain) { read0(s); break; }
-      switchin(s);
-      if (file_is_binary(pari_infile))
-      {
-        int vector;
-        GEN x = gpreadbin(s, &vector);
-        if (vector) /* many BIN_GEN */
-        {
-          long i, l = lg(x);
-          pari_warn(warner,"setting %ld history entries", l-1);
-          for (i=1; i<l; i++) pari_add_hist(gel(x,i), 0);
-        }
-      }
-      break;
-    case 's': dbg_pari_heap(); break;
-    case 't': gentypes(); break;
-    case 'u':
-      print_all_user_fun((*s == 'm')? 1: 0);
-      break;
-    case 'v': print_version(); break;
-    case 'y':
-      s = get_sep(s);
-      if (!*s) s = (GP_DATA->simplify)? "0": "1";
-      (void)sd_simplify(s,d_ACKNOWLEDGE); break;
-    default: pari_err(e_SYNTAX,"unexpected character", tch,tch-1);
-  }
-}
-
-static void
 convert_time(char *s, long delay)
 {
   if (delay >= 3600000)
@@ -1058,7 +688,7 @@ convert_time(char *s, long delay)
 }
 
 /* Format a time of 'delay' ms */
-static char *
+const char *
 gp_format_time(long delay)
 {
   static char buf[64];
@@ -1074,47 +704,14 @@ gp_format_time(long delay)
   s[2] = 0; return buf;
 }
 
-static int
-chron(char *s)
-{
-  if (*s)
-  { /* if "#" or "##" timer metacommand. Otherwise let the parser get it */
-    char *t;
-    if (*s == '#') s++;
-    if (*s) return 0;
-    t = gp_format_time(pari_get_histtime(0));
-    pari_printf("  ***   last result computed in %s", t);
-  }
-  else { GP_DATA->chrono ^= 1; (void)sd_timer(NULL,d_ACKNOWLEDGE); }
-  return 1;
-}
-
-/* return 0: can't interpret *buf as a metacommand
- *        1: did interpret *buf as a metacommand or empty command */
-static int
-check_meta(char *buf, int ismain)
-{
-  switch(*buf++)
-  {
-    case '?': aide(buf, h_REGULAR); break;
-    case '#': return chron(buf);
-    case '\\': escape(buf, ismain); break;
-    case '\0': break;
-    default: return 0;
-  }
-  return 1;
-}
-
-/********************************************************************/
-/*                                                                  */
-/*                              GPRC                                */
-/*                                                                  */
-/********************************************************************/
-/* LOCATE GPRC */
-
-static int get_line_from_file(const char *prompt, filtre_t *F, FILE *file);
-static void
-err_gprc(const char *s, char *t, char *u)
+/********************************************************************/
+/*                                                                  */
+/*                              GPRC                                */
+/*                                                                  */
+/********************************************************************/
+/* LOCATE GPRC */
+static void
+err_gprc(const char *s, char *t, char *u)
 {
   err_printf("\n");
   pari_err(e_SYNTAX,s,t,u);
@@ -1240,6 +837,14 @@ get_preproc_value(char **s)
     if (!d) return orequal;
     return less? (d < 0): (d > 0);
   }
+  if (!strncmp(*s,"BITS_IN_LONG",12)) {
+    *s += 12;
+    if ((*s)[0] == '=' && (*s)[1] == '=')
+    {
+      *s += 2;
+      return BITS_IN_LONG == read_uint(s);
+    }
+  }
   return -1;
 }
 
@@ -1270,7 +875,7 @@ next_expr(char *t)
   }
 }
 
-static Buffer *
+Buffer *
 filtered_buffer(filtre_t *F)
 {
   Buffer *b = new_buffer();
@@ -1279,11 +884,9 @@ filtered_buffer(filtre_t *F)
   return b;
 }
 
-static jmp_buf *env;
-static pari_stack s_env;
 /* parse src of the form s=t (or s="t"), set *ps to s, and *pt to t.
  * modifies src (replaces = by \0) */
-static void
+void
 parse_key_val(char *src, char **ps, char **pt)
 {
   char *s_end, *t;
@@ -1291,20 +894,23 @@ parse_key_val(char *src, char **ps, char **pt)
   if (*t != '=') err_gprc("missing '='",t,src);
   s_end = t;
   t++;
-  if (*t == '"') (void)readstring(t, t, src);
+  if (*t == '"') (void)pari_translate_string(t, t, src);
   *s_end = 0; *ps = src; *pt = t;
 }
 
-static void
+void
 gp_initrc(pari_stack *p_A)
 {
   FILE *file = gprc_get();
   Buffer *b;
   filtre_t F;
   VOLATILE long c = 0;
+  jmp_buf *env;
+  pari_stack s_env;
 
   if (!file) return;
   b = filtered_buffer(&F);
+  pari_stack_init(&s_env, sizeof(*env), (void**)&env);
   (void)pari_stack_new(&s_env);
   for(;;)
   {
@@ -1340,7 +946,7 @@ gp_initrc(pari_stack *p_A)
       { /* read file */
         s += 4;
         t = (char*)pari_malloc(strlen(s) + 1);
-        if (*s == '"') (void)readstring(s, t, s-4); else strcpy(t,s);
+        if (*s == '"') (void)pari_translate_string(s, t, s-4); else strcpy(t,s);
         pari_stack_pushp(p_A,t);
       }
       else
@@ -1350,28 +956,48 @@ gp_initrc(pari_stack *p_A)
       }
     }
   }
-  s_env.n--;
+  pari_stack_delete(&s_env);
   pop_buffer();
   if (!(GP_DATA->flags & gpd_QUIET)) err_printf("Done.\n\n");
   fclose(file);
 }
 
+void
+gp_load_gprc(void)
+{
+  pari_stack sA;
+  char **A;
+  long i;
+  pari_stack_init(&sA,sizeof(*A),(void**)&A);
+  gp_initrc(&sA);
+  for (i = 0; i < sA.n; pari_free(A[i]),i++)
+  {
+    pari_CATCH(CATCH_ALL) { err_printf("... skipping file '%s'\n", A[i]); }
+    pari_TRY { gp_read_file(A[i]); } pari_ENDCATCH;
+  }
+  pari_stack_delete(&sA);
+}
+
 /********************************************************************/
 /*                                                                  */
 /*                             PROMPTS                              */
 /*                                                                  */
 /********************************************************************/
-static int gp_is_interactive = 0;
-static const char *DFT_PROMPT = "? ";
-static const char *CONTPROMPT = "";
-static const char *COMMENTPROMPT = "comment> ";
-static const char *DFT_INPROMPT = "";
-
-static char Prompt[MAX_PROMPT_LEN], Prompt_cont[MAX_PROMPT_LEN];
-
 #ifndef _WIN32
-/* if prompt is coloured, we must tell readline to ignore the
- * corresponding ANSI escape sequences */
+/* if prompt is coloured, tell readline to ignore the ANSI escape sequences */
+/* s must be able to store 14 chars (including final \0) */
+#ifdef READLINE
+static void
+readline_prompt_color(char *s, int c)
+{
+  *s++ = '\001'; /*RL_PROMPT_START_IGNORE*/
+  term_get_color(s, c);
+  s += strlen(s);
+  *s++ = '\002'; /*RL_PROMPT_END_IGNORE*/
+  *s = 0;
+}
+#endif
+/* s must be able to store 14 chars (including final \0) */
 static void
 brace_color(char *s, int c, int force)
 {
@@ -1384,42 +1010,36 @@ brace_color(char *s, int c, int force)
     term_get_color(s, c);
 }
 
-static void
-color_prompt(char *buf, const char *prompt)
+/* strlen(prompt) + 28 chars */
+static const char *
+color_prompt(const char *prompt)
 {
-  char *s = buf;
+  long n = strlen(prompt);
+  char *t = stack_malloc(n + 28), *s = t;
   *s = 0;
   /* escape sequences bug readline, so use special bracing (if available) */
   brace_color(s, c_PROMPT, 0);
-  s += strlen(s); strcpy(s, prompt);
-  s += strlen(s);
+  s += strlen(s); strncpy(s, prompt, n);
+  s += n; *s = 0;
   brace_color(s, c_INPUT, 1);
+  return t;
 }
 #else
-static void
-color_prompt(char *buf, const char *prompt) { strcpy(buf,prompt); }
-#endif
-
 static const char *
-expand_prompt(char *buf, const char *prompt, filtre_t *F)
-{
-  if (F && F->in_comment) return COMMENTPROMPT;
-  strftime_expand(prompt, buf, MAX_PROMPT_LEN-1);
-  return buf;
-}
+color_prompt(const char *prompt) { return stack_strdup(prompt); }
+#endif
 
 const char *
-do_prompt(char *buf, const char *prompt, filtre_t *F)
+gp_format_prompt(const char *prompt)
 {
   if (GP_DATA->flags & gpd_TEST)
-    strcpy(buf, prompt);
+    return prompt;
   else
   {
-    char b[MAX_PROMPT_LEN];
-    const char *s = expand_prompt(b, prompt, F);
-    color_prompt(buf, s);
+    char b[256]; /* longer is truncated */
+    strftime_expand(prompt, b, sizeof(b));
+    return color_prompt(b);
   }
-  return buf;
 }
 
 /********************************************************************/
@@ -1429,10 +1049,7 @@ do_prompt(char *buf, const char *prompt, filtre_t *F)
 /********************************************************************/
 static int
 is_interactive(void)
-{
-  ulong f = GP_DATA->flags&(gpd_TEXMACS|gpd_TEST);
-  return pari_infile == stdin && !f && gp_is_interactive;
-}
+{ return cb_pari_is_interactive? cb_pari_is_interactive(): 0; }
 
 static const char esc = (0x1f & '['); /* C-[ = escape */
 static char *
@@ -1462,7 +1079,6 @@ update_logfile(const char *prompt, const char *s)
   pari_sp av;
   const char *p;
   if (!pari_logfile) return;
-  if (!is_interactive() && !GP_DATA->echo) return;
   av = avma;
   p = strip_prompt(prompt); /* raw prompt */
 
@@ -1485,9 +1101,11 @@ update_logfile(const char *prompt, const char *s)
 }
 
 void
-echo_and_log(const char *prompt, const char *s)
+gp_echo_and_log(const char *prompt, const char *s)
 {
-  if (GP_DATA->echo && !is_interactive()) {
+  if (!is_interactive())
+  {
+    if (!GP_DATA->echo) return;
     /* not pari_puts(): would duplicate in logfile */
     fputs(prompt, pari_outfile);
     fputs(s,      pari_outfile);
@@ -1499,70 +1117,67 @@ echo_and_log(const char *prompt, const char *s)
 }
 
 /* prompt = NULL --> from gprc. Return 1 if new input, and 0 if EOF */
-static int
+int
 get_line_from_file(const char *prompt, filtre_t *F, FILE *file)
 {
-  const int Texmacs_stdin = ((GP_DATA->flags & gpd_TEXMACS) && file == stdin);
   char *s;
   input_method IM;
 
   IM.file = file;
-  IM.fgets= Texmacs_stdin? &fgets_texmacs: &fgets;
+  IM.fgets= (file==stdin && cb_pari_fgets_interactive)? cb_pari_fgets_interactive: &fgets;
   IM.getline = &file_input;
   IM.free = 0;
   if (! input_loop(F,&IM))
   {
-    if (Texmacs_stdin) tm_start_output();
+    if (file==stdin && cb_pari_start_output) cb_pari_start_output();
     return 0;
   }
-
-  s = ((Buffer*)F->buf)->buf;
+  s = F->buf->buf;
   /* don't log if from gprc or empty input */
-  if (*s && prompt) echo_and_log(prompt, s);
-  if (GP_DATA->flags & gpd_TEXMACS)
-  {
-    tm_did_complete = 0;
-    if (Texmacs_stdin && *s == DATA_BEGIN)
-    { handle_texmacs_command(s); *s = 0; }
-    else
-      tm_start_output();
-  }
+  if (*s && prompt) gp_echo_and_log(prompt, s);
   return 1;
 }
 
 /* return 0 if no line could be read (EOF). If PROMPT = NULL, expand and
  * color default prompt; otherwise, use PROMPT as-is. */
-static int
+int
 gp_read_line(filtre_t *F, const char *PROMPT)
 {
+  static const char *DFT_PROMPT = "? ";
   Buffer *b = (Buffer*)F->buf;
-  char buf[MAX_PROMPT_LEN + 24];
   const char *p;
   int res, interactive;
-  F->downcase = (compatible == OLDALL);
   if (b->len > 100000) fix_buffer(b, 100000);
   interactive = is_interactive();
   if (interactive || pari_logfile || GP_DATA->echo)
-    p = PROMPT? PROMPT: do_prompt(buf, Prompt, F);
+  {
+    p = PROMPT;
+    if (!p) {
+      p = F->in_comment? GP_DATA->prompt_comment: GP_DATA->prompt;
+      p = gp_format_prompt(p);
+    }
+  }
   else
     p = DFT_PROMPT;
 
   if (interactive)
   {
     BLOCK_EH_START
-#ifdef READLINE
-    if (GP_DATA->use_readline)
-      res = get_line_from_readline(p, Prompt_cont, F);
-    else
-#endif
-    {
+    if (cb_pari_get_line_interactive)
+      res = cb_pari_get_line_interactive(p, GP_DATA->prompt_cont, F);
+    else {
       pari_puts(p); pari_flush();
       res = get_line_from_file(p, F, pari_infile);
     }
     BLOCK_EH_END
   }
   else
-    res = get_line_from_file(p, F, pari_infile);
+  { /* in case UI fakes non-interactivity, e.g. TeXmacs */
+    if (cb_pari_start_output && cb_pari_get_line_interactive)
+      res = cb_pari_get_line_interactive(p, GP_DATA->prompt_cont, F);
+    else
+      res = get_line_from_file(p, F, pari_infile);
+  }
 
   if (!disable_color && p != DFT_PROMPT &&
       (gp_colors[c_PROMPT] != c_NONE || gp_colors[c_INPUT] != c_NONE))
@@ -1572,269 +1187,46 @@ gp_read_line(filtre_t *F, const char *PROMPT)
   return res;
 }
 
-static int
-is_silent(char *s) { return s[strlen(s) - 1] == ';'; }
-
-static void
-reset_ctrlc(void)
-{
-#if defined(_WIN32) || defined(__CYGWIN32__)
-  win32ctrlc = 0;
-#endif
-}
-
-enum { gp_ISMAIN = 1, gp_RECOVER = 2 };
-
-static GEN
-gp_main_loop(long flag)
-{
-  VOLATILE const long dorecover = flag & gp_RECOVER;
-  VOLATILE const long ismain    = flag & gp_ISMAIN;
-  VOLATILE GEN z = gnil;
-  VOLATILE long t = 0;
-  VOLATILE pari_sp av = avma;
-  filtre_t F;
-  Buffer *b = filtered_buffer(&F);
-  struct gp_context rec;
-
-  if (dorecover) /* set recovery point */
-  {
-    long er;
-    if ((er = setjmp(env[s_env.n-1])))
-    { /* recover: jump from error [ > 0 ] or allocatemem [ -1 ] */
-      if (er > 0) { /* true error */
-        if (!(GP_DATA->recover)) exit(1);
-        gp_context_restore(&rec);
-        /* true error not from main instance, let caller sort it out */
-        if (!ismain) { kill_buffers_upto_including(b); return NULL; }
-      } else { /* allocatemem */
-        filestate_restore(rec.file);
-        gp_context_save(&rec);
-      }
-      avma = av = top;
-      kill_buffers_upto(b);
-      alarm0(0);
-    }
-  }
-  for(;;)
-  {
-    if (dorecover) gp_context_save(&rec);
-    if (! gp_read_line(&F, NULL))
-    {
-      if (popinfile()) gp_quit(0);
-      if (ismain) continue;
-      pop_buffer(); return z;
-    }
-    if (check_meta(b->buf, ismain)) continue;
-
-    avma = av;
-    if (ismain)
-    {
-      reset_ctrlc();
-      timer_start(GP_DATA->T);
-      pari_set_last_newline(1);
-    }
-    z = closure_evalres(pari_compile_str(b->buf, GP_DATA->strictmatch));
-    if (! ismain) continue;
-    alarm0(0);
-
-    if (!pari_last_was_newline()) pari_putc('\n');
-
-    t = timer_delay(GP_DATA->T);
-    if (t && GP_DATA->chrono)
-    {
-      pari_puts("time = ");
-      pari_puts(gp_format_time(t));
-    }
-    if (GP_DATA->simplify) z = simplify_shallow(z);
-    pari_add_hist(z, t);
-    if (z != gnil && ! is_silent(b->buf) ) gp_output(z, GP_DATA);
-  }
-}
-
 /********************************************************************/
 /*                                                                  */
 /*                      EXCEPTION HANDLER                           */
 /*                                                                  */
 /********************************************************************/
-static void
-gp_sigint_fun(void) {
-  char buf[64];
-  if (GP_DATA->flags & gpd_TEXMACS) tm_start_output();
-  convert_time(buf, timer_get(GP_DATA->T));
-  pari_sigint(buf);
-}
-
-#if defined(SIGALRM) || defined(HAS_ALARM)
 static THREAD pari_timer ti_alarm;
-#endif
-#ifdef SIGALRM
+
+#if defined(_WIN32) || defined(SIGALRM)
 static void
 gp_alarm_fun(void) {
   char buf[64];
-  if (GP_DATA->flags & gpd_TEXMACS) tm_start_output();
+  if (cb_pari_start_output) cb_pari_start_output();
   convert_time(buf, timer_get(&ti_alarm));
   pari_err(e_ALARM, buf);
 }
 #endif /* SIGALRM */
 
-static const char *
-break_loop_prompt(char *buf, long n)
-{
-  char s[128];
-  if (n == 1)
-    strcpy(s, "break> ");
-  else
-    sprintf(s, "break[%ld]> ", n);
-  return do_prompt(buf, s, NULL);
-}
-
-static long frame_level=0, dbg_level = 0;
-
-static int
-break_loop(int numerr)
-{
-  filtre_t F;
-  Buffer *b;
-  int sigint = numerr<0, go_on = sigint;
-  struct gp_context rec;
-  const char *prompt, *msg;
-  char promptbuf[MAX_PROMPT_LEN + 24];
-  long nenv, oldframe_level = frame_level;
-  pari_sp av;
-
-  if (numerr == e_SYNTAX) return 0;
-  if (numerr == e_STACK) { evalstate_clone(); avma = top; }
-
-  b = filtered_buffer(&F);
-  nenv=pari_stack_new(&s_env);
-  gp_context_save(&rec);
-  iferr_env = NULL;
-  dbg_level = 0;
-  frame_level = closure_context(oldframe_level, dbg_level);
-  pari_infile = newfile(stdin, "stdin", mf_IN)->file;
-  term_color(c_ERR); pari_putc('\n');
-  if (sigint)
-    msg = "Break loop: <Return> to continue; 'break' to go back to GP prompt";
-  else
-    msg = "Break loop: type 'break' to go back to GP prompt";
-  print_errcontext(pariOut, msg, NULL, NULL);
-  term_color(c_NONE);
-  prompt = break_loop_prompt(promptbuf, s_env.n-1);
-  av = avma;
-  for(;;)
-  {
-    GEN x;
-    long er, br_status;
-    avma = av;
-    if ((er=setjmp(env[nenv])))
-    {
-      if (er < 0)
-      {
-        s_env.n = 1;
-        frame_level = oldframe_level;
-        longjmp(env[s_env.n-1], er);
-      }
-      gp_context_restore(&rec);
-      iferr_env = NULL;
-      closure_err(dbg_level);
-      (void) closure_context(oldframe_level, dbg_level);
-      pari_infile = newfile(stdin, "stdin", mf_IN)->file;
-    }
-    term_color(c_NONE);
-    if (!gp_read_line(&F, prompt))
-      br_status = br_BREAK; /* EOF */
-    else
-    {
-      /* Empty input ? Continue if entry on sigint (exit debugger frame) */
-      if (! *(b->buf) && sigint) break;
-      reset_ctrlc();
-      if (check_meta(b->buf, 0)) continue;
-      x = closure_evalbrk(pari_compile_str(b->buf,0), &br_status);
-    }
-    switch (br_status)
-    {
-      case br_NEXT: case br_MULTINEXT:
-        popinfile(); /* exit frame. Don't exit debugger if s_env.n > 2 */
-        go_on = 0; goto BR_EXIT;
-      case br_BREAK: case br_RETURN:
-        killallfiles(); /* completely exit the debugger */
-        go_on = 0; goto BR_EXIT;
-    }
-
-    if (x != gnil && !is_silent(b->buf))
-    {
-      term_color(c_OUTPUT);
-      gen_output(x, GP_DATA->fmt);
-      pari_putc('\n');
-    }
-  }
-BR_EXIT:
-  s_env.n=nenv;
-  frame_level = oldframe_level;
-  gp_context_restore(&rec);
-  pop_buffer(); return go_on;
-}
-
-/* numerr < 0: from SIGINT */
-static void
-gp_pre_recover(long numerr)
-{
-  if (numerr>=0)
-  {
-    out_puts(pariErr, "\n"); pariErr->flush();
-  }
-  longjmp(env[s_env.n-1], numerr);
-}
-
-/* numerr < 0: from SIGINT */
-static void
-gp_err_recover(long numerr)
-{
-  longjmp(env[s_env.n-1], numerr);
-}
-
 void
-dbg_up(long k)
-{
-  if (k<0) k=0;
-  dbg_level += k;
-  if (dbg_level>frame_level) dbg_level=frame_level;
-  gp_err_recover(e_NONE);
-}
-
-void
-dbg_down(long k)
-{
-  if (k<0) k=0;
-  dbg_level -= k;
-  if (dbg_level<0) dbg_level=0;
-  gp_err_recover(e_NONE);
-}
-
-GEN
-dbg_err(void) { GEN E = pari_err_last(); return E? gcopy(E):gnil; }
-
-void
-pari_breakpoint(void)
-{
-  if (!pari_last_was_newline()) pari_putc('\n');
-  closure_err(0);
-  if (break_loop(-1)) return;
-  gp_err_recover(e_MISC);
+gp_sigint_fun(void) {
+  char buf[64];
+#if defined(_WIN32)
+  if (win32alrm) { win32alrm = 0; gp_alarm_fun(); return;}
+#endif
+  if (cb_pari_start_output) cb_pari_start_output();
+  convert_time(buf, timer_get(GP_DATA->T));
+  pari_sigint(buf);
 }
 
-/* numerr < 0: from SIGINT */
-static int
-gp_handle_exception(long numerr)
+const char *
+break_loop_prompt(long n)
 {
-  if (disable_exception_handler) disable_exception_handler = 0;
-  else if ((GP_DATA->breakloop) && break_loop(numerr)) return 1;
-  return 0;
+  char *s;
+  if (n == 1) return gp_format_prompt("break> ");
+  s = stack_malloc(32);
+  sprintf(s, "break[%ld]> ", n);
+  return gp_format_prompt(s);
 }
 
 #ifdef SIGALRM
-static void
+void
 gp_alarm_handler(int sig)
 {
 #ifndef HAS_SIGACTION
@@ -1852,139 +1244,63 @@ gp_alarm_handler(int sig)
 /*                      GP-SPECIFIC ROUTINES                        */
 /*                                                                  */
 /********************************************************************/
-static void
-check_secure(const char *s)
-{
-  if (GP_DATA->secure)
-    pari_err(e_MISC, "[secure mode]: system commands not allowed\nTried to run '%s'",s);
-}
-
-GEN
-read0(const char *s)
-{
-  switchin(s);
-  if (file_is_binary(pari_infile)) return gpreadbin(s, NULL);
-  return gp_main_loop(0);
-}
-/* as read0 but without a main instance of gp running */
-static void
-read_main(const char *s)
+void
+gp_allocatemem(GEN z)
 {
-  GEN z;
-  if (setjmp(env[s_env.n-1]))
-    z = NULL;
+  ulong newsize;
+  if (!z) newsize = 0;
   else {
-    switchin(s);
-    if (file_is_binary(pari_infile)) {
-      z = readbin(s,pari_infile, NULL);
-      popinfile();
-    }
-    else z = gp_main_loop(gp_RECOVER);
+    if (typ(z) != t_INT) pari_err_TYPE("allocatemem",z);
+    newsize = itou(z);
+    if (signe(z) < 0) pari_err_DOMAIN("allocatemem","size","<",gen_0,z);
   }
-  if (!z) err_printf("... skipping file '%s'\n", s);
-  avma = top;
-}
-
-static GEN
-get_lines(FILE *F)
-{
-  pari_sp av = avma;
-  long i, nz = 16;
-  GEN z = cgetg(nz + 1, t_VEC);
-  Buffer *b = new_buffer();
-  input_method IM;
-  IM.fgets = &fgets;
-  IM.file = F;
-  for(i = 1;;)
-  {
-    char *s = b->buf, *e;
-    if (!file_getline(b, &s, &IM)) break;
-    if (i > nz) { nz <<= 1; z = vec_lengthen(z, nz); }
-    e = s + strlen(s)-1;
-    if (*e == '\n') *e = 0;
-    gel(z,i++) = strtoGENstr(s);
-  }
-  delete_buffer(b); setlg(z, i);
-  return gerepilecopy(av, z);
-}
-
-GEN
-externstr(const char *s)
-{
-  pariFILE *F;
-  GEN z;
-  check_secure(s);
-  F = try_pipe(s, mf_IN);
-  z = get_lines(F->file);
-  pari_fclose(F); return z;
-}
-GEN
-readstr(const char *s)
-{
-  GEN z = get_lines(switchin(s));
-  popinfile(); return z;
-}
-
-GEN
-extern0(const char *s)
-{
-  check_secure(s);
-  pari_infile = try_pipe(s, mf_IN)->file;
-  return gp_main_loop(0);
+  if (pari_mainstack->vsize)
+    paristack_resize(newsize);
+  else
+    paristack_newrsize(newsize);
 }
 
 GEN
-input0(void)
+gp_input(void)
 {
   filtre_t F;
   Buffer *b = filtered_buffer(&F);
   GEN x;
 
-  while (! get_line_from_file(DFT_INPROMPT,&F,pari_infile))
-    if (popinfile()) { err_printf("no input ???"); gp_quit(1); }
+  while (! get_line_from_file("",&F,pari_infile))
+    if (popinfile()) { err_printf("no input ???"); cb_pari_quit(1); }
   x = readseq(b->buf);
   pop_buffer(); return x;
 }
 
-void
-system0(const char *s)
-{
-/*FIXME: HAS_SYSTEM */
-#if defined(UNIX) || defined(__EMX__) || defined(_WIN32)
-  check_secure(s);
-  if (system(s) < 0)
-    pari_err(e_MISC, "system(\"%s\") failed", s);
-#else
-  pari_err(e_ARCH,"system");
-#endif
-}
-
 static GEN
 closure_alarmer(GEN C, long s)
 {
   struct pari_evalstate state;
   VOLATILE GEN x;
-  if (!s) { alarm0(0); return closure_evalgen(C); }
+  if (!s) { pari_alarm(0); return closure_evalgen(C); }
   evalstate_save(&state);
-#ifndef HAS_ALARM
+#if !defined(HAS_ALARM) && !defined(_WIN32)
   pari_err(e_ARCH,"alarm");
 #endif
   pari_CATCH(CATCH_ALL) /* We need to stop the timer after any error */
   {
     GEN E = pari_err_last();
-    if (err_get_num(E) != e_ALARM) { alarm0(0); pari_err(0, E); }
+    if (err_get_num(E) != e_ALARM) { pari_alarm(0); pari_err(0, E); }
     x = evalstate_restore_err(&state);
   }
-  pari_TRY { alarm0(s); x = closure_evalgen(C); alarm0(0); } pari_ENDCATCH;
+  pari_TRY { pari_alarm(s); x = closure_evalgen(C); pari_alarm(0); } pari_ENDCATCH;
   return x;
 }
 
 void
-alarm0(long s)
+pari_alarm(long s)
 {
   if (s < 0) pari_err_DOMAIN("alarm","delay","<",gen_0,stoi(s));
-#ifdef HAS_ALARM
   if (s) timer_start(&ti_alarm);
+#ifdef _WIN32
+  win32_alarm(s);
+#elif defined(HAS_ALARM)
   alarm(s);
 #else
   if (s) pari_err(e_ARCH,"alarm");
@@ -1994,270 +1310,15 @@ alarm0(long s)
 GEN
 gp_alarm(long s, GEN code)
 {
-  if (!code) { alarm0(s); return gnil; }
+  if (!code) { pari_alarm(s); return gnil; }
   return closure_alarmer(code,s);
 }
 
 /*******************************************************************/
 /**                                                               **/
-/**                        INITIALIZATION                         **/
-/**                                                               **/
-/*******************************************************************/
-static char *
-read_arg(long *nread, char *t, long argc, char **argv)
-{
-  long i = *nread;
-  if (isdigit((int)*t)) return t;
-  if (*t || i==argc) usage(argv[0]);
-  *nread = i+1; return argv[i];
-}
-
-static char *
-read_arg_equal(long *nread, char *t, long argc, char **argv)
-{
-  long i = *nread;
-  if (*t=='=' && isdigit((int)t[1])) return t+1;
-  if (*t || i==argc) usage(argv[0]);
-  *nread = i+1; return argv[i];
-}
-
-static void
-init_trivial_stack(void)
-{
-  const size_t s = 2048;
-  bot = (pari_sp)pari_malloc(s);
-  avma = top = bot + s;
-}
-
-typedef struct { char *key, *val; } pair_t;
-/* If ab of the form key=val, record pair in new stack entry
- * P[n].key must be freed by caller to avoid memory leak */
-static void
-record_default(pari_stack *s_P, char *ab)
-{
-  pair_t *P = (pair_t*)*pari_stack_base(s_P);
-  char *k, *v;
-  long n;
-  ab = pari_strdup(ab);
-  parse_key_val(ab, &k, &v);
-  n = pari_stack_new(s_P);
-  P[n].key = k;
-  P[n].val = v;
-}
-static void
-read_opt(pari_stack *p_A, long argc, char **argv)
-{
-  pair_t *P;
-  pari_stack s_P; /* key / value to record default() settings */
-  char *b = NULL, *p = NULL, *s = NULL;
-  ulong f = GP_DATA->flags;
-  long i = 1, initrc = 1;
-
-  (void)&p; (void)&b; (void)&s; /* -Wall gcc-2.95 */
-
-  pari_stack_init(&s_P,sizeof(*P),(void**)&P);
-  pari_stack_alloc(&s_P, 64);
-  pari_outfile = stderr;
-  while (i < argc)
-  {
-    char *t = argv[i];
-
-    if (*t++ != '-') break;
-    i++;
-START:
-    switch(*t++)
-    {
-      case 'p': p = read_arg(&i,t,argc,argv); break;
-      case 's': s = read_arg(&i,t,argc,argv); break;
-      case 'e':
-        f |= gpd_EMACS; if (*t) goto START;
-        break;
-      case 'q':
-        f |= gpd_QUIET; if (*t) goto START;
-        break;
-      case 't':
-        f |= gpd_TEST; if (*t) goto START;
-        break;
-      case 'f':
-        initrc = 0; if (*t) goto START;
-        break;
-      case 'D':
-        if (*t || i == argc) usage(argv[0]);
-        record_default(&s_P, argv[i++]);
-        break;
-      case '-':
-        if (strcmp(t, "version-short") == 0) { print_shortversion(); exit(0); }
-        if (strcmp(t, "version") == 0) {
-          init_trivial_stack(); print_version();
-          pari_free((void*)bot); exit(0);
-        }
-        if (strcmp(t, "default") == 0) {
-          if (i == argc) usage(argv[0]);
-          record_default(&s_P, argv[i++]);
-          break;
-        }
-        if (strcmp(t, "texmacs") == 0) { f |= gpd_TEXMACS; break; }
-        if (strcmp(t, "emacs") == 0) { f |= gpd_EMACS; break; }
-        if (strcmp(t, "test") == 0) { f |= gpd_TEST; break; }
-        if (strcmp(t, "quiet") == 0) { f |= gpd_QUIET; break; }
-        if (strcmp(t, "fast") == 0) { initrc = 0; break; }
-        if (strncmp(t, "primelimit",10) == 0) {p = read_arg_equal(&i,t+10,argc,argv); break; }
-        if (strncmp(t, "stacksize",9) == 0) {s = read_arg_equal(&i,t+9,argc,argv); break; }
-       /* fall through */
-      default:
-        usage(argv[0]);
-    }
-  }
-#ifdef READLINE
-  GP_DATA->use_readline = gp_is_interactive;
-#else
-  GP_DATA->use_readline = 0;
-#endif
-  if (!gp_is_interactive && !(GP_DATA->flags & gpd_EMACS))
-    GP_DATA->breakloop = 0;
-  if (f & gpd_TEXMACS) tm_start_output();
-  GP_DATA->flags = f;
-  if (f & gpd_TEST) {
-    GP_DATA->breakloop = 0;
-    init_linewrap(76);
-  } else if (initrc)
-    gp_initrc(p_A);
-  for ( ; i < argc; i++) pari_stack_pushp(p_A, pari_strdup(argv[i]));
-
-  /* override the values from gprc */
-  if (p) (void)sd_primelimit(p, d_INITRC);
-  if (s) (void)sd_parisize(s, d_INITRC);
-  for (i = 0; i < s_P.n; i++) {
-    setdefault(P[i].key, P[i].val, d_INITRC);
-    free((void*)P[i].key);
-  }
-  pari_stack_delete(&s_P);
-
-  if (GP_DATA->flags & (gpd_EMACS|gpd_TEXMACS|gpd_TEST)) disable_color = 1;
-  pari_outfile = stdout;
-}
-
-#ifdef __CYGWIN32__
-void
-cyg_environment(int argc, char ** argv)
-{
-  char *ti_dirs = getenv("TERMINFO_DIRS");
-  char *argv0, *p;
-  char *newdir;
-  long n;
-
-  if (!argc || !argv) return;
-  argv0 = *argv;
-  if (!argv0 || !*argv0) return;
-  p = strrchr(argv0, '/');
-  if (!p)
-    p = argv0 = "";
-  else
-    p++;
-  n = p - argv0;
-  if (ti_dirs)
-  {
-    n += 14 + strlen(ti_dirs) + 1 + 8 + 1;
-    newdir = malloc(n);
-    if (!newdir) return;
-    snprintf(newdir, n-8, "TERMINFO_DIRS=%s:%s", ti_dirs, argv0);
-  }
-  else
-  {
-    n += 14 + 8 + 1;
-    newdir = malloc(n);
-    if (!newdir) return;
-    snprintf(newdir, n-8, "TERMINFO_DIRS=%s", argv0);
-  }
-  strcpy(newdir+n-9,"terminfo");
-  putenv(newdir);
-}
-#endif
-
-#ifndef WINCE
-int
-main(int argc, char **argv)
-{
-#else
-int
-WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
-        LPWSTR lpCmdLine, int nShowCmd)
-{
-  char **argv = NULL;
-  int argc = 1;
-#endif
-  void **A;
-  pari_stack s_A;
-
-  GP_DATA = default_gp_data();
-  pari_stack_init(&s_env, sizeof(*env), (void**)&env);
-  (void)pari_stack_new(&s_env);
-
-  if (setjmp(env[s_env.n-1]))
-  {
-    puts("### Errors on startup, exiting...\n\n");
-    exit(1);
-  }
-#ifdef __CYGWIN32__
-  cyg_environment(argc, argv);
-#endif
-  gp_is_interactive = pari_stdin_isatty();
-  pari_init_defaults();
-  pari_library_path = DL_DFLT_NAME;
-  pari_stack_init(&s_A,sizeof(*A),(void**)&A);
-  pari_stack_init(&s_bufstack, sizeof(Buffer*), (void**)&bufstack);
-  cb_pari_err_recover = gp_err_recover;
-  pari_init_opts(1000000 * sizeof(long), 0, INIT_SIGm | INIT_noPRIMEm);
-  cb_pari_pre_recover = gp_pre_recover;
-  pari_add_defaults_module(functions_gp_default);
-  (void)sd_graphcolormap("[\"white\",\"black\",\"blue\",\"violetred\",\"red\",\"green\",\"grey\",\"gainsboro\"]", d_SILENT);
-  (void)sd_graphcolors("[4, 5]", d_SILENT);
-  strcpy(Prompt,      DFT_PROMPT);
-  strcpy(Prompt_cont, CONTPROMPT);
-  Help = init_help();
-
-  read_opt(&s_A, argc,argv);
-  initprimetable(GP_DATA->primelimit);
-#ifdef SIGALRM
-  (void)os_signal(SIGALRM,gp_alarm_handler);
-#endif
-  pari_add_module(functions_gp);
-  pari_add_module(functions_highlevel);
-  pari_add_oldmodule(functions_oldgp);
-
-  init_graph();
-#ifdef READLINE
-  init_readline();
-#endif
-  cb_pari_whatnow = whatnow;
-  cb_pari_sigint = gp_sigint_fun;
-  cb_pari_handle_exception = gp_handle_exception;
-  cb_pari_ask_confirm = gp_ask_confirm;
-  gp_expand_path(GP_DATA->path);
-
-  timer_start(GP_DATA->T);
-  if (!(GP_DATA->flags & gpd_QUIET)) gp_head();
-  if (s_A.n)
-  {
-    FILE *l = pari_logfile;
-    long i;
-    pari_logfile = NULL;
-    for (i = 0; i < s_A.n; pari_free(A[i]),i++) read_main((char*)A[i]);
-    /* Reading one of the input files above can set pari_logfile.
-     * Don't restore in that case. */
-    if (!pari_logfile) pari_logfile = l;
-  }
-  pari_stack_delete(&s_A);
-  (void)gp_main_loop(gp_RECOVER|gp_ISMAIN);
-  gp_quit(0); return 0; /* not reached */
-}
-
-/*******************************************************************/
-/**                                                               **/
-/**                          GP OUTPUT                            **/
+/**                    EXTERNAL PRETTYPRINTER                     **/
 /**                                                               **/
 /*******************************************************************/
-    /* EXTERNAL PRETTYPRINTER */
 /* Wait for prettinprinter to finish, to prevent new prompt from overwriting
  * the output.  Fill the output buffer, wait until it is read.
  * Better than sleep(2): give possibility to print */
@@ -2287,7 +1348,7 @@ prettyp_init(void)
 }
 
 /* n = history number. if n = 0 no history */
-static int
+int
 tex2mail_output(GEN z, long n)
 {
   pariout_t T = *(GP_DATA->fmt); /* copy */
@@ -2344,61 +1405,7 @@ tex2mail_output(GEN z, long n)
     fputc('\n', log); fflush(log);
   }
   if (n) term_color(c_NONE);
-  return 1;
-}
-
-    /* TEXMACS */
-static void
-texmacs_output(GEN z, long n)
-{
-  char *sz = GENtoTeXstr(z);
-  printf("%clatex:", DATA_BEGIN);
-  if (n) printf("\\magenta\\%%%ld = ", n);
-  printf("$\\blue %s$%c", sz,DATA_END);
-  pari_free(sz); fflush(stdout);
-}
-
-    /* REGULAR */
-static void
-normal_output(GEN z, long n)
-{
-  long l = 0;
-  char *s;
-  /* history number */
-  if (n)
-  {
-    char buf[64];
-    if (!(GP_DATA->flags & gpd_QUIET))
-    {
-      term_color(c_HIST);
-      sprintf(buf, "%%%ld = ", n);
-      pari_puts(buf);
-      l = strlen(buf);
-    }
-  }
-  /* output */
-  term_color(c_OUTPUT);
-  s = GENtostr(z);
-  if (GP_DATA->lim_lines)
-    lim_lines_output(s, l, GP_DATA->lim_lines);
-  else
-    pari_puts(s);
-  pari_free(s);
-  term_color(c_NONE); pari_putc('\n');
-}
-
-void
-gp_output(GEN z, gp_data *G)
-{
-  if (G->flags & gpd_TEST) {
-    init_linewrap(76);
-    gen_output(z, G->fmt); pari_putc('\n');
-  }
-  else if (G->flags & gpd_TEXMACS)
-    texmacs_output(z, G->hist->total);
-  else if (G->fmt->prettyp != f_PRETTY || !tex2mail_output(z, G->hist->total))
-    normal_output(z, G->hist->total);
-  pari_flush();
+  pari_flush(); return 1;
 }
 
 /*******************************************************************/
@@ -2424,7 +1431,7 @@ sd_graphcolormap(const char *v, long flag)
 
   if (v)
   {
-    char *t = filtre(v, 0);
+    char *t = gp_filter(v);
     if (*t != '[' || t[strlen(t)-1] != ']')
       pari_err(e_SYNTAX, "incorrect value for graphcolormap", t, t);
     for (s = 0, p = t+1, l = 2, a=0; *p; p++)
@@ -2446,14 +1453,14 @@ sd_graphcolormap(const char *v, long flag)
         l++;
     if (l < 4)
       pari_err(e_MISC, "too few colors (< 4) in graphcolormap");
-    if (pari_colormap) pari_free(pari_colormap);
-    pari_colormap = (GEN)pari_malloc((l+4*a)*sizeof(long) + s);
-    pari_colormap[0] = evaltyp(t_VEC)|evallg(l);
-    for (p = t+1, i = 1, lp = pari_colormap+l; i < l; p++)
+    if (GP_DATA->colormap) pari_free(GP_DATA->colormap);
+    GP_DATA->colormap = (GEN)pari_malloc((l+4*a)*sizeof(long) + s);
+    GP_DATA->colormap[0] = evaltyp(t_VEC)|evallg(l);
+    for (p = t+1, i = 1, lp = GP_DATA->colormap+l; i < l; p++)
       switch(*p)
       {
       case '"':
-        gel(pari_colormap, i) = lp;
+        gel(GP_DATA->colormap, i) = lp;
         q = ++p; while (*q != '"') q++;
         *q = 0;
         j = 1 + nchar2nlong(q-p+1);
@@ -2463,7 +1470,7 @@ sd_graphcolormap(const char *v, long flag)
         break;
       case '[': {
         const char *ap[3];
-        gel(pari_colormap, i) = lp;
+        gel(GP_DATA->colormap, i) = lp;
         lp[0] = evaltyp(t_VECSMALL)|_evallg(4);
         for (ap[0] = ++p, j=0; *p && *p != ']'; p++)
           if (*p == ',' && j<2) { *p++ = 0; ap[++j] = p; }
@@ -2492,12 +1499,12 @@ sd_graphcolormap(const char *v, long flag)
   }
   if (flag == d_RETURN || flag == d_ACKNOWLEDGE)
   {
-    GEN cols = cgetg(lg(pari_colormap), t_VEC);
+    GEN cols = cgetg(lg(GP_DATA->colormap), t_VEC);
     long i;
 
     for (i = 1; i < lg(cols); i++)
     {
-      GEN c = gel(pari_colormap, i);
+      GEN c = gel(GP_DATA->colormap, i);
       if (typ(c) == t_STR)
         gel(cols, i) = gcopy(c);
       else
@@ -2516,14 +1523,14 @@ sd_graphcolors(const char *v, long flag)
   char *p;
 
   if (v) {
-    char *t = filtre(v, 0);
+    char *t = gp_filter(v);
     for (p = t+1, l=2; *p != ']'; p++)
       if (*p == ',') l++;
       else if (*p < '0' || *p > '9')
         pari_err(e_SYNTAX, "incorrect value for graphcolors", p, t);
     if (*++p) pari_err(e_SYNTAX, "incorrect value for graphcolors", p, t);
-    if (pari_graphcolors) pari_free(pari_graphcolors);
-    pari_graphcolors = cgetalloc(t_VECSMALL, l);
+    if (GP_DATA->graphcolors) pari_free(GP_DATA->graphcolors);
+    GP_DATA->graphcolors = cgetalloc(t_VECSMALL, l);
     for (p = t+1, i=0; *p; p++)
     {
       long n = 0;
@@ -2533,16 +1540,16 @@ sd_graphcolors(const char *v, long flag)
         n += *p-'0';
         p++;
       }
-      pari_graphcolors[++i] = n;
+      GP_DATA->graphcolors[++i] = n;
     }
     pari_free(t);
   }
   switch(flag)
   {
   case d_RETURN:
-    return vecsmall_to_vec(pari_graphcolors);
+    return vecsmall_to_vec(GP_DATA->graphcolors);
   case d_ACKNOWLEDGE:
-    pari_printf("   graphcolors = %Ps\n", vecsmall_to_vec(pari_graphcolors));
+    pari_printf("   graphcolors = %Ps\n", vecsmall_to_vec(GP_DATA->graphcolors));
   }
   return gnil;
 }
@@ -2555,14 +1562,14 @@ sd_help(const char *v, long flag)
   {
     if (GP_DATA->secure)
       pari_err(e_MISC,"[secure mode]: can't modify 'help' default (to %s)",v);
-    if (Help) pari_free((void*)Help);
+    if (GP_DATA->help) pari_free((void*)GP_DATA->help);
 #ifndef _WIN32
-    Help = path_expand(v);
+    GP_DATA->help = path_expand(v);
 #else
-    Help = strdup(v);
+    GP_DATA->help = pari_strdup(v);
 #endif
   }
-  str = Help? Help: "none";
+  str = GP_DATA->help? GP_DATA->help: "none";
   if (flag == d_RETURN) return strtoGENstr(str);
   if (flag == d_ACKNOWLEDGE)
     pari_printf("   help = \"%s\"\n", str);
@@ -2570,20 +1577,23 @@ sd_help(const char *v, long flag)
 }
 
 static GEN
-sd_prompt_set(const char *v, long flag, const char *how, char *p)
+sd_prompt_set(const char *v, long flag, const char *how, char **p)
 {
-  if (v) strncpy(p,v,MAX_PROMPT_LEN);
-  if (flag == d_RETURN) return strtoGENstr(p);
+  if (v) {
+    if (*p) free(*p);
+    *p = pari_strdup(v);
+  }
+  if (flag == d_RETURN) return strtoGENstr(*p);
   if (flag == d_ACKNOWLEDGE)
-    pari_printf("   prompt%s = \"%s\"\n", how, p);
+    pari_printf("   prompt%s = \"%s\"\n", how, *p);
   return gnil;
 }
 GEN
 sd_prompt(const char *v, long flag)
-{ return sd_prompt_set(v, flag, "", Prompt); }
+{ return sd_prompt_set(v, flag, "", &(GP_DATA->prompt)); }
 GEN
 sd_prompt_cont(const char *v, long flag)
-{ return sd_prompt_set(v, flag, "_cont", Prompt_cont); }
+{ return sd_prompt_set(v, flag, "_cont", &(GP_DATA->prompt_cont)); }
 
 GEN
 sd_breakloop(const char *v, long flag)
@@ -2598,15 +1608,6 @@ GEN
 sd_recover(const char *v, long flag)
 { return sd_toggle(v,flag,"recover", &(GP_DATA->recover)); }
 
-#ifndef READLINE /* default not implemented */
-GEN
-sd_readline(const char *v, long flag)
-{ (void)v; (void)flag; return gnil; }
-GEN
-sd_histfile(const char *v, long flag)
-{ (void)v; (void)flag; return gnil; }
-#endif
-
 GEN
 sd_psfile(const char *v, long flag)
 { return sd_string(v, flag, "psfile", &current_psfile); }
@@ -2625,3 +1626,191 @@ sd_linewrap(const char *v, long flag)
   { if (n) init_linewrap(n); }
   GP_DATA->linewrap = n; return z;
 }
+
+/* readline-specific defaults */
+GEN
+sd_readline(const char *v, long flag)
+{
+  const char *msg[] = {
+    "(bits 0x2/0x4 control matched-insert/arg-complete)", NULL};
+  ulong state = GP_DATA->readline_state;
+  GEN res = sd_ulong(v,flag,"readline", &GP_DATA->readline_state, 0, 7, msg);
+
+  if (state != GP_DATA->readline_state)
+    (void)sd_toggle(GP_DATA->readline_state? "1": "0", d_SILENT, "readline", &(GP_DATA->use_readline));
+  return res;
+}
+GEN
+sd_histfile(const char *v, long flag)
+{
+  char *old = GP_DATA->histfile;
+  GEN r = sd_string(v, flag, "histfile", &GP_DATA->histfile);
+  if (v && !*v)
+  {
+    free(GP_DATA->histfile);
+    GP_DATA->histfile = NULL;
+  }
+  else if (GP_DATA->histfile != old && (!old || strcmp(old,GP_DATA->histfile)))
+  {
+    if (cb_pari_init_histfile) cb_pari_init_histfile();
+  }
+  return r;
+}
+
+/********************************************************************/
+/**                                                                **/
+/**                         METACOMMANDS                           **/
+/**                                                                **/
+/********************************************************************/
+void
+pari_print_version(void)
+{
+  pari_sp av = avma;
+  char *buf, *ver = what_cc();
+  const char *date = paricfg_compiledate;
+
+  pari_center(paricfg_version);
+  pari_center(paricfg_buildinfo);
+  buf = stack_malloc(strlen(date) +  32 + (ver? strlen(ver): 0));
+  if (ver) (void)sprintf(buf, "compiled: %s, %s", date, ver);
+  else     (void)sprintf(buf, "compiled: %s", date);
+  pari_center(buf);
+  sprintf(buf, "threading engine: %s",paricfg_mt_engine);
+  pari_center(buf);
+  ver = what_readline();
+  buf = stack_malloc(strlen(ver) + 64);
+  (void)sprintf(buf, "(readline %s, extended help%s enabled)", ver,
+                has_ext_help()? "": " not");
+  pari_center(buf); avma = av;
+}
+
+static void
+escape(const char *tch, int ismain)
+{
+  const char *s = tch;
+  char c;
+  switch ((c = *s++))
+  {
+    case 'w': case 'x': case 'a': case 'b': case 'B': case 'm':
+    { /* history things */
+      long d;
+      GEN x;
+      if (c != 'w' && c != 'x') d = get_int(s,0);
+      else
+      {
+        d = atol(s); if (*s == '-') s++;
+        while (isdigit((int)*s)) s++;
+      }
+      x = pari_get_hist(d);
+      switch (c)
+      {
+        case 'B': /* prettyprinter */
+          if (tex2mail_output(x,0)) break;
+        case 'b': /* fall through */
+        case 'm': matbrute(x, GP_DATA->fmt->format, -1); break;
+        case 'a': brute(x, GP_DATA->fmt->format, -1); break;
+        case 'x': dbgGEN(x, get_int(s, -1)); break;
+        case 'w':
+          s = get_sep(s); if (!*s) s = current_logfile;
+          write0(s, mkvec(x)); return;
+      }
+      pari_putc('\n'); return;
+    }
+
+    case 'c': commands(-1); break;
+    case 'd': (void)setdefault(NULL,NULL,d_SILENT); break;
+    case 'e':
+      s = get_sep(s);
+      if (!*s) s = (GP_DATA->echo)? "0": "1";
+      (void)sd_echo(s,d_ACKNOWLEDGE); break;
+    case 'g':
+      switch (*s)
+      {
+        case 'm': s++; (void)sd_debugmem(*s? s: NULL,d_ACKNOWLEDGE); break;
+        case 'f': s++; (void)sd_debugfiles(*s? s: NULL,d_ACKNOWLEDGE); break;
+        default : (void)sd_debug(*s? s: NULL,d_ACKNOWLEDGE); break;
+      }
+      break;
+    case 'h': print_functions_hash(s); break;
+    case 'l':
+      s = get_sep(s);
+      if (*s)
+      {
+        (void)sd_logfile(s,d_ACKNOWLEDGE);
+        if (pari_logfile) break;
+      }
+      (void)sd_log(pari_logfile?"0":"1",d_ACKNOWLEDGE);
+      break;
+    case 'o': (void)sd_output(*s? s: NULL,d_ACKNOWLEDGE); break;
+    case 'p':
+      switch (*s)
+      {
+        case 's': s++;
+          (void)sd_seriesprecision(*s? s: NULL,d_ACKNOWLEDGE); break;
+        default :
+          (void)sd_realprecision(*s? s: NULL,d_ACKNOWLEDGE); break;
+      }
+      break;
+    case 'q': cb_pari_quit(0); break;
+    case 'r':
+      s = get_sep(s);
+      if (!ismain) { (void)gp_read_file(s); break; }
+      switchin(s);
+      if (file_is_binary(pari_infile))
+      {
+        int vector;
+        GEN x = readbin(s,pari_infile, &vector);
+        popinfile();
+        if (!x) pari_err_FILE("input file",s);
+        if (vector) /* many BIN_GEN */
+        {
+          long i, l = lg(x);
+          pari_warn(warner,"setting %ld history entries", l-1);
+          for (i=1; i<l; i++) pari_add_hist(gel(x,i), 0);
+        }
+      }
+      break;
+    case 's': dbg_pari_heap(); break;
+    case 't': gentypes(); break;
+    case 'u':
+      print_all_user_fun((*s == 'm')? 1: 0);
+      break;
+    case 'v': pari_print_version(); break;
+    case 'y':
+      s = get_sep(s);
+      if (!*s) s = (GP_DATA->simplify)? "0": "1";
+      (void)sd_simplify(s,d_ACKNOWLEDGE); break;
+    default: pari_err(e_SYNTAX,"unexpected character", tch,tch-1);
+  }
+}
+
+static int
+chron(const char *s)
+{
+  if (*s)
+  { /* if "#" or "##" timer metacommand. Otherwise let the parser get it */
+    const char *t;
+    if (*s == '#') s++;
+    if (*s) return 0;
+    t = gp_format_time(pari_get_histtime(0));
+    pari_printf("  ***   last result computed in %s", t);
+  }
+  else { GP_DATA->chrono ^= 1; (void)sd_timer(NULL,d_ACKNOWLEDGE); }
+  return 1;
+}
+
+/* return 0: can't interpret *buf as a metacommand
+ *        1: did interpret *buf as a metacommand or empty command */
+int
+gp_meta(const char *buf, int ismain)
+{
+  switch(*buf++)
+  {
+    case '?': gp_help(buf, h_REGULAR); break;
+    case '#': return chron(buf);
+    case '\\': escape(buf, ismain); break;
+    case '\0': break;
+    default: return 0;
+  }
+  return 1;
+}
diff --git a/src/language/hash.c b/src/language/hash.c
index a2b7c6b..d6637fb 100644
--- a/src/language/hash.c
+++ b/src/language/hash.c
@@ -113,21 +113,84 @@ hash_insert(hashtable *h, void *k, void *v)
   e->val = v; hash_link(h, e);
 }
 
+/* the key 'k' may correspond to different values in the hash, return
+ * one satisfying the selection callback */
+hashentry *
+hash_select(hashtable *h, void *k, void *E,int(*select)(void *,hashentry *))
+{
+  ulong hash = h->hash(k);
+  hashentry *e = h->table[ hash % h->len ];
+  while (e)
+  {
+    if (hash == e->hash && h->eq(k, e->key) && select(E,e)) return e;
+    e = e->next;
+  }
+  return NULL;
+}
+
+GEN
+hash_keys(hashtable *h)
+{
+  long k = 1;
+  ulong i;
+  GEN v = cgetg(h->nb+1, t_VECSMALL);
+  for (i = 0; i < h->len; i++)
+  {
+    hashentry *e = h->table[i];
+    while (e) { v[k++] = (long)e->key; e = e->next; }
+  }
+  return v;
+}
+GEN
+hash_values(hashtable *h)
+{
+  long k = 1;
+  ulong i;
+  GEN v = cgetg(h->nb+1, t_VECSMALL);
+  for (i = 0; i < h->len; i++)
+  {
+    hashentry *e = h->table[i];
+    while (e) { v[k++] = (long)e->val; e = e->next; }
+  }
+  return v;
+}
+
+/* assume hash = h->hash(k) */
+hashentry *
+hash_search2(hashtable *h, void *k, ulong hash)
+{
+  hashentry *e = h->table[ hash % h->len ];
+  while (e)
+  {
+    if (hash == e->hash && h->eq(k, e->key)) return e;
+    e = e->next;
+  }
+  return NULL; /* not found */
+}
 /* returns entry associated with key k or NULL */
 hashentry *
 hash_search(hashtable *h, void *k)
 {
-  ulong hash;
-  hashentry *e;
   if (h->nb == 0) return NULL;
-  hash = h->hash(k);
-  e = h->table[ hash % h->len ];
+  return hash_search2(h, k, h->hash(k));
+}
+
+hashentry *
+hash_remove_select(hashtable *h, void *k, void *E,
+  int (*select)(void*,hashentry*))
+{
+  ulong hash = h->hash(k), index = hash % h->len;
+  hashentry **pE = &(h->table[index]), *e = *pE;
   while (e)
   {
-    if (hash == e->hash && h->eq(k, e->key)) return e;
+    if (hash == e->hash && h->eq(k, e->key) && select(E,e)) {
+      *pE = e->next; h->nb--;
+      return e;
+    }
+    pE = &(e->next);
     e = e->next;
   }
-  return NULL; /* not found */
+  return NULL;
 }
 
 hashentry *
@@ -158,13 +221,24 @@ hash_destroy(hashtable *h)
   }
   pari_free(h->table); pari_free(h);
 }
+static ulong
+hash_id(void *x) { return (ulong)x; }
+static int
+eq_id(void *x, void *y) { return x == y; }
+hashtable *
+hash_create_ulong(ulong s, long stack)
+{ return hash_create(s, &hash_id, &eq_id, stack); }
 
 static
 int strequal(void *a, void *b) { return !strcmp((char*)a,(char*)b); }
 hashtable *
+hash_create_str(ulong s, long stack)
+{ return hash_create(s, (ulong (*)(void *))&hash_str, strequal, stack); }
+
+hashtable *
 hashstr_import_static(hashentry *e, ulong size)
 {
-  hashtable *h = hash_create(size, (ulong (*)(void *))hash_str, strequal, 0);
+  hashtable *h = hash_create_str(size, 0);
   for ( ; e->key; e++) { hash_link(h, e); h->nb++; }
   return h;
 }
@@ -203,13 +277,13 @@ hash_GEN(GEN x)
     case t_INT:
       lx = lgefint(x);
       h &= TYPBITS;
-      for (i = 1; i < lx; i++) h = glue(h, (ulong)x[i]);
+      for (i = 1; i < lx; i++) h = glue(h, uel(x,i));
       return h;
     case t_REAL:
     case t_STR:
     case t_VECSMALL:
       lx = lg(x);
-      for (i = 1; i < lx; i++) h = glue(h, (ulong)x[i]);
+      for (i = 1; i < lx; i++) h = glue(h, uel(x,i));
       return h;
     /* one more special case */
     case t_LIST:
diff --git a/src/language/init.c b/src/language/init.c
index 4aaa79b..ef0d5ee 100644
--- a/src/language/init.c
+++ b/src/language/init.c
@@ -16,6 +16,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 /*        INITIALIZING THE SYSTEM, ERRORS, STACK MANAGEMENT        */
 /*                                                                 */
 /*******************************************************************/
+/* _GNU_SOURCE is needed before first include to get RUSAGE_THREAD */
+#undef _GNU_SOURCE /* avoid warning */
+#define _GNU_SOURCE
 #include <string.h>
 #include "pari.h"
 #include "paripriv.h"
@@ -70,33 +73,46 @@ int     disable_color;
 ulong   DEBUGFILES, DEBUGLEVEL, DEBUGMEM;
 long    DEBUGVAR;
 ulong   pari_mt_nbthreads;
-ulong   compatible, precreal, precdl, logstyle;
+long    precreal;
+ulong   precdl, logstyle;
 gp_data *GP_DATA;
 
-GEN pari_colormap, pari_graphcolors;
+GEN colormap, pari_graphcolors;
 
 entree  **varentries;
+long    *varpriority;
 
-THREAD pari_sp bot, top, avma;
-THREAD size_t memused;
+THREAD pari_sp avma;
+THREAD struct pari_mainstack *pari_mainstack;
 
-static void ** MODULES, ** OLDMODULES;
-static pari_stack s_MODULES, s_OLDMODULES;
+static void ** MODULES;
+static pari_stack s_MODULES;
 const long functions_tblsz = 135; /* size of functions_hash */
 entree **functions_hash, **defaults_hash;
 
+char *(*cb_pari_fgets_interactive)(char *s, int n, FILE *f);
+int (*cb_pari_get_line_interactive)(const char*, const char*, filtre_t *F);
+void (*cb_pari_quit)(long);
+void (*cb_pari_init_histfile)(void);
 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);
 void (*cb_pari_err_recover)(long);
+int (*cb_pari_break_loop)(int);
+int (*cb_pari_is_interactive)(void);
+void (*cb_pari_start_output)();
+
 const char * pari_library_path = NULL;
 
 static THREAD GEN global_err_data;
 THREAD jmp_buf *iferr_env;
 const long CATCH_ALL = -1;
 
+static void pari_init_timer(void);
+
 /*********************************************************************/
 /*                                                                   */
 /*                       BLOCKS & CLONES                             */
@@ -342,7 +358,7 @@ static void
 dflt_sigint_fun(void) { pari_err(e_MISC, "user interrupt"); }
 
 #if defined(_WIN32) || defined(__CYGWIN32__)
-int win32ctrlc = 0;
+int win32ctrlc = 0, win32alrm = 0;
 void
 dowin32ctrlc(void)
 {
@@ -464,39 +480,6 @@ init_universal_constants(void)
   err_e_STACK = (GEN)readonly_err_STACK;
 }
 
-static const size_t MIN_STACK = 500032;
-static size_t
-fix_size(size_t a)
-{
-  size_t b = a & (~0x3fUL); /* Align */
-  if (b < MIN_STACK) b = MIN_STACK;
-  return b;
-}
-/* old = current stack size (0 = unallocated), size = new size */
-void
-pari_init_stack(size_t size, size_t old)
-{
-  size_t s = fix_size(size);
-  if (old != s) {
-    BLOCK_SIGINT_START;
-    if (old) pari_free((void*)bot);
-    for (;;)
-    {
-      char buf[128];
-      if (s < MIN_STACK) pari_err(e_MEM); /* no way out. Die */
-      bot = (pari_sp)malloc(s); /* NOT pari_malloc, e_MEM would be deadly */
-      if (bot) break;
-      /* must use sprintf: pari stack is currently dead */
-      s = fix_size(s>>1);
-      sprintf(buf, "not enough memory, new stack %lu", (ulong)s);
-      pari_warn(warner, buf, s);
-    }
-    BLOCK_SIGINT_END;
-  }
-  avma = top = bot+s;
-  memused = 0;
-}
-
 static void
 pari_init_errcatch(void)
 {
@@ -504,21 +487,6 @@ pari_init_errcatch(void)
   global_err_data = NULL;
 }
 
-void
-allocatemem(ulong newsize)
-{
-  size_t s, old = top - bot;
-
-  evalstate_reset();
-  if (!newsize) newsize = old << 1;
-  pari_init_stack(newsize, old);
-  s = top - bot;
-  pari_warn(warner,"new stack size = %lu (%.3f Mbytes)", s, s/1048576.);
-  if (cb_pari_pre_recover) cb_pari_pre_recover(-1);
-  pari_init_errcatch();
-  cb_pari_err_recover(-1);
-}
-
 /*********************************************************************/
 /*                           INIT DEFAULTS                           */
 /*********************************************************************/
@@ -535,7 +503,6 @@ pari_init_defaults(void)
 #endif
 
   precdl = 16;
-  compatible = NONE;
   DEBUGFILES = DEBUGLEVEL = DEBUGMEM = 0;
   disable_color = 1;
   logstyle = logstyle_none;
@@ -556,7 +523,7 @@ pari_init_defaults(void)
   }
   else pari_datadir= pari_strdup(pari_datadir);
   for (i=0; i<c_LAST; i++) gp_colors[i] = c_NONE;
-  pari_colormap = NULL; pari_graphcolors = NULL;
+  colormap = NULL; pari_graphcolors = NULL;
 }
 
 /*********************************************************************/
@@ -603,9 +570,7 @@ gp_init_entrees(pari_stack *p_A, entree **hash)
 }
 int
 gp_init_functions(void)
-{
-  return gp_init_entrees(new_fun_set? &s_MODULES: &s_OLDMODULES, functions_hash);
-}
+{ return gp_init_entrees(&s_MODULES, functions_hash); }
 
 extern entree functions_basic[], functions_default[];
 static void
@@ -613,11 +578,8 @@ pari_init_functions(void)
 {
   pari_stack_init(&s_MODULES, sizeof(*MODULES),(void**)&MODULES);
   pari_stack_pushp(&s_MODULES,functions_basic);
-  pari_stack_init(&s_OLDMODULES, sizeof(*OLDMODULES),(void**)&OLDMODULES);
-  pari_stack_pushp(&s_OLDMODULES,oldfonctions);
   functions_hash = (entree**) pari_calloc(sizeof(entree*)*functions_tblsz);
-  pari_fill_hashtable(functions_hash,
-                      new_fun_set? functions_basic: oldfonctions);
+  pari_fill_hashtable(functions_hash, functions_basic);
   defaults_hash = (entree**) pari_calloc(sizeof(entree*)*functions_tblsz);
   pari_add_defaults_module(functions_default);
 }
@@ -625,8 +587,7 @@ pari_init_functions(void)
 void
 pari_add_module(entree *ep)
 {
-  if (new_fun_set)
-    pari_fill_hashtable(functions_hash, ep);
+  pari_fill_hashtable(functions_hash, ep);
   pari_stack_pushp(&s_MODULES, ep);
 }
 
@@ -634,38 +595,197 @@ void
 pari_add_defaults_module(entree *ep)
 { pari_fill_hashtable(defaults_hash, ep); }
 
-void
-pari_add_oldmodule(entree *ep)
+/*********************************************************************/
+/*                       PARI MAIN STACK                             */
+/*********************************************************************/
+
+#ifdef HAS_MMAP
+#include <sys/mman.h>
+#define PARI_STACK_ALIGN (sysconf(_SC_PAGE_SIZE))
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+#ifndef MAP_NORESERVE
+#define MAP_NORESERVE 0
+#endif
+static void *
+pari_mainstack_malloc(size_t size)
 {
-  if (!new_fun_set)
-    pari_fill_hashtable(functions_hash, ep);
-  pari_stack_pushp(&s_OLDMODULES, ep);
+  void *b = mmap(NULL, size, PROT_READ|PROT_WRITE,
+                             MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE,-1,0);
+  return (b == MAP_FAILED) ? NULL: b;
 }
 
-/*********************************************************************/
-/*                       PARI THREAD                                 */
-/*********************************************************************/
+static void
+pari_mainstack_mfree(void *s, size_t size)
+{
+  munmap(s, size);
+}
+
+static void
+pari_mainstack_mreset(void *s, size_t size)
+{
+  madvise(s, size, MADV_DONTNEED);
+}
+
+#else
+#define PARI_STACK_ALIGN (0x40UL)
+static void *
+pari_mainstack_malloc(size_t s)
+{
+  return malloc(s); /* NOT pari_malloc, e_MEM would be deadly */
+}
+
+static void
+pari_mainstack_mfree(void *s, size_t size) { (void) size; free(s); }
+
+static void
+pari_mainstack_mreset(void *s, size_t size) { (void) s; (void) size; }
+
+#endif
+
+static const size_t MIN_STACK = 500032UL;
+static size_t
+fix_size(size_t a)
+{
+  size_t ps = PARI_STACK_ALIGN;
+  size_t b = a & ~(ps - 1); /* Align */
+  if (b < a) b += ps;
+  if (b < MIN_STACK) b = MIN_STACK;
+  return b;
+}
 
 static void
-pari_mainstack_alloc(struct pari_mainstack *st, size_t s)
+pari_mainstack_alloc(struct pari_mainstack *st, size_t rsize, size_t vsize)
 {
-  st->bot = (pari_sp)pari_malloc(s);
-  st->avma = st->top = st->bot+s;
+  size_t sizemax = vsize ? vsize: rsize, s = fix_size(sizemax);
+  for (;; s>>=1)
+  {
+    char buf[128];
+    if (s < MIN_STACK) pari_err(e_MEM); /* no way out. Die */
+    st->vbot = (pari_sp)pari_mainstack_malloc(s);
+    if (st->vbot) break;
+      /* must use sprintf: pari stack is currently dead */
+    sprintf(buf, "not enough memory, new stack %lu", (ulong)s);
+    pari_warn(warner, buf, s);
+  }
+  st->vsize = vsize ? s: 0;
+  st->rsize = minss(rsize, s);
+  st->size = st->rsize;
+  st->top = st->vbot+s;
+  st->bot = st->top - st->size;
   st->memused = 0;
 }
 
 static void
 pari_mainstack_free(struct pari_mainstack *st)
 {
-  pari_free((void*)st->bot);
-  st->avma = st->top = st->bot = 0;
+  pari_mainstack_mfree((void*)st->vbot, st->vsize ? st->vsize : fix_size(st->rsize));
+  st->top = st->bot = st->vbot = 0;
+  st->size = st->vsize =0;
+}
+
+static void
+pari_mainstack_resize(struct pari_mainstack *st, size_t rsize, size_t vsize)
+{
+  BLOCK_SIGINT_START;
+  pari_mainstack_free(st);
+  pari_mainstack_alloc(st, rsize, vsize);
+  BLOCK_SIGINT_END;
 }
 
 static void
 pari_mainstack_use(struct pari_mainstack *st)
 {
-  bot = st->bot; top = st->top; avma = st->avma;
-  memused = st->memused;
+  pari_mainstack = st;
+  avma = st->top;
+}
+
+void
+paristack_alloc(size_t rsize, size_t vsize)
+{
+  pari_mainstack_alloc(pari_mainstack, rsize, vsize);
+  pari_mainstack_use(pari_mainstack);
+}
+
+void
+paristack_setsize(size_t rsize, size_t vsize)
+{
+  pari_mainstack_resize(pari_mainstack, rsize, vsize);
+  pari_mainstack_use(pari_mainstack);
+}
+
+void
+parivstack_resize(ulong newsize)
+{
+  size_t s;
+  if (newsize && newsize < pari_mainstack->rsize)
+    pari_err_DIM("stack sizes [parisizemax < parisize]");
+  if (newsize == pari_mainstack->vsize) return;
+  evalstate_reset();
+  paristack_setsize(pari_mainstack->rsize, newsize);
+  s = newsize ? newsize : pari_mainstack->rsize;
+  pari_warn(warner,"new maximum stack size = %lu (%.3f Mbytes)", s, s/1048576.);
+  pari_init_errcatch();
+  cb_pari_err_recover(-1);
+}
+
+void
+paristack_newrsize(ulong newsize)
+{
+  size_t s, vsize = pari_mainstack->vsize;
+  if (!newsize) newsize = pari_mainstack->rsize << 1;
+  if (newsize != pari_mainstack->rsize)
+    pari_mainstack_resize(pari_mainstack, newsize, vsize);
+  evalstate_reset();
+  s = pari_mainstack->rsize;
+  pari_warn(warner,"new stack size = %lu (%.3f Mbytes)", s, s/1048576.);
+  pari_init_errcatch();
+  cb_pari_err_recover(-1);
+}
+
+void
+paristack_resize(ulong newsize)
+{
+  size_t vsize = pari_mainstack->vsize;
+  if (!newsize)
+    newsize = pari_mainstack->size << 1;
+  newsize = maxuu(minuu(newsize, vsize), pari_mainstack->size);
+  pari_mainstack->size = newsize;
+  pari_mainstack->bot = pari_mainstack->top - pari_mainstack->size;
+  pari_warn(warner,"increasing stack size to %lu",newsize);
+}
+
+void
+parivstack_reset(void)
+{
+  pari_mainstack->size = pari_mainstack->rsize;
+  pari_mainstack->bot = pari_mainstack->top - pari_mainstack->size;
+  pari_mainstack_mreset((void *)pari_mainstack->vbot,
+                        pari_mainstack->bot-pari_mainstack->vbot);
+}
+
+void
+new_chunk_resize(size_t x)
+{
+  if (pari_mainstack->vsize==0
+    || x > (avma-pari_mainstack->vbot) / sizeof(long)) pari_err(e_STACK);
+  while (x > (avma-pari_mainstack->bot) / sizeof(long))
+    paristack_resize(0);
+}
+
+/*********************************************************************/
+/*                       PARI THREAD                                 */
+/*********************************************************************/
+
+/* Initial PARI thread structure t with a stack of size s and virtual size v
+ * and argument arg */
+
+void
+pari_thread_valloc(struct pari_thread *t, size_t s, size_t v, GEN arg)
+{
+  pari_mainstack_alloc(&t->st,s,v);
+  t->data = arg;
 }
 
 /* Initial PARI thread structure t with a stack of size s and
@@ -674,7 +794,7 @@ pari_mainstack_use(struct pari_mainstack *st)
 void
 pari_thread_alloc(struct pari_thread *t, size_t s, GEN arg)
 {
-  pari_mainstack_alloc(&t->st,s);
+  pari_mainstack_alloc(&t->st,s,0);
   t->data = arg;
 }
 
@@ -730,14 +850,28 @@ pari_exit(void)
 static void
 dflt_err_recover(long errnum) { (void) errnum; pari_exit(); }
 
+static void
+dflt_pari_quit(long err) { (void)err; /*do nothing*/; }
+
+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)
 {
   ulong u;
 
+  cb_pari_quit = dflt_pari_quit;
+  cb_pari_init_histfile = NULL;
+  cb_pari_get_line_interactive = NULL;
+  cb_pari_fgets_interactive = NULL;
   cb_pari_whatnow = NULL;
+  cb_pari_handle_exception = NULL;
+  cb_pari_err_handle = pari_err_display;
   cb_pari_pre_recover = NULL;
+  cb_pari_break_loop = NULL;
+  cb_pari_is_interactive = NULL;
+  cb_pari_start_output = NULL;
   cb_pari_sigint = dflt_sigint_fun;
   if (init_opts&INIT_JMPm) cb_pari_err_recover = dflt_err_recover;
 
@@ -749,22 +883,24 @@ pari_init_opts(size_t parisize, ulong maxprime, ulong init_opts)
     gp_expand_path(GP_DATA->path);
   }
 
-  if (init_opts&INIT_SIGm) pari_sig_init(pari_sighandler);
-  pari_init_stack(parisize, 0);
+  pari_mainstack = (struct pari_mainstack *) malloc(sizeof(*pari_mainstack));
+  paristack_alloc(parisize, 0);
   init_universal_constants();
   diffptr = NULL;
   if (!(init_opts&INIT_noPRIMEm)) initprimetable(maxprime);
   pari_kernel_init();
 
   primetab = cgetalloc(t_VEC, 1);
-  varentries = (entree**) pari_calloc((MAXVARN+1)*sizeof(entree*));
   pari_thread_init();
   pari_init_seadata();
   pari_init_functions();
   pari_var_init();
+  pari_init_timer();
+  pari_init_buffers();
   (void)getabstime();
   try_to_recover = 1;
   if (!(init_opts&INIT_noIMTm)) pari_mt_init();
+  if ((init_opts&INIT_SIGm)) pari_sig_init(pari_sighandler);
 }
 
 void
@@ -780,7 +916,6 @@ pari_close_opts(ulong init_opts)
   if ((init_opts&INIT_SIGm)) pari_sig_init(SIG_DFL);
   if (!(init_opts&INIT_noIMTm)) pari_mt_close();
 
-  while (delete_var()) /* empty */;
   for (i = 0; i < functions_tblsz; i++)
   {
     entree *ep = functions_hash[i];
@@ -790,7 +925,7 @@ pari_close_opts(ulong init_opts)
       ep = EP;
     }
   }
-  free((void*)varentries);
+  pari_var_close();
   free((void*)primetab);
   pari_close_seadata();
   pari_thread_close();
@@ -798,12 +933,12 @@ pari_close_opts(ulong init_opts)
 
   free((void*)functions_hash);
   free((void*)defaults_hash);
-  free((void*)bot);
   if (diffptr) free((void*)diffptr);
   free(current_logfile);
   free(current_psfile);
+  pari_mainstack_free(pari_mainstack);
+  free((void*)pari_mainstack);
   pari_stack_delete(&s_MODULES);
-  pari_stack_delete(&s_OLDMODULES);
   pari_close_homedir();
   if (pari_datadir) free(pari_datadir);
   if (init_opts&INIT_DFTm)
@@ -812,6 +947,10 @@ pari_close_opts(ulong init_opts)
     if (GP_DATA->pp->cmd) free((void*)GP_DATA->pp->cmd);
     delete_dirs(GP_DATA->path);
     free((void*)GP_DATA->path->PATH);
+    if (GP_DATA->help) free((void*)GP_DATA->help);
+    free((void*)GP_DATA->prompt);
+    free((void*)GP_DATA->prompt_cont);
+    free((void*)GP_DATA->histfile);
   }
   BLOCK_SIGINT_END;
 }
@@ -835,6 +974,7 @@ gp_context_save(struct gp_context* rec)
   rec->listloc = next_block;
   rec->iferr_env = iferr_env;
   rec->err_data  = global_err_data;
+  varstate_save(&rec->var);
   evalstate_save(&rec->eval);
   parsestate_save(&rec->parse);
 }
@@ -872,6 +1012,7 @@ gp_context_restore(struct gp_context* rec)
       ep = EP;
     }
   }
+  varstate_restore(&rec->var);
   if (DEBUGMEM>2) err_printf("leaving recover()\n");
   BLOCK_SIGINT_END
   try_to_recover = 1;
@@ -885,9 +1026,6 @@ err_recover(long numerr)
   evalstate_reset();
   killallfiles();
   pari_init_errcatch();
-  out_puts(pariErr, "\n");
-  pariErr->flush();
-
   cb_pari_err_recover(numerr);
 }
 
@@ -1096,6 +1234,8 @@ pari_err2GEN(long numerr, va_list ap)
     retmkerr2(numerr, utoi(va_arg(ap, ulong)));
   case e_STACK:
     return err_e_STACK;
+  case e_STACKTHREAD:
+    retmkerr3(numerr, utoi(va_arg(ap, ulong)), utoi(va_arg(ap, ulong)));
   default:
     return mkerr(numerr);
   }
@@ -1238,13 +1378,29 @@ pari_err2str(GEN e)
     return pari_sprintf("not an n-th power residue in %Ps: %Ps.",
                         gel(e,2), gel(e,3));
   case e_STACK:
+  case e_STACKTHREAD:
     {
-      size_t d = top - bot;
+      const char *stack = numerr == e_STACK? "PARI": "thread";
+      const char *var = numerr == e_STACK? "parisizemax": "threadsizemax";
+      size_t rsize = numerr == e_STACKTHREAD && GP_DATA->threadsize ?
+                                GP_DATA->threadsize: pari_mainstack->rsize;
+      size_t vsize = numerr == e_STACK? pari_mainstack->vsize:
+                                        GP_DATA->threadsizemax;
       char *buf = (char *) pari_malloc(512*sizeof(char));
-      sprintf(buf, "the PARI stack overflows !\n"
-          "  current stack size: %lu (%.3f Mbytes)\n"
-          "  [hint] you can increase GP stack with allocatemem()\n",
-          (ulong)d, (double)d/1048576.);
+      if (vsize)
+      {
+        sprintf(buf, "the %s stack overflows !\n"
+            "  current stack size: %lu (%.3f Mbytes)\n"
+            "  [hint] you can increase '%s' using default()\n",
+            stack, (ulong)vsize, (double)vsize/1048576., var);
+      }
+      else
+      {
+        sprintf(buf, "the %s stack overflows !\n"
+            "  current stack size: %lu (%.3f Mbytes)\n"
+            "  [hint] set '%s' to a non-zero value in your GPRC\n",
+            stack, (ulong)rsize, (double)rsize/1048576., var);
+      }
       return buf;
     }
   case e_SYNTAX:
@@ -1264,21 +1420,22 @@ pari_err2str(GEN e)
   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)
@@ -1293,6 +1450,8 @@ pari_err_display(GEN err)
     }
     pari_free(s);
   }
+  out_term_color(pariErr, c_NONE);
+  pariErr->flush(); return 0;
 }
 
 void
@@ -1313,12 +1472,9 @@ pari_err(int numerr, ...)
   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);
@@ -1361,6 +1517,7 @@ numerr_name(long numerr)
   case e_SQRTN:    return "e_SQRTN";
   case e_STACK:    return "e_STACK";
   case e_SYNTAX:   return "e_SYNTAX";
+  case e_STACKTHREAD:   return "e_STACKTHREAD";
   case e_TYPE2:    return "e_TYPE2";
   case e_TYPE:     return "e_TYPE";
   case e_USER:     return "e_USER";
@@ -1440,7 +1597,7 @@ trap0(const char *e, GEN r, GEN f)
 /*                                                                 */
 /*******************************************************************/
 /* lontyp[tx] = 0 (non recursive type) or number of codewords for type tx */
-const  long lontyp[] = { 0,0,0,1,1,2,1,2,1,1, 2,2,0,1,1,1,1,1,1,1, 2,0,0,2,2 };
+const  long lontyp[] = { 0,0,0,1,1,2,1,2,1,1, 2,2,0,1,1,1,1,1,1,1, 2,0,0,2,2,1 };
 
 static GEN
 list_internal_copy(GEN z, long nmax)
@@ -1450,7 +1607,7 @@ list_internal_copy(GEN z, long nmax)
   if (!z) return NULL;
   l = lg(z);
   a = (GEN)pari_malloc((nmax+1) * sizeof(long));
-  for (i = 1; i < l; i++) gel(a,i) = gclone( gel(z,i) );
+  for (i = 1; i < l; i++) gel(a,i) = gel(z,i)? gclone(gel(z,i)): gen_0;
   a[0] = z[0]; return a;
 }
 
@@ -1554,16 +1711,15 @@ gcopy_avma(GEN x, pari_sp *AVMA)
       y = cgetlist_avma(AVMA);
       listassign(x, y); return y;
 
-    default:
-      y = cgetg_copy_avma(x, &lx, AVMA);
-      if (lontyp[tx] == 1) i = 1; else { y[1] = x[1]; i = 2; }
-      for (; i<lx; i++) gel(y,i) = gcopy_avma(gel(x,i), AVMA);
   }
+  y = cgetg_copy_avma(x, &lx, AVMA);
+  if (lontyp[tx] == 1) i = 1; else { y[1] = x[1]; i = 2; }
+  for (; i<lx; i++) gel(y,i) = gcopy_avma(gel(x,i), AVMA);
   return y;
 }
 
 /* [copy_bin/bin_copy:] same as gcopy_avma but use NULL to code an exact 0, and
- * make shallow copies of t_LISTs */
+ * make shallow copies of finalized t_LISTs */
 static GEN
 gcopy_av0(GEN x, pari_sp *AVMA)
 {
@@ -1576,14 +1732,16 @@ gcopy_av0(GEN x, pari_sp *AVMA)
       if (!signe(x)) return NULL; /* special marker */
       *AVMA = (pari_sp)icopy_avma(x, *AVMA);
       return (GEN)*AVMA;
-    case t_REAL: case t_STR: case t_VECSMALL: case t_LIST:
+    case t_LIST:
+      if (list_data(x) && !list_nmax(x)) break; /* not finalized, need copy */
+      /* else finalized: shallow copy */
+    case t_REAL: case t_STR: case t_VECSMALL:
       *AVMA = (pari_sp)leafcopy_avma(x, *AVMA);
       return (GEN)*AVMA;
-    default:
-      y = cgetg_copy_avma(x, &lx, AVMA);
-      if (lontyp[tx] == 1) i = 1; else { y[1] = x[1]; i = 2; }
-      for (; i<lx; i++) gel(y,i) = gcopy_av0(gel(x,i), AVMA);
   }
+  y = cgetg_copy_avma(x, &lx, AVMA);
+  if (lontyp[tx] == 1) i = 1; else { y[1] = x[1]; i = 2; }
+  for (; i<lx; i++) gel(y,i) = gcopy_av0(gel(x,i), AVMA);
   return y;
 }
 
@@ -1629,12 +1787,11 @@ gcopy_av0_canon(GEN x, pari_sp *AVMA)
       }
       return y;
     }
-    default:
-      y = cgetg_copy_avma(x, &lx, AVMA);
-      if (lontyp[tx] == 1) i = 1; else { y[1] = x[1]; i = 2; }
-      for (; i<lx; i++) gel(y,i) = gcopy_av0_canon(gel(x,i), AVMA);
   }
-return y;
+  y = cgetg_copy_avma(x, &lx, AVMA);
+  if (lontyp[tx] == 1) i = 1; else { y[1] = x[1]; i = 2; }
+  for (; i<lx; i++) gel(y,i) = gcopy_av0_canon(gel(x,i), AVMA);
+  return y;
 }
 
 /* [copy_bin/bin_copy:] size (number of words) required for gcopy_av0(x) */
@@ -1655,11 +1812,10 @@ taille0(GEN x)
       GEN L = list_data(x);
       return L? 3 + taille0(L): 3;
     }
-    default:
-      n = lx = lg(x);
-      for (i=lontyp[tx]; i<lx; i++) n += taille0(gel(x,i));
-      return n;
   }
+  n = lx = lg(x);
+  for (i=lontyp[tx]; i<lx; i++) n += taille0(gel(x,i));
+  return n;
 }
 
 /* [copy_bin/bin_copy:] size (number of words) required for gcopy_av0(x) */
@@ -1672,16 +1828,20 @@ taille0_nolist(GEN x)
     case t_INT:
       lx = lgefint(x);
       return lx == 2? 0: lx;
+    case t_LIST:
+    {
+      GEN L = list_data(x);
+      if (L && !list_nmax(x)) break; /* not finalized, deep copy */
+    }
+    /* else finalized: shallow */
     case t_REAL:
     case t_STR:
     case t_VECSMALL:
-    case t_LIST:
       return lg(x);
-    default:
-      n = lx = lg(x);
-      for (i=lontyp[tx]; i<lx; i++) n += taille0_nolist(gel(x,i));
-      return n;
   }
+  n = lx = lg(x);
+  for (i=lontyp[tx]; i<lx; i++) n += taille0_nolist(gel(x,i));
+  return n;
 }
 
 /* How many words do we need to allocate to copy x ? t_LIST is a special case
@@ -1782,8 +1942,13 @@ void
 shiftaddress(GEN x, long dec)
 {
   long i, lx, tx = typ(x);
-  if (is_recursive_t(tx) && tx != t_LIST)
+  if (is_recursive_t(tx))
   {
+    if (tx == t_LIST)
+    {
+      if (!list_data(x) || list_nmax(x)) return; /* empty or finalized */
+      /* not finalized, update pointers  */
+    }
     lx = lg(x);
     for (i=lontyp[tx]; i<lx; i++) {
       if (!x[i]) gel(x,i) = gen_0;
@@ -1886,32 +2051,20 @@ obj_checkbuild(GEN S, long tag, GEN (*build)(GEN))
 }
 
 GEN
-obj_checkbuild_prec(GEN S, long tag, GEN (*build)(GEN,long), long prec)
+obj_checkbuild_prec(GEN S, long tag, GEN (*build)(GEN,long),
+  long (*pr)(GEN), long prec)
 {
   pari_sp av = avma;
   GEN w = obj_check(S, tag);
-  if (w)
-  {
-    long p = gprecision(w);
-    if (p >= prec) return gprec_w(w, prec);
-  }
-  w = obj_insert(S, tag, build(S, prec));
+  if (!w || pr(w) < prec) w = obj_insert(S, tag, build(S, prec));
   avma = av; return gcopy(w);
 }
-
+GEN
+obj_checkbuild_realprec(GEN S, long tag, GEN (*build)(GEN,long), long prec)
+{ return obj_checkbuild_prec(S,tag,build,gprecision,prec); }
 GEN
 obj_checkbuild_padicprec(GEN S, long tag, GEN (*build)(GEN,long), long prec)
-{
-  pari_sp av = avma;
-  GEN w = obj_check(S, tag);
-  if (w)
-  {
-    long p = padicprec_relative(w);
-    if (p >= prec) return gprec_w(w, prec);
-  }
-  w = obj_insert(S, tag, build(S, prec));
-  avma = av; return gcopy(w);
-}
+{ return obj_checkbuild_prec(S,tag,build,padicprec_relative,prec); }
 
 /* Reset S [last position], freeing all clones */
 void
@@ -2078,13 +2231,14 @@ gerepile(pari_sp av, pari_sp tetpil, GEN q)
 void
 fill_stack(void)
 {
-  GEN x = ((GEN)bot);
+  GEN x = ((GEN)pari_mainstack->bot);
   while (x < (GEN)avma) *x++ = 0xfefefefeUL;
 }
 
 void
 debug_stack(void)
 {
+  pari_sp top = pari_mainstack->top, bot = pari_mainstack->bot;
   GEN z;
   err_printf("bot=0x%lx\ttop=0x%lx\tavma=0x%lx\n", bot, top, avma);
   for (z = ((GEN)top)-1; z >= (GEN)avma; z--)
@@ -2095,7 +2249,7 @@ void
 setdebugvar(long n) { DEBUGVAR=n; }
 
 long
-getstack(void) { return top-avma; }
+getstack(void) { return pari_mainstack->top-avma; }
 
 /*******************************************************************/
 /*                                                                 */
@@ -2103,30 +2257,68 @@ getstack(void) { return top-avma; }
 /*                                                                 */
 /*******************************************************************/
 
+#if defined(USE_GETTIMEOFDAY) || defined(USE_GETRUSAGE)
+#include <sys/time.h>
+#endif
+
+#if defined(USE_FTIME) || defined(USE_FTIMEFORWALLTIME)
+#include <sys/timeb.h>
+#endif
+
 #if defined(USE_CLOCK_GETTIME)
 #include <time.h>
+#endif
+
+#if defined(USE_CLOCK_GETTIME)
+#if defined(_POSIX_THREAD_CPUTIME)
+static THREAD clockid_t time_type = CLOCK_THREAD_CPUTIME_ID;
+#else
+static const THREAD clockid_t time_type = CLOCK_PROCESS_CPUTIME_ID;
+#endif
+static void
+pari_init_timer(void)
+{
+#if defined(_POSIX_THREAD_CPUTIME)
+  time_type = CLOCK_PROCESS_CPUTIME_ID;
+#endif
+}
+
 void
 timer_start(pari_timer *T)
 {
   struct timespec t;
-  clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&t);
+  clock_gettime(time_type,&t);
   T->us = t.tv_nsec / 1000;
   T->s  = t.tv_sec;
 }
 #elif defined(USE_GETRUSAGE)
-# include <sys/time.h>
 # include <sys/resource.h>
+#ifdef RUSAGE_THREAD
+static THREAD int rusage_type = RUSAGE_THREAD;
+#else
+static const THREAD int rusage_type = RUSAGE_SELF;
+#endif /*RUSAGE_THREAD*/
+static void
+pari_init_timer(void)
+{
+#ifdef RUSAGE_THREAD
+  rusage_type = RUSAGE_SELF;
+#endif
+}
+
 void
 timer_start(pari_timer *T)
 {
   struct rusage r;
-  getrusage(RUSAGE_SELF,&r);
+  getrusage(rusage_type,&r);
   T->us = r.ru_utime.tv_usec;
   T->s  = r.ru_utime.tv_sec;
 }
 #elif defined(USE_FTIME)
 
-# include <sys/timeb.h>
+static void
+pari_init_timer(void) { }
+
 void
 timer_start(pari_timer *T)
 {
@@ -2149,6 +2341,9 @@ _get_time(pari_timer *T, long Ticks, long TickPerSecond)
 #  include <sys/times.h>
 #  include <sys/time.h>
 #  include <time.h>
+static void
+pari_init_timer(void) { }
+
 void
 timer_start(pari_timer *T)
 {
@@ -2161,6 +2356,9 @@ timer_start(pari_timer *T)
   _get_time(T, t.tms_utime, tck);
 }
 # elif defined(WINCE)
+static void
+pari_init_timer(void) { }
+
 void
 timer_start(pari_timer *T)
 { _get_time(T, GetTickCount(), 1000); }
@@ -2169,6 +2367,9 @@ timer_start(pari_timer *T)
 #  ifndef CLOCKS_PER_SEC
 #   define CLOCKS_PER_SEC 1000000 /* may be false on YOUR system */
 #  endif
+static void
+pari_init_timer(void) { }
+
 void
 timer_start(pari_timer *T)
 { _get_time(T, clock(), CLOCKS_PER_SEC); }
@@ -2221,6 +2422,33 @@ msgtimer(const char *format, ...)
 }
 long
 getabstime(void)  { return timer_get(&abstimer_T);}
+#if defined(USE_CLOCK_GETTIME) || defined(USE_GETTIMEOFDAY) \
+ || defined(USE_FTIMEFORWALLTIME)
+static GEN
+timetoi(ulong s, ulong m)
+{
+  pari_sp av = avma;
+  GEN r = addiu(muliu(utoi(s), 1000), m);
+  return gerepileuptoint(av, r);
+}
+#endif
+GEN
+getwalltime(void)
+{
+#if defined(USE_CLOCK_GETTIME)
+  struct timespec t;
+  if (!clock_gettime(CLOCK_REALTIME,&t))
+    return timetoi(t.tv_sec, (t.tv_nsec + 500000)/1000000);
+#elif defined(USE_GETTIMEOFDAY)
+  struct timeval tv;
+  if (!gettimeofday(&tv, NULL))
+    return timetoi(tv.tv_sec, (tv.tv_usec + 500)/1000);
+#elif defined(USE_FTIMEFORWALLTIME)
+  struct timeb tp;
+  ftime(&tp); return timetoi(tp.time, tp.millitm);
+#endif
+  return utoi(getabstime());
+}
 
 /*******************************************************************/
 /*                                                                 */
@@ -2259,80 +2487,23 @@ pari_version(void)
   }
 }
 
-/* List of GP functions:
- * generated from the description system.
- * ---------------------
+/* List of GP functions: generated from the description system.
  * Format (struct entree) :
- *   char *name    : name (under GP).
- *   ulong valence : (EpNEW, EpALIAS,EpVAR, EpINSTALL)|EpSTATIC
- *   void *value   : For PREDEFINED FUNCTIONS: C function to call.
- *                   For USER FUNCTIONS: pointer to defining data (block) =
- *                    entree*: NULL, list of entree (arguments), NULL
- *                    char*  : function text
- *   long menu     : which help section do we belong to (See below).
- *   char *code    : argument list (See below).
- *   char *help    : short help text (init to NULL).
- *   void *pvalue  : push_val history.
- *   long arity    : maximum number of arguments.
- *   entree *next  : next entree (init to NULL, used in hashing code).
- * menu:
- * -----
- *  1: Standard monadic or dyadic OPERATORS
- *  2: CONVERSIONS and similar elementary functions
- *  3: TRANSCENDENTAL functions
- *  4: NUMBER THEORETICAL functions
- *  5: Functions related to ELLIPTIC CURVES
- *  6: Functions related to general NUMBER FIELDS
- *  7: POLYNOMIALS and power series
- *  8: Vectors, matrices, LINEAR ALGEBRA and sets
- *  9: SUMS, products, integrals and similar functions
- *  10: GRAPHIC functions
- *  11: PROGRAMMING under GP
- *
- * code: describe function prototype. NULL = use valence instead.
- * -----
- * Arguments:
- *  I  closure whose value is ignored, like in for() loop
- *  E  closure whose value is used, like in sum() loop
- *  J  implicit function of arity 1, like in parsum() loop
- *  G  GEN
- *  L  long
- *  V  lexical variable
- *  C  lexical context
- *  n  variable number
- *  W  GEN, which will be modified in place (for t_LIST)
- *  &  *GEN
- *  f  Fake *long (function requires it, but we don't use the resulting long)
- *  p  real precision (prec for the C library)
- *  P  series precision (precdl for the C library)
- *  r  raw input (treated as a string without quotes).
- *     Quoted args are copied as strings. Stops at first unquoted ')' or ','.
- *     Special chars can be quoted using '\'.  Ex : aa"b\n)"c => "aab\n)c".
- *  s  expanded string. Example: Pi"x"2 yields "3.142x2".
- *     The unquoted components can be of any pari type (converted according to
- *     the current output format)
- *  E* any number of E
- *  s* any number of strings (see s)
- *  M  Mnemonic or a flag (converted to a long); description follows
- *         after \n at the end of the argument description
- *  D  Has a default value. Format is "Dvalue,type," (the ending comma is
- *     mandatory). Ex: D0,L, (arg is long, 0 by default).
- *     Special syntax:
- *       if type = G, &, r, s, I or V:  D[G&rsIV] all send NULL.
- *       if type = n: Dn sends -1.
- *       if type = &: argument must be prefixed by '&'.
- *
- *     The user-given args are read first, then completed by the defaults
- *
- * Return type (first char or immediately after 'x'): GEN by default, otherwise
- *  m Return GEN but is can point to the input (member function).
- *  l Return long
- *  i Return int
- *  v Return void
- *
- * Syntax requirements:
- *  = Separator '=' required.
- ****************************************************************************
- */
+ *   char *name   : name (under GP).
+ *   ulong valence: (EpNEW, EpALIAS,EpVAR, EpINSTALL)|EpSTATIC
+ *   void *value  : For PREDEFINED FUNCTIONS: C function to call.
+ *                  For USER FUNCTIONS: pointer to defining data (block) =
+ *                   entree*: NULL, list of entree (arguments), NULL
+ *                   char*  : function text
+ *   long menu    : which help section do we belong to
+ *                   1: Standard monadic or dyadic OPERATORS
+ *                   2: CONVERSIONS and similar elementary functions
+ *                   3: TRANSCENDENTAL functions, etc.
+ *   char *code   : GP prototype, aka Parser Code (see libpari's manual)
+ *                  if NULL, use valence instead.
+ *   char *help   : short help text (init to NULL).
+ *   void *pvalue : push_val history.
+ *   long arity   : maximum number of arguments.
+ *   entree *next : next entree (init to NULL, used in hashing code). */
 #include "init.h"
 #include "default.h"
diff --git a/src/language/init.h b/src/language/init.h
index 756fdfe..d1efd15 100644
--- a/src/language/init.h
+++ b/src/language/init.h
@@ -2,12 +2,12 @@
 /* See src/desc/gen_proto */
 /* Do not edit*/
 entree functions_basic[]={
-{"!_",0,(void*)gnot,13,"G","!_"},
-{"#_",0,(void*)glength,13,"lG","#x: number of non code words in x, number of characters for a string."},
-{"%",0,(void*)pari_get_hist,13,"D0,L,","last history item."},
-{"%#",0,(void*)pari_get_histtime,13,"lD0,L,","time to compute last history item."},
-{"+_",0,NULL,13,NULL,"+_"},
-{"-_",0,(void*)gneg,13,"G","-_"},
+{"!_",0,(void*)gnot,15,"G","!_"},
+{"#_",0,(void*)glength,15,"lG","#x: number of non code words in x, number of characters for a string."},
+{"%",0,(void*)pari_get_hist,15,"D0,L,","last history item."},
+{"%#",0,(void*)pari_get_histtime,15,"lD0,L,","time to compute last history item."},
+{"+_",0,NULL,15,NULL,"+_"},
+{"-_",0,(void*)gneg,15,"G","-_"},
 {"Catalan",0,(void*)mpcatalan,3,"p","Catalan=Catalan(): Catalan's number with current precision."},
 {"Col",0,(void*)gtocol0,2,"GD0,L,","Col(x, {n}): transforms the object x into a column vector of dimension n."},
 {"Colrev",0,(void*)gtocolrev0,2,"GD0,L,","Colrev(x, {n}): transforms the object x into a column vector of dimension n in reverse order with respect to Col(x, {n}). Empty vector if x is omitted."},
@@ -16,8 +16,8 @@ entree functions_basic[]={
 {"List",0,(void*)gtolist,2,"DG","List({x=[]}): transforms the vector or list x into a list. Empty list if x is omitted."},
 {"Mat",0,(void*)gtomat,2,"DG","Mat({x=[]}): transforms any GEN x into a matrix. Empty matrix if x is omitted."},
 {"Mod",0,(void*)gmodulo,2,"GG","Mod(a,b): creates 'a modulo b'."},
-{"O",0,(void*)ggrando,7,"","O(p^e): p-adic or power series zero with precision given by e"},
-{"O(_^_)",0,(void*)ggrando,15,"GD1,L,","O(p^e): p-adic or power series zero with precision given by e."},
+{"O",0,(void*)ggrando,9,"","O(p^e): p-adic or power series zero with precision given by e"},
+{"O(_^_)",0,(void*)ggrando,17,"GD1,L,","O(p^e): p-adic or power series zero with precision given by e."},
 {"Pi",0,(void*)mppi,3,"p","Pi=Pi(): the constant pi, with current precision."},
 {"Pol",0,(void*)gtopoly,2,"GDn","Pol(t,{v='x}): convert t (usually a vector or a power series) into a polynomial with variable v, starting with the leading coefficient."},
 {"Polrev",0,(void*)gtopolyrev,2,"GDn","Polrev(t,{v='x}): convert t (usually a vector or a power series) into a polynomial with variable v, starting with the constant term."},
@@ -27,117 +27,175 @@ entree functions_basic[]={
 {"Str",0,(void*)Str,2,"s*","Str({x}*): concatenates its (string) argument into a single string."},
 {"Strchr",0,(void*)Strchr,2,"G","Strchr(x): converts x to a string, translating each integer into a character."},
 {"Strexpand",0,(void*)Strexpand,2,"s*","Strexpand({x}*): concatenates its (string) argument into a single string, performing tilde expansion."},
-{"Strprintf",0,(void*)Strprintf,11,"ss*","Strprintf(fmt,{x}*): returns a string built from the remaining arguments according to the format fmt."},
+{"Strprintf",0,(void*)Strprintf,13,"ss*","Strprintf(fmt,{x}*): returns a string built from the remaining arguments according to the format fmt."},
 {"Strtex",0,(void*)Strtex,2,"s*","Strtex({x}*): translates its (string) arguments to TeX format and returns the resulting string."},
 {"Vec",0,(void*)gtovec0,2,"GD0,L,","Vec(x, {n}): transforms the object x into a vector of dimension n."},
 {"Vecrev",0,(void*)gtovecrev0,2,"GD0,L,","Vecrev(x, {n}): transforms the object x into a vector of dimension n in reverse order with respect to Vec(x, {n}). Empty vector if x is omitted."},
 {"Vecsmall",0,(void*)gtovecsmall0,2,"GD0,L,","Vecsmall(x, {n}): transforms the object x into a VECSMALL of dimension n."},
-{"[_.._]",0,(void*)vecrange,15,"GG","[a..b] = [a,a+1,...,b]"},
-{"[_|_<-_,_;_]",0,(void*)vecexpr1,15,"mGVDEDE","[a(x)|x<-b,c(x);...]"},
-{"[_|_<-_,_]",0,(void*)vecexpr0,15,"GVDEDE","[a(x)|x<-b,c(x)] = apply(a,select(c,b))"},
-{"_!",0,(void*)mpfact,13,"L","n!: factorial of n."},
-{"_!=_",0,(void*)gne,13,"GG","_!=_"},
-{"_%=_",0,(void*)gmode,13,"&G","x%=y: shortcut for x=x%y."},
-{"_%_",0,(void*)gmod,13,"GG","x%y: Euclidean remainder of x and y."},
-{"_&&_",0,(void*)andpari,13,"GE","_&&_"},
-{"_'",0,(void*)deriv,13,"GDn","x': derivative of x with respect to the main variable."},
-{"_*=_",0,(void*)gmule,13,"&G","x*=y: shortcut for x=x*y."},
-{"_*_",0,(void*)gmul,13,"GG","x*y: product of x and y."},
-{"_++",0,(void*)gadd1e,13,"&","x++"},
-{"_+=_",0,(void*)gadde,13,"&G","x+=y: shortcut for x=x+y."},
-{"_+_",0,(void*)gadd,13,"GG","x+y: sum of x and y."},
-{"_--",0,(void*)gsub1e,13,"&","x--"},
-{"_-=_",0,(void*)gsube,13,"&G","x-=y: shortcut for x=x-y."},
-{"_-_",0,(void*)gsub,13,"GG","x-y: difference of x and y."},
-{"_.a1",0,(void*)member_a1,14,"mG","_.a1"},
-{"_.a2",0,(void*)member_a2,14,"mG","_.a2"},
-{"_.a3",0,(void*)member_a3,14,"mG","_.a3"},
-{"_.a4",0,(void*)member_a4,14,"mG","_.a4"},
-{"_.a6",0,(void*)member_a6,14,"mG","_.a6"},
-{"_.area",0,(void*)member_area,14,"mG","_.area"},
-{"_.b2",0,(void*)member_b2,14,"mG","_.b2"},
-{"_.b4",0,(void*)member_b4,14,"mG","_.b4"},
-{"_.b6",0,(void*)member_b6,14,"mG","_.b6"},
-{"_.b8",0,(void*)member_b8,14,"mG","_.b8"},
-{"_.bid",0,(void*)member_bid,14,"mG","_.bid"},
-{"_.bnf",0,(void*)member_bnf,14,"mG","_.bnf"},
-{"_.c4",0,(void*)member_c4,14,"mG","_.c4"},
-{"_.c6",0,(void*)member_c6,14,"mG","_.c6"},
-{"_.clgp",0,(void*)member_clgp,14,"mG","_.clgp"},
-{"_.codiff",0,(void*)member_codiff,14,"mG","_.codiff"},
-{"_.cyc",0,(void*)member_cyc,14,"mG","_.cyc"},
-{"_.diff",0,(void*)member_diff,14,"mG","_.diff"},
-{"_.disc",0,(void*)member_disc,14,"mG","_.disc"},
-{"_.e",0,(void*)member_e,14,"mG","_.e"},
-{"_.eta",0,(void*)member_eta,14,"mG","_.eta"},
-{"_.f",0,(void*)member_f,14,"mG","_.f"},
-{"_.fu",0,(void*)member_fu,14,"G","_.fu"},
-{"_.futu",0,(void*)member_futu,14,"mG","_.futu"},
-{"_.gen",0,(void*)member_gen,14,"mG","_.gen"},
-{"_.group",0,(void*)member_group,14,"mG","_.group"},
-{"_.index",0,(void*)member_index,14,"mG","_.index"},
-{"_.j",0,(void*)member_j,14,"mG","_.j"},
-{"_.mod",0,(void*)member_mod,14,"mG","_.mod"},
-{"_.nf",0,(void*)member_nf,14,"mG","_.nf"},
-{"_.no",0,(void*)member_no,14,"mG","_.no"},
-{"_.omega",0,(void*)member_omega,14,"mG","_.omega"},
-{"_.orders",0,(void*)member_orders,14,"mG","_.orders"},
-{"_.p",0,(void*)member_p,14,"mG","_.p"},
-{"_.pol",0,(void*)member_pol,14,"mG","_.pol"},
-{"_.polabs",0,(void*)member_polabs,14,"mG","_.polabs"},
-{"_.r1",0,(void*)member_r1,14,"mG","_.r1"},
-{"_.r2",0,(void*)member_r2,14,"mG","_.r2"},
-{"_.reg",0,(void*)member_reg,14,"mG","_.reg"},
-{"_.roots",0,(void*)member_roots,14,"mG","_.roots"},
-{"_.sign",0,(void*)member_sign,14,"mG","_.sign"},
-{"_.t2",0,(void*)member_t2,14,"G","_.t2"},
-{"_.tate",0,(void*)member_tate,14,"mG","_.tate"},
-{"_.tu",0,(void*)member_tu,14,"G","_.tu"},
-{"_.tufu",0,(void*)member_tufu,14,"mG","_.tufu"},
-{"_.zk",0,(void*)member_zk,14,"mG","_.zk"},
-{"_.zkst",0,(void*)member_zkst,14,"mG","_.zkst"},
-{"_/=_",0,(void*)gdive,13,"&G","x/=y: shortcut for x=x/y."},
-{"_/_",0,(void*)gdiv,13,"GG","x/y: quotient of x and y."},
-{"_<<=_",0,(void*)gshiftle,13,"&L","x<<=y: shortcut for x=x<<y."},
-{"_<<_",0,(void*)gshift,13,"GL","x<<y"},
-{"_<=_",0,(void*)gle,13,"GG","x<=y: return 1 if x is less or equal to y, 0 otherwise."},
-{"_<_",0,(void*)glt,13,"GG","x<y: return 1 if x is strictly less than y, 0 otherwise."},
-{"_===_",0,(void*)gidentical,13,"iGG","a === b : true if a and b are identical"},
-{"_==_",0,(void*)geq,13,"GG","_==_"},
-{"_>=_",0,(void*)gge,13,"GG","x>=y: return 1 if x is greater or equal to y, 0 otherwise."},
-{"_>>=_",0,(void*)gshiftre,13,"&L","x>>=y: shortcut for x=x>>y."},
-{"_>>_",0,(void*)gshift_right,13,"GL","x>>y"},
-{"_>_",0,(void*)ggt,13,"GG","x>y: return 1 if x is strictly greater than y, 0 otherwise."},
-{"_[_.._,_.._]",0,(void*)matslice0,13,"GD0,L,D0,L,D0,L,D0,L,","x[a..b,c..d] = [x[a,c],  x[a+1,c],  ...,x[b,c];                      x[a,c+1],x[a+1,c+1],...,x[b,c+1];                        ...       ...          ...                      x[a,d],  x[a+1,d]  ,...,x[b,d]]"},
-{"_[_.._]",0,(void*)vecslice0,13,"GD0,L,L","x[a..b] = [x[a],x[a+1],...,x[b]]"},
-{"_\\/=_",0,(void*)gdivrounde,13,"&G","x\\/=y: shortcut for x=x\\/y."},
-{"_\\/_",0,(void*)gdivround,13,"GG","x\\/y: rounded Euclidean quotient of x and y."},
-{"_\\=_",0,(void*)gdivente,13,"&G","x\\=y: shortcut for x=x\\y."},
-{"_\\_",0,(void*)gdivent,13,"GG","x\\y: Euclidean quotient of x and y."},
-{"_^_",0,(void*)gpow,13,"GGp","x^y: compute x to the power y."},
-{"_^s",0,(void*)gpowgs,15,"GL","return x^n where n is a small integer"},
-{"__",0,NULL,13,NULL,"__"},
-{"_derivfun",0,(void*)derivfun0,15,"GGp","_derivfun(closure,[args]) numerical derivation of closure with respect to the first variable at (args)."},
-{"_eval_mnemonic",0,(void*)eval_mnemonic,15,"lGs","Convert a mnemonic string to a flag."},
-{"_factor_Aurifeuille",0,(void*)factor_Aurifeuille,15,"GL","_factor_Aurifeuille(a,d): return an algebraic factor of Phi_d(a), a != 0"},
-{"_factor_Aurifeuille_prime",0,(void*)factor_Aurifeuille_prime,15,"GL","_factor_Aurifeuille_prime(p,d): return an algebraic factor of Phi_d(p), p prime"},
-{"_multi_if",0,(void*)ifpari_multi,15,"GE*","internal variant of if() that allows more than 3 arguments."},
-{"_parapply_worker",0,(void*)parapply_worker,15,"GG","_parapply_worker(d,C): evaluate the closure C on d."},
-{"_pareval_worker",0,(void*)pareval_worker,15,"G","_pareval_worker(C): evaluate the closure C."},
-{"_parfor_worker",0,(void*)parfor_worker,15,"GG","_parfor_worker(i,C): evaluate the closure C on i and return [i,C(i)]"},
-{"_parvector_worker",0,(void*)parvector_worker,15,"GG","_parvector_worker(i,C): evaluate the closure C on i."},
-{"_void_if",0,(void*)ifpari_void,15,"vGDIDI","internal variant of if() that does not return a value."},
-{"_||_",0,(void*)orpari,13,"GE","x||y: inclusive OR."},
-{"_~",0,(void*)gtrans,13,"G","x~: transpose of x."},
+{"[_.._]",0,(void*)vecrange,17,"GG","[a..b] = [a,a+1,...,b]"},
+{"[_|_<-_,_;_]",0,(void*)vecexpr1,17,"mGVDEDE","[a(x)|x<-b,c(x);...]"},
+{"[_|_<-_,_]",0,(void*)vecexpr0,17,"GVDEDE","[a(x)|x<-b,c(x)] = apply(a,select(c,b))"},
+{"_!",0,(void*)mpfact,15,"L","n!: factorial of n."},
+{"_!=_",0,(void*)gne,15,"GG","_!=_"},
+{"_%=_",0,(void*)gmode,15,"&G","x%=y: shortcut for x=x%y."},
+{"_%_",0,(void*)gmod,15,"GG","x%y: Euclidean remainder of x and y."},
+{"_&&_",0,(void*)andpari,15,"GE","_&&_"},
+{"_'",0,(void*)deriv,15,"GDn","x': derivative of x with respect to the main variable."},
+{"_*=_",0,(void*)gmule,15,"&G","x*=y: shortcut for x=x*y."},
+{"_*_",0,(void*)gmul,15,"GG","x*y: product of x and y."},
+{"_++",0,(void*)gadd1e,15,"&","x++"},
+{"_+=_",0,(void*)gadde,15,"&G","x+=y: shortcut for x=x+y."},
+{"_+_",0,(void*)gadd,15,"GG","x+y: sum of x and y."},
+{"_--",0,(void*)gsub1e,15,"&","x--"},
+{"_-=_",0,(void*)gsube,15,"&G","x-=y: shortcut for x=x-y."},
+{"_-_",0,(void*)gsub,15,"GG","x-y: difference of x and y."},
+{"_.a1",0,(void*)member_a1,16,"mG","_.a1"},
+{"_.a2",0,(void*)member_a2,16,"mG","_.a2"},
+{"_.a3",0,(void*)member_a3,16,"mG","_.a3"},
+{"_.a4",0,(void*)member_a4,16,"mG","_.a4"},
+{"_.a6",0,(void*)member_a6,16,"mG","_.a6"},
+{"_.area",0,(void*)member_area,16,"mG","_.area"},
+{"_.b2",0,(void*)member_b2,16,"mG","_.b2"},
+{"_.b4",0,(void*)member_b4,16,"mG","_.b4"},
+{"_.b6",0,(void*)member_b6,16,"mG","_.b6"},
+{"_.b8",0,(void*)member_b8,16,"mG","_.b8"},
+{"_.bid",0,(void*)member_bid,16,"mG","_.bid"},
+{"_.bnf",0,(void*)member_bnf,16,"mG","_.bnf"},
+{"_.c4",0,(void*)member_c4,16,"mG","_.c4"},
+{"_.c6",0,(void*)member_c6,16,"mG","_.c6"},
+{"_.clgp",0,(void*)member_clgp,16,"mG","_.clgp"},
+{"_.codiff",0,(void*)member_codiff,16,"mG","_.codiff"},
+{"_.cyc",0,(void*)member_cyc,16,"mG","_.cyc"},
+{"_.diff",0,(void*)member_diff,16,"mG","_.diff"},
+{"_.disc",0,(void*)member_disc,16,"mG","_.disc"},
+{"_.e",0,(void*)member_e,16,"mG","_.e"},
+{"_.eta",0,(void*)member_eta,16,"mG","_.eta"},
+{"_.f",0,(void*)member_f,16,"mG","_.f"},
+{"_.fu",0,(void*)member_fu,16,"G","_.fu"},
+{"_.futu",0,(void*)member_futu,16,"mG","_.futu"},
+{"_.gen",0,(void*)member_gen,16,"mG","_.gen"},
+{"_.group",0,(void*)member_group,16,"mG","_.group"},
+{"_.index",0,(void*)member_index,16,"mG","_.index"},
+{"_.j",0,(void*)member_j,16,"mG","_.j"},
+{"_.mod",0,(void*)member_mod,16,"mG","_.mod"},
+{"_.nf",0,(void*)member_nf,16,"mG","_.nf"},
+{"_.no",0,(void*)member_no,16,"mG","_.no"},
+{"_.omega",0,(void*)member_omega,16,"mG","_.omega"},
+{"_.orders",0,(void*)member_orders,16,"mG","_.orders"},
+{"_.p",0,(void*)member_p,16,"mG","_.p"},
+{"_.pol",0,(void*)member_pol,16,"mG","_.pol"},
+{"_.polabs",0,(void*)member_polabs,16,"mG","_.polabs"},
+{"_.r1",0,(void*)member_r1,16,"mG","_.r1"},
+{"_.r2",0,(void*)member_r2,16,"mG","_.r2"},
+{"_.reg",0,(void*)member_reg,16,"mG","_.reg"},
+{"_.roots",0,(void*)member_roots,16,"mG","_.roots"},
+{"_.sign",0,(void*)member_sign,16,"mG","_.sign"},
+{"_.t2",0,(void*)member_t2,16,"G","_.t2"},
+{"_.tate",0,(void*)member_tate,16,"mG","_.tate"},
+{"_.tu",0,(void*)member_tu,16,"G","_.tu"},
+{"_.tufu",0,(void*)member_tufu,16,"mG","_.tufu"},
+{"_.zk",0,(void*)member_zk,16,"mG","_.zk"},
+{"_.zkst",0,(void*)member_zkst,16,"mG","_.zkst"},
+{"_/=_",0,(void*)gdive,15,"&G","x/=y: shortcut for x=x/y."},
+{"_/_",0,(void*)gdiv,15,"GG","x/y: quotient of x and y."},
+{"_<<=_",0,(void*)gshiftle,15,"&L","x<<=y: shortcut for x=x<<y."},
+{"_<<_",0,(void*)gshift,15,"GL","x<<y"},
+{"_<=_",0,(void*)gle,15,"GG","x<=y: return 1 if x is less or equal to y, 0 otherwise."},
+{"_<_",0,(void*)glt,15,"GG","x<y: return 1 if x is strictly less than y, 0 otherwise."},
+{"_===_",0,(void*)gidentical,15,"iGG","a === b : true if a and b are identical"},
+{"_==_",0,(void*)geq,15,"GG","_==_"},
+{"_>=_",0,(void*)gge,15,"GG","x>=y: return 1 if x is greater or equal to y, 0 otherwise."},
+{"_>>=_",0,(void*)gshiftre,15,"&L","x>>=y: shortcut for x=x>>y."},
+{"_>>_",0,(void*)gshift_right,15,"GL","x>>y"},
+{"_>_",0,(void*)ggt,15,"GG","x>y: return 1 if x is strictly greater than y, 0 otherwise."},
+{"_[_.._,_.._]",0,(void*)matslice0,15,"GD0,L,D0,L,D0,L,D0,L,","x[a..b,c..d] = [x[a,c],  x[a+1,c],  ...,x[b,c];                      x[a,c+1],x[a+1,c+1],...,x[b,c+1];                        ...       ...          ...                      x[a,d],  x[a+1,d]  ,...,x[b,d]]"},
+{"_[_.._]",0,(void*)vecslice0,15,"GD0,L,L","x[a..b] = [x[a],x[a+1],...,x[b]]"},
+{"_\\/=_",0,(void*)gdivrounde,15,"&G","x\\/=y: shortcut for x=x\\/y."},
+{"_\\/_",0,(void*)gdivround,15,"GG","x\\/y: rounded Euclidean quotient of x and y."},
+{"_\\=_",0,(void*)gdivente,15,"&G","x\\=y: shortcut for x=x\\y."},
+{"_\\_",0,(void*)gdivent,15,"GG","x\\y: Euclidean quotient of x and y."},
+{"_^_",0,(void*)gpow,15,"GGp","x^y: compute x to the power y."},
+{"_^s",0,(void*)gpowgs,17,"GL","return x^n where n is a small integer"},
+{"__",0,NULL,15,NULL,"__"},
+{"_derivfun",0,(void*)derivfun0,17,"GGp","_derivfun(closure,[args]) numerical derivation of closure with respect to the first variable at (args)."},
+{"_eval_mnemonic",0,(void*)eval_mnemonic,17,"lGs","Convert a mnemonic string to a flag."},
+{"_factor_Aurifeuille",0,(void*)factor_Aurifeuille,17,"GL","_factor_Aurifeuille(a,d): return an algebraic factor of Phi_d(a), a != 0"},
+{"_factor_Aurifeuille_prime",0,(void*)factor_Aurifeuille_prime,17,"GL","_factor_Aurifeuille_prime(p,d): return an algebraic factor of Phi_d(p), p prime"},
+{"_multi_if",0,(void*)ifpari_multi,17,"GE*","internal variant of if() that allows more than 3 arguments."},
+{"_parapply_worker",0,(void*)parapply_worker,17,"GG","_parapply_worker(d,C): evaluate the closure C on d."},
+{"_pareval_worker",0,(void*)pareval_worker,17,"G","_pareval_worker(C): evaluate the closure C."},
+{"_parfor_worker",0,(void*)parfor_worker,17,"GG","_parfor_worker(i,C): evaluate the closure C on i and return [i,C(i)]"},
+{"_parvector_worker",0,(void*)parvector_worker,17,"GG","_parvector_worker(i,C): evaluate the closure C on i."},
+{"_void_if",0,(void*)ifpari_void,17,"vGDIDI","internal variant of if() that does not return a value."},
+{"_||_",0,(void*)orpari,15,"GE","x||y: inclusive OR."},
+{"_~",0,(void*)gtrans,15,"G","x~: transpose of x."},
 {"abs",0,(void*)gabs,3,"Gp","abs(x): absolute value (or modulus) of x."},
 {"acos",0,(void*)gacos,3,"Gp","acos(x): arc cosine of x."},
 {"acosh",0,(void*)gacosh,3,"Gp","acosh(x): inverse hyperbolic cosine of x."},
-{"addhelp",0,(void*)addhelp,11,"vrs","addhelp(sym,str): add/change help message for the symbol sym."},
+{"addhelp",0,(void*)addhelp,13,"vrs","addhelp(sym,str): add/change help message for the symbol sym."},
 {"addprimes",0,(void*)addprimes,4,"DG","addprimes({x=[]}): add primes in the vector x to the prime table to be used in trial division. x may also be a single integer. Composite \"primes\" are NOT allowed!"},
 {"agm",0,(void*)agm,3,"GGp","agm(x,y): arithmetic-geometric mean of x and y."},
-{"algdep",0,(void*)algdep0,8,"GLD0,L,","algdep(x,k,{flag=0}): algebraic relations up to degree n of x, using lindep([1,x,...,x^(k-1)], flag)."},
-{"alias",0,(void*)alias0,11,"vrr","alias(newsym,sym): defines the symbol newsym as an alias for the symbol sym."},
-{"apply",0,(void*)apply0,11,"GG","apply(f, A): apply function f to each entry in A."},
+{"alarm",0,(void*)gp_alarm,13,"D0,L,DE","alarm({s = 0},{code}): if code is omitted, trigger an \"e_ALARM\" exception after s seconds, cancelling any previously set alarm; stop a pending alarm if s = 0 or is omitted. Otherwise, evaluate code, aborting after s seconds."},
+{"algabsdim",0,(void*)algabsdim,8,"lG","algabsdim(al): dimension of the algebra al over its prime subfield."},
+{"algadd",0,(void*)algadd,8,"GGG","algadd(al,x,y): element x+y in al."},
+{"algalgtobasis",0,(void*)algalgtobasis,8,"GG","algalgtobasis(al,x): transforms the element x of the algebra al into a column vector on the integral basis of al."},
+{"algaut",0,(void*)algaut,8,"G","algaut(al): the stored automorphism of the splitting field of the cyclic algebra al."},
+{"algb",0,(void*)algb,8,"G","algb(al): the element b of the center of the cyclic algebra al used to define it."},
+{"algbasis",0,(void*)algbasis,8,"G","algbasis(al): basis of the stored order of the central simple algebra al."},
+{"algbasistoalg",0,(void*)algbasistoalg,8,"GG","algbasistoalg(al,x): transforms the column vector x on the integral basis of al into an element of al in algebraic form."},
+{"algcenter",0,(void*)gp_algcenter,8,"G","algcenter(al): center of the algebra al."},
+{"algcentralproj",0,(void*)alg_centralproj,8,"GGD0,L,","algcentralproj(al,z,{maps=0}): projections of the algebra al on the orthogonal central idempotents z[i]."},
+{"algchar",0,(void*)algchar,8,"G","algchar(al): characteristic of the algebra al."},
+{"algcharpoly",0,(void*)algcharpoly,8,"GGDn","algcharpoly(al,b,{v='x}): (reduced) characteristic polynomial of b in \\var{al}, with respect to the variable $v$."},
+{"algdecomposition",0,(void*)alg_decomposition,8,"G","algdecomposition(al): semisimple decomposition of the algebra al."},
+{"algdegree",0,(void*)algdegree,8,"lG","algdegree(al): degree of the central simple algebra al."},
+{"algdep",0,(void*)algdep0,10,"GLD0,L,","algdep(x,k,{flag=0}): algebraic relations up to degree n of x, using lindep([1,x,...,x^(k-1)], flag)."},
+{"algdim",0,(void*)algdim,8,"lG","algdim(al): dimension of the algebra al."},
+{"algdisc",0,(void*)algdisc,8,"G","algdisc(al): discriminant of the stored order of the algebra al."},
+{"algdivl",0,(void*)algdivl,8,"GGG","algdivl(al,x,y): element x\\y in al."},
+{"algdivr",0,(void*)algdivr,8,"GGG","algdivr(al,x,y): element x/y in al."},
+{"alghasse",0,(void*)alghasse,8,"GG","alghasse(al,pl): the hasse invariant of the central simple algebra al at the place pl."},
+{"alghassef",0,(void*)alghassef,8,"G","alghassef(al): the hasse invariant of the central simple algebra al at finite places."},
+{"alghassei",0,(void*)alghassei,8,"G","alghassei(al): the hasse invariant of the central simple algebra al at infinite places."},
+{"algindex",0,(void*)algindex,8,"lGDG","algindex(al,{pl}): the index of the central simple algebra al. If pl is set, it should be a prime ideal of the center or an integer between 1 and r1+r2, and in that case return the local index at the place pl instead."},
+{"alginit",0,(void*)alginit,8,"GGDnD1,L,","alginit(B, C, {v}, {flag = 1}): initialize the central simple algebra defined by data B, C. If flag = 1, compute a maximal order."},
+{"alginv",0,(void*)alginv,8,"GG","alginv(al,x): element 1/x in al."},
+{"alginvbasis",0,(void*)alginvbasis,8,"G","alginvbasis(al): basis of the natural order of the central simple algebra al in terms of the stored order."},
+{"algisassociative",0,(void*)algisassociative,8,"iGD0,G,","algisassociative(mt,p=0): true (1) if the multiplication table mt is suitable for algtableinit(mt,p), false (0) otherwise."},
+{"algiscommutative",0,(void*)algiscommutative,8,"iG","algiscommutative(al): test whether the algebra al is commutative."},
+{"algisdivision",0,(void*)algisdivision,8,"iGDG","algisdivision(al,{pl}): test whether the central simple algebra al is a division algebra. If pl is set, it should be a prime ideal of the center or an integer between 1 and r1+r2, and in that case test whether al is locally a division algebra at the place pl instead."},
+{"algisdivl",0,(void*)algisdivl,8,"iGGGD&","algisdivl(al,x,y,{&z}): tests whether y is left divisible by x and sets z to the left quotient x\\y."},
+{"algisinv",0,(void*)algisinv,8,"iGGD&","algisinv(al,x,{&ix}): tests whether x is invertible and sets ix to the inverse of x."},
+{"algisramified",0,(void*)algisramified,8,"iGDG","algisramified(al,{pl}): test whether the central simple algebra al is ramified, i.e. not isomorphic to a matrix ring over its center. If pl is set, it should be a prime ideal of the center or an integer between 1 and r1+r2, and in that case test whether al is locally ramified at the place pl instead."},
+{"algissemisimple",0,(void*)algissemisimple,8,"iG","algissemisimple(al): test whether the algebra al is semisimple."},
+{"algissimple",0,(void*)algissimple,8,"iGD0,L,","algissimple(al, {ss = 0}): test whether the algebra al is simple."},
+{"algissplit",0,(void*)algissplit,8,"iGDG","algissplit(al,{pl}): test whether the central simple algebra al is split, i.e. isomorphic to a matrix ring over its center. If pl is set, it should be a prime ideal of the center or an integer between 1 and r1+r2, and in that case test whether al is locally split at the place pl instead."},
+{"algmul",0,(void*)algmul,8,"GGG","algmul(al,x,y): element x*y in al."},
+{"algmultable",0,(void*)gp_algmultable,8,"GDG","algmultable(al,x): left multiplication table of x."},
+{"algneg",0,(void*)algneg,8,"GG","algneg(al,x): element -x in al."},
+{"algnorm",0,(void*)algnorm,8,"GG","algnorm(al,x): (reduced) norm of x."},
+{"algpoleval",0,(void*)algpoleval,8,"GGG","algpoleval(al,T,b): T in K[X] evaluate T(b) in al."},
+{"algpow",0,(void*)algpow,8,"GGG","algpow(al,x,n): element x^n in al."},
+{"algprimesubalg",0,(void*)algprimesubalg,8,"G","algprimesubalg(al): prime subalgebra of the positive characteristic, semisimple algebra al."},
+{"algquotient",0,(void*)alg_quotient,8,"GGD0,L,","algquotient(al,I,{flag=0}): quotient of the algebra al by the two-sided ideal I."},
+{"algradical",0,(void*)algradical,8,"G","algradical(al): Jacobson radical of the algebra al."},
+{"algramifiedplaces",0,(void*)algramifiedplaces,8,"G","algramifiedplaces(al): vector of the places of the center of al that ramify in al. Each place is described as an integer between 1 and r1 or as a prime ideal."},
+{"algrandom",0,(void*)algrandom,8,"GG","algrandom(al,b): random element in al with coefficients in [-b,b]."},
+{"algrelmultable",0,(void*)algrelmultable,8,"G","algrelmultable(al): multiplication table of the central simple algebra al over its center."},
+{"algsimpledec",0,(void*)algsimpledec,8,"GD0,L,","algsimpledec(al,{flag=0}): decomposition into simple algebras of the semisimple algebra al."},
+{"algsplittingdata",0,(void*)algsplittingdata,8,"G","algsplittingdata(al): data stored in the central simple algebra al to compute a splitting of al over an extension."},
+{"algsplittingfield",0,(void*)algsplittingfield,8,"G","algsplittingfield(al): the stored splitting field of the central simple algebra al."},
+{"algsplittingmatrix",0,(void*)algsplittingmatrix,8,"GG","algsplittingmatrix(al,x): image of x under a splitting of al."},
+{"algsqr",0,(void*)algsqr,8,"GG","algsqr(al,x): element x^2 in al."},
+{"algsub",0,(void*)algsub,8,"GGG","algsub(al,x,y): element x-y in al."},
+{"algsubalg",0,(void*)algsubalg,8,"GG","algsubalg(al,B): subalgebra of al with basis B."},
+{"algtableinit",0,(void*)algtableinit,8,"GDG","algtableinit(mt, {p}): initialize the associative algebra over Q (resp. Fp) defined by the multiplication table mt."},
+{"algtensor",0,(void*)algtensor,8,"GGD1,L,","algtensor(al1,al2,{maxord=1}): tensor product of al1 and al2."},
+{"algtrace",0,(void*)algtrace,8,"GG","algtrace(al,x): (reduced) trace of x."},
+{"algtype",0,(void*)algtype,8,"lG","algtype(al): type of the algebra al."},
+{"alias",0,(void*)alias0,13,"vrr","alias(newsym,sym): defines the symbol newsym as an alias for the symbol sym."},
+{"allocatemem",0,(void*)gp_allocatemem,13,"vDG","allocatemem({s=0}): allocates a new stack of s bytes. doubles the stack if s is omitted."},
+{"apply",0,(void*)apply0,13,"GG","apply(f, A): apply function f to each entry in A."},
 {"arg",0,(void*)garg,3,"Gp","arg(x): argument of x,such that -pi<arg(x)<=pi."},
 {"asin",0,(void*)gasin,3,"Gp","asin(x): arc sine of x."},
 {"asinh",0,(void*)gasinh,3,"Gp","asinh(x): inverse hyperbolic sine of x."},
@@ -157,7 +215,7 @@ entree functions_basic[]={
 {"bestappr",0,(void*)bestappr,4,"GDG","bestappr(x, {B}): returns a rational approximation to x, whose denominator is limited by B, if present. This function applies to reals, intmods, p-adics, and rationals of course. Otherwise it applies recursively to all components."},
 {"bestapprPade",0,(void*)bestapprPade,4,"GD-1,L,","bestappr(x, {B}): returns a rational function approximation to x. This function applies to series, polmods, and rational functions of course. Otherwise it applies recursively to all components."},
 {"bezout",0,(void*)gcdext0,4,"GG","bezout(x,y): deprecated alias for gcdext"},
-{"bezoutres",0,(void*)polresultantext0,7,"GGDn","bezoutre(A,B,{v}): deprecated alias for polresultantext"},
+{"bezoutres",0,(void*)polresultantext0,9,"GGDn","bezoutres(A,B,{v}): deprecated alias for polresultantext"},
 {"bigomega",0,(void*)bigomega,4,"lG","bigomega(x): number of prime divisors of x, counted with multiplicity."},
 {"binary",0,(void*)binaire,2,"G","binary(x): gives the vector formed by the binary digits of x (x integer)."},
 {"binomial",0,(void*)binomial,4,"GL","binomial(x,y): binomial coefficient x*(x-1)...*(x-y+1)/y! defined for y in Z and any x."},
@@ -167,39 +225,42 @@ entree functions_basic[]={
 {"bitor",0,(void*)gbitor,2,"GG","bitor(x,y): bitwise \"or\" of two integers x and y. Negative numbers behave as if modulo big power of 2."},
 {"bittest",0,(void*)gbittest,2,"GL","bittest(x,n): gives bit number n (coefficient of 2^n) of the integer x. Negative numbers behave as if modulo big power of 2."},
 {"bitxor",0,(void*)gbitxor,2,"GG","bitxor(x,y): bitwise \"exclusive or\" of two integers x and y. Negative numbers behave as if modulo big power of 2."},
-{"bnfcertify",0,(void*)bnfcertify0,6,"lGD0,L,","bnfcertify(bnf,{flag = 0}): certify the correctness (i.e. remove the GRH) of the bnf data output by bnfinit. If flag is present, only certify that the class group is a quotient of the one computed in bnf (much simpler in general)."},
-{"bnfcompress",0,(void*)bnfcompress,6,"G","bnfcompress(bnf): converts bnf to a much smaller sbnf, containing the same information. Use bnfinit(sbnf) to recover a true bnf."},
-{"bnfdecodemodule",0,(void*)decodemodule,6,"GG","bnfdecodemodule(nf,m): given a coded module m as in bnrdisclist, gives the true module."},
-{"bnfinit",0,(void*)bnfinit0,6,"GD0,L,DGp","bnfinit(P,{flag=0},{tech=[]}): compute the necessary data for future use in ideal and unit group computations, including fundamental units if they are not too large. flag and tech are both optional. flag can be any of 0: default, 1: insist on having fundamental units. See manual for details about tech."},
-{"bnfisintnorm",0,(void*)bnfisintnorm,6,"GG","bnfisintnorm(bnf,x): compute a complete system of solutions (modulo units of positive norm) of the absolute norm equation N(a)=x, where a belongs to the maximal order of big number field bnf (if bnf is not certified, this depends on GRH)."},
-{"bnfisnorm",0,(void*)bnfisnorm,6,"GGD1,L,","bnfisnorm(bnf,x,{flag=1}): Tries to tell whether x (in Q) is the norm of some fractional y (in bnf). Returns a vector [a,b] where x=Norm(a)*b. Looks for a solution which is a S-unit, with S a certain list of primes (in bnf) containing (among others) all primes dividing x. If bnf is known to be Galois, set flag=0 (in this case, x is a norm iff b=1). If flag is non zero the program adds to S all the primes: dividing flag if flag<0, or less than  [...]
-{"bnfisprincipal",0,(void*)bnfisprincipal0,6,"GGD1,L,","bnfisprincipal(bnf,x,{flag=1}): bnf being output by bnfinit (with flag<=2), gives [v,alpha], where v is the vector of exponents on the class group generators and alpha is the generator of the resulting principal ideal. In particular x is principal if and only if v is the zero vector. flag is optional, whose binary digits mean 1: output [v,alpha] (only v if unset); 2: increase precision until alpha can be computed (do not insist if u [...]
-{"bnfissunit",0,(void*)bnfissunit,6,"GGG","bnfissunit(bnf,sfu,x): bnf being output by bnfinit (with flag<=2), sfu by bnfsunit, gives the column vector of exponents of x on the fundamental S-units and the roots of unity if x is a unit, the empty vector otherwise."},
-{"bnfisunit",0,(void*)bnfisunit,6,"GG","bnfisunit(bnf,x): bnf being output by bnfinit, gives the column vector of exponents of x on the fundamental units and the roots of unity if x is a unit, the empty vector otherwise."},
-{"bnfnarrow",0,(void*)buchnarrow,6,"G","bnfnarrow(bnf): given a big number field as output by bnfinit, gives as a 3-component vector the structure of the narrow class group."},
-{"bnfsignunit",0,(void*)signunits,6,"G","bnfsignunit(bnf): matrix of signs of the real embeddings of the system of fundamental units found by bnfinit."},
-{"bnfsunit",0,(void*)bnfsunit,6,"GGp","bnfsunit(bnf,S): compute the fundamental S-units of the number field bnf output by bnfinit, S being a list of prime ideals. res[1] contains the S-units, res[5] the S-classgroup. See manual for details."},
-{"bnrL1",0,(void*)bnrL1,6,"GDGD0,L,p","bnrL1(bnr, {H}, {flag=0}): bnr being output by bnrinit(,,1) and H being a square matrix defining a congruence subgroup of bnr (the trivial subgroup if omitted), for each character of bnr trivial on this subgroup, compute L(1, chi) (or equivalently the first non-zero term c(chi) of the expansion at s = 0). The binary digits of flag mean 1: if 0 then compute the term c(chi) and return [r(chi), c(chi)] where r(chi) is the order of L(s, chi) at s = 0, o [...]
-{"bnrclassno",0,(void*)bnrclassno0,6,"GDGDG","bnrclassno(A,{B},{C}): relative degree of the class field defined by A,B,C. [A,{B},{C}] is of type [bnr], [bnr,subgroup], [bnf,modulus], or [bnf,modulus,subgroup]. Faster than bnrinit if only the ray class number is wanted."},
-{"bnrclassnolist",0,(void*)bnrclassnolist,6,"GG","bnrclassnolist(bnf,list): if list is as output by ideallist or similar, gives list of corresponding ray class numbers."},
-{"bnrconductor",0,(void*)bnrconductor0,6,"GDGDGD0,L,","bnrconductor(A,{B},{C},{flag=0}): conductor f of the subfield of the ray class field given by A,B,C. flag is optional and can be 0: default, 1: returns [f, Cl_f, H], H subgroup of the ray class group modulo f defining the extension, 2: returns [f, bnr(f), H]."},
-{"bnrconductorofchar",0,(void*)bnrconductorofchar,6,"GG","bnrconductorofchar(bnr,chi): conductor of the character chi on the ray class group bnr."},
-{"bnrdisc",0,(void*)bnrdisc0,6,"GDGDGD0,L,","bnrdisc(A,{B},{C},{flag=0}): absolute or relative [N,R1,discf] of the field defined by A,B,C. [A,{B},{C}] is of type [bnr], [bnr,subgroup], [bnf, modulus] or [bnf,modulus,subgroup], where bnf is as output by bnfinit, bnr by bnrinit, and subgroup is the HNF matrix of a subgroup of the corresponding ray class group (if omitted, the trivial subgroup). flag is optional whose binary digits mean 1: give relative data; 2: return 0 if modulus is not t [...]
-{"bnrdisclist",0,(void*)bnrdisclist0,6,"GGDG","bnrdisclist(bnf,bound,{arch}): gives list of discriminants of ray class fields of all conductors up to norm bound, in a long vector The ramified Archimedean places are given by arch; all possible values are taken if arch is omitted. Supports the alternative syntax bnrdisclist(bnf,list), where list is as output by ideallist or ideallistarch (with units)."},
-{"bnrinit",0,(void*)bnrinit0,6,"GGD0,L,","bnrinit(bnf,f,{flag=0}): given a bnf as output by bnfinit and a modulus f, initializes data linked to the ray class group structure corresponding to this module. flag is optional, and can be 0: default, 1: compute also the generators."},
-{"bnrisconductor",0,(void*)bnrisconductor0,6,"lGDGDG","bnrisconductor(A,{B},{C}): returns 1 if the modulus is the conductor of the subfield of the ray class field given by A,B,C (see bnrdisc), and 0 otherwise. Slightly faster than bnrconductor if this is the only desired result."},
-{"bnrisprincipal",0,(void*)bnrisprincipal,6,"GGD1,L,","bnrisprincipal(bnr,x,{flag=1}): bnr being output by bnrinit, gives [v,alpha], where v is the vector of exponents on the class group generators and alpha is the generator of the resulting principal ideal. In particular x is principal if and only if v is the zero vector. If (optional) flag is set to 0, output only v."},
-{"bnrrootnumber",0,(void*)bnrrootnumber,6,"GGD0,L,p","bnrrootnumber(bnr,chi,{flag=0}): returns the so-called Artin Root Number, i.e. the constant W appearing in the functional equation of the Hecke L-function associated to chi. Set flag = 1 if the character is known to be primitive."},
-{"bnrstark",0,(void*)bnrstark,6,"GDGp","bnrstark(bnr,{subgroup}): bnr being as output by bnrinit(,,1), finds a relative equation for the class field corresponding to the module in bnr and the given congruence subgroup (the trivial subgroup if omitted) using Stark's units. The ground field and the class field must be totally real."},
-{"break",0,(void*)break0,11,"D1,L,","break({n=1}): interrupt execution of current instruction sequence, and exit from the n innermost enclosing loops."},
+{"bnfcertify",0,(void*)bnfcertify0,7,"lGD0,L,","bnfcertify(bnf,{flag = 0}): certify the correctness (i.e. remove the GRH) of the bnf data output by bnfinit. If flag is present, only certify that the class group is a quotient of the one computed in bnf (much simpler in general)."},
+{"bnfcompress",0,(void*)bnfcompress,7,"G","bnfcompress(bnf): converts bnf to a much smaller sbnf, containing the same information. Use bnfinit(sbnf) to recover a true bnf."},
+{"bnfdecodemodule",0,(void*)decodemodule,7,"GG","bnfdecodemodule(nf,m): given a coded module m as in bnrdisclist, gives the true module."},
+{"bnfinit",0,(void*)bnfinit0,7,"GD0,L,DGp","bnfinit(P,{flag=0},{tech=[]}): compute the necessary data for future use in ideal and unit group computations, including fundamental units if they are not too large. flag and tech are both optional. flag can be any of 0: default, 1: insist on having fundamental units. See manual for details about tech."},
+{"bnfisintnorm",0,(void*)bnfisintnorm,7,"GG","bnfisintnorm(bnf,x): compute a complete system of solutions (modulo units of positive norm) of the absolute norm equation N(a)=x, where a belongs to the maximal order of big number field bnf (if bnf is not certified, this depends on GRH)."},
+{"bnfisnorm",0,(void*)bnfisnorm,7,"GGD1,L,","bnfisnorm(bnf,x,{flag=1}): Tries to tell whether x (in Q) is the norm of some fractional y (in bnf). Returns a vector [a,b] where x=Norm(a)*b. Looks for a solution which is a S-unit, with S a certain list of primes (in bnf) containing (among others) all primes dividing x. If bnf is known to be Galois, set flag=0 (in this case, x is a norm iff b=1). If flag is non zero the program adds to S all the primes: dividing flag if flag<0, or less than  [...]
+{"bnfisprincipal",0,(void*)bnfisprincipal0,7,"GGD1,L,","bnfisprincipal(bnf,x,{flag=1}): bnf being output by bnfinit (with flag<=2), gives [v,alpha], where v is the vector of exponents on the class group generators and alpha is the generator of the resulting principal ideal. In particular x is principal if and only if v is the zero vector. flag is optional, whose binary digits mean 1: output [v,alpha] (only v if unset); 2: increase precision until alpha can be computed (do not insist if u [...]
+{"bnfissunit",0,(void*)bnfissunit,7,"GGG","bnfissunit(bnf,sfu,x): bnf being output by bnfinit (with flag<=2), sfu by bnfsunit, gives the column vector of exponents of x on the fundamental S-units and the roots of unity if x is a unit, the empty vector otherwise."},
+{"bnfisunit",0,(void*)bnfisunit,7,"GG","bnfisunit(bnf,x): bnf being output by bnfinit, gives the column vector of exponents of x on the fundamental units and the roots of unity if x is a unit, the empty vector otherwise."},
+{"bnfnarrow",0,(void*)buchnarrow,7,"G","bnfnarrow(bnf): given a big number field as output by bnfinit, gives as a 3-component vector the structure of the narrow class group."},
+{"bnfsignunit",0,(void*)signunits,7,"G","bnfsignunit(bnf): matrix of signs of the real embeddings of the system of fundamental units found by bnfinit."},
+{"bnfsunit",0,(void*)bnfsunit,7,"GGp","bnfsunit(bnf,S): compute the fundamental S-units of the number field bnf output by bnfinit, S being a list of prime ideals. res[1] contains the S-units, res[5] the S-classgroup. See manual for details."},
+{"bnrL1",0,(void*)bnrL1,7,"GDGD0,L,p","bnrL1(bnr, {H}, {flag=0}): bnr being output by bnrinit(,,1) and H being a square matrix defining a congruence subgroup of bnr (the trivial subgroup if omitted), for each character of bnr trivial on this subgroup, compute L(1, chi) (or equivalently the first non-zero term c(chi) of the expansion at s = 0). The binary digits of flag mean 1: if 0 then compute the term c(chi) and return [r(chi), c(chi)] where r(chi) is the order of L(s, chi) at s = 0, o [...]
+{"bnrclassno",0,(void*)bnrclassno0,7,"GDGDG","bnrclassno(A,{B},{C}): relative degree of the class field defined by A,B,C. [A,{B},{C}] is of type [bnr], [bnr,subgroup], [bnf,modulus], or [bnf,modulus,subgroup]. Faster than bnrinit if only the ray class number is wanted."},
+{"bnrclassnolist",0,(void*)bnrclassnolist,7,"GG","bnrclassnolist(bnf,list): if list is as output by ideallist or similar, gives list of corresponding ray class numbers."},
+{"bnrconductor",0,(void*)bnrconductor0,7,"GDGDGD0,L,","bnrconductor(A,{B},{C},{flag=0}): conductor f of the subfield of the ray class field given by A,B,C. flag is optional and can be 0: default, 1: returns [f, Cl_f, H], H subgroup of the ray class group modulo f defining the extension, 2: returns [f, bnr(f), H]."},
+{"bnrconductorofchar",0,(void*)bnrconductorofchar,7,"GG","bnrconductorofchar(bnr,chi): conductor of the character chi on the ray class group bnr."},
+{"bnrdisc",0,(void*)bnrdisc0,7,"GDGDGD0,L,","bnrdisc(A,{B},{C},{flag=0}): absolute or relative [N,R1,discf] of the field defined by A,B,C. [A,{B},{C}] is of type [bnr], [bnr,subgroup], [bnf, modulus] or [bnf,modulus,subgroup], where bnf is as output by bnfinit, bnr by bnrinit, and subgroup is the HNF matrix of a subgroup of the corresponding ray class group (if omitted, the trivial subgroup). flag is optional whose binary digits mean 1: give relative data; 2: return 0 if modulus is not t [...]
+{"bnrdisclist",0,(void*)bnrdisclist0,7,"GGDG","bnrdisclist(bnf,bound,{arch}): gives list of discriminants of ray class fields of all conductors up to norm bound, in a long vector The ramified Archimedean places are given by arch; all possible values are taken if arch is omitted. Supports the alternative syntax bnrdisclist(bnf,list), where list is as output by ideallist or ideallistarch (with units)."},
+{"bnrgaloisapply",0,(void*)bnrgaloisapply,7,"GGG","bnrgaloisapply(bnr, mat, H): apply the automorphism given by its matrix mat to the cngruence subgroup H given as a HNF matrix. The matrix mat can be computed with bnrgaloismatrix"},
+{"bnrgaloismatrix",0,(void*)bnrgaloismatrix,7,"GG","bnrgaloismatrix(bnr,aut): return the matrix of the action of the automorphism aut of the base field bnf.nf on the generators of the ray class field bnr.gen. aut can be given as a polynomial, or a vector of automorphisms or a galois group as output by galoisinit, in which case a vector of matrices is returned (in the later case, only for the generators aut.gen)."},
+{"bnrinit",0,(void*)bnrinit0,7,"GGD0,L,","bnrinit(bnf,f,{flag=0}): given a bnf as output by bnfinit and a modulus f, initializes data linked to the ray class group structure corresponding to this module. flag is optional, and can be 0: default, 1: compute also the generators."},
+{"bnrisconductor",0,(void*)bnrisconductor0,7,"lGDGDG","bnrisconductor(A,{B},{C}): returns 1 if the modulus is the conductor of the subfield of the ray class field given by A,B,C (see bnrdisc), and 0 otherwise. Slightly faster than bnrconductor if this is the only desired result."},
+{"bnrisgalois",0,(void*)bnrisgalois,7,"lGGG","bnrisgalois(bnr, gal, H): check whether the class field associated to the subgroup H is Galois over the subfield of bnr.nf fixed by the Galois group gal, which can be given as output by galoisinit, or as a matrix or a vector of matrices as output by bnrgaloismatrix. The ray class field associated to bnr need to be Galois, which is not checked."},
+{"bnrisprincipal",0,(void*)bnrisprincipal,7,"GGD1,L,","bnrisprincipal(bnr,x,{flag=1}): bnr being output by bnrinit, gives [v,alpha], where v is the vector of exponents on the class group generators and alpha is the generator of the resulting principal ideal. In particular x is principal if and only if v is the zero vector. If (optional) flag is set to 0, output only v."},
+{"bnrrootnumber",0,(void*)bnrrootnumber,7,"GGD0,L,p","bnrrootnumber(bnr,chi,{flag=0}): returns the so-called Artin Root Number, i.e. the constant W appearing in the functional equation of the Hecke L-function associated to chi. Set flag = 1 if the character is known to be primitive."},
+{"bnrstark",0,(void*)bnrstark,7,"GDGp","bnrstark(bnr,{subgroup}): bnr being as output by bnrinit(,,1), finds a relative equation for the class field corresponding to the module in bnr and the given congruence subgroup (the trivial subgroup if omitted) using Stark's units. The ground field and the class field must be totally real."},
+{"break",0,(void*)break0,13,"D1,L,","break({n=1}): interrupt execution of current instruction sequence, and exit from the n innermost enclosing loops."},
 {"ceil",0,(void*)gceil,2,"G","ceil(x): ceiling of x = smallest integer >= x."},
 {"centerlift",0,(void*)centerlift0,2,"GDn","centerlift(x,{v}): centered lift of x. Same as lift except for intmod and padic components."},
 {"characteristic",0,(void*)characteristic,2,"mG","characteristic(x): characteristic of the base ring over which x is defined"},
-{"charpoly",0,(void*)charpoly0,8,"GDnD5,L,","charpoly(A,{v='x},{flag=5}): det(v*Id-A)=characteristic polynomial of the matrix or polmod A. flag is optional and ignored unless A is a matrix; it may be set to 0 (Le Verrier), 1 (Lagrange interpolation), 2 (Hessenberg form), 3 (Berkowitz), 4 (modular) if A is integral, or 5 (default, choose best method). Algorithms 0 (Le Verrier) and 1 (Lagrange) assume that n! is invertible, where n is the dimension of the matrix."},
+{"charpoly",0,(void*)charpoly0,10,"GDnD5,L,","charpoly(A,{v='x},{flag=5}): det(v*Id-A)=characteristic polynomial of the matrix or polmod A. flag is optional and ignored unless A is a matrix; it may be set to 0 (Le Verrier), 1 (Lagrange interpolation), 2 (Hessenberg form), 3 (Berkowitz), 4 (modular) if A is integral, or 5 (default, choose best method). Algorithms 0 (Le Verrier) and 1 (Lagrange) assume that n! is invertible, where n is the dimension of the matrix."},
 {"chinese",0,(void*)chinese,4,"GDG","chinese(x,{y}): x,y being both intmods (or polmods) computes z in the same residue classes as x and y."},
 {"cmp",0,(void*)cmp_universal,1,"iGG","cmp(x,y): compare two arbitrary objects x and y (1 if x>y, 0 if x=y, -1 if x<y). The function is used to implement sets, and has no useful mathematical meaning."},
 {"component",0,(void*)compo,2,"GL","component(x,n): the n'th component of the internal representation of x. For vectors or matrices, it is simpler to use x[]. For list objects such as nf, bnf, bnr or ell, it is much easier to use member functions starting with \".\"."},
-{"concat",0,(void*)concat,8,"GDG","concat(x,{y}): concatenation of x and y, which can be scalars, vectors or matrices, or lists (in this last case, both x and y have to be lists). If y is omitted, x has to be a list or row vector and its elements are concatenated."},
+{"concat",0,(void*)concat,10,"GDG","concat(x,{y}): concatenation of x and y, which can be scalars, vectors or matrices, or lists (in this last case, both x and y have to be lists). If y is omitted, x has to be a list or row vector and its elements are concatenated."},
 {"conj",0,(void*)gconj,2,"G","conj(x): the algebraic conjugate of x."},
 {"conjvec",0,(void*)conjvec,2,"Gp","conjvec(z): conjugate vector of the algebraic number z."},
 {"content",0,(void*)content,4,"G","content(x): gcd of all the components of x, when this makes sense."},
@@ -210,28 +271,28 @@ entree functions_basic[]={
 {"cos",0,(void*)gcos,3,"Gp","cos(x): cosine of x."},
 {"cosh",0,(void*)gcosh,3,"Gp","cosh(x): hyperbolic cosine of x."},
 {"cotan",0,(void*)gcotan,3,"Gp","cotan(x): cotangent of x."},
-{"dbg_x",0,(void*)dbgGEN,11,"vGD-1,L,","dbg_x(A{,n}): print inner structure of A, complete if n is omitted, up to level n otherwise. Intended for debugging."},
-{"default",0,(void*)default0,11,"DrDs","default({key},{val}): returns the current value of the default key. If val is present, set opt to val first. If no argument is given, print a list of all defaults as well as their values."},
+{"dbg_x",0,(void*)dbgGEN,13,"vGD-1,L,","dbg_x(A{,n}): print inner structure of A, complete if n is omitted, up to level n otherwise. Intended for debugging."},
+{"default",0,(void*)default0,13,"DrDs","default({key},{val}): returns the current value of the default key. If val is present, set opt to val first. If no argument is given, print a list of all defaults as well as their values."},
 {"denominator",0,(void*)denom,2,"G","denominator(x): denominator of x (or lowest common denominator in case of an array)."},
-{"deriv",0,(void*)deriv,7,"GDn","deriv(x,{v}): derivative of x with respect to v, or to the main variable of x if v is omitted."},
-{"derivnum",0,(void*)derivnum0,9,"V=GEp","derivnum(X=a,expr): numerical derivation of expr with respect to X at X = a."},
-{"diffop",0,(void*)diffop0,7,"GGGD1,L,","diffop(x,v,d,{n=1}): apply the differential operator D to x, where D is defined by D(v[i])=d[i], where v is a vector of variable names. D is 0 for variables outside of v unless they appear as modulus of a POLMOD. If the optional parameter n is given, return D^n(x) instead."},
+{"deriv",0,(void*)deriv,9,"GDn","deriv(x,{v}): derivative of x with respect to v, or to the main variable of x if v is omitted."},
+{"derivnum",0,(void*)derivnum0,11,"V=GEp","derivnum(X=a,expr): numerical derivation of expr with respect to X at X = a."},
+{"diffop",0,(void*)diffop0,9,"GGGD1,L,","diffop(x,v,d,{n=1}): apply the differential operator D to x, where D is defined by D(v[i])=d[i], where v is a vector of variable names. D is 0 for variables outside of v unless they appear as modulus of a POLMOD. If the optional parameter n is given, return D^n(x) instead."},
 {"digits",0,(void*)digits,2,"GDG","digits(x,{b=10}): gives the vector formed by the digits of x in base b (x and b integers)."},
 {"dilog",0,(void*)dilog,3,"Gp","dilog(x): dilogarithm of x."},
 {"dirdiv",0,(void*)dirdiv,4,"GG","dirdiv(x,y): division of the Dirichlet series x by the Dirichlet series y."},
 {"direuler",0,(void*)direuler0,4,"V=GGEDG","direuler(p=a,b,expr,{c}): Dirichlet Euler product of expression expr from p=a to p=b, limited to b terms. Expr should be a polynomial or rational function in p and X, and X is understood to mean p^(-s). If c is present, output only the first c terms."},
 {"dirmul",0,(void*)dirmul,4,"GG","dirmul(x,y): multiplication of the Dirichlet series x by the Dirichlet series y."},
-{"dirzetak",0,(void*)dirzetak,6,"GG","dirzetak(nf,b): Dirichlet series of the Dedekind zeta function of the number field nf up to the bound b-1."},
+{"dirzetak",0,(void*)dirzetak,7,"GG","dirzetak(nf,b): Dirichlet series of the Dedekind zeta function of the number field nf up to the bound b-1."},
 {"divisors",0,(void*)divisors,4,"G","divisors(x): gives a vector formed by the divisors of x in increasing order."},
 {"divrem",0,(void*)divrem,1,"GGDn","divrem(x,y,{v}): euclidean division of x by y giving as a 2-dimensional column vector the quotient and the remainder, with respect to v (to main variable if v is omitted)"},
 {"eint1",0,(void*)veceint1,3,"GDGp","eint1(x,{n}): exponential integral E1(x). If n is present and x > 0, computes the vector of the first n values of the exponential integral E1(n.x)"},
-{"ellL1",0,(void*)ellL1,5,"GLp","ellL1(e, r): returns the value at s=1 of the derivative of order r of the L-function of the elliptic curve e assuming that r is at most the order of vanishing of the function at s=1."},
+{"ellL1",0,(void*)ellL1,5,"GD0,L,p","ellL1(e, {r = 0}): returns the value at s=1 of the derivative of order r of the L-function of the elliptic curve e assuming that r is at most the order of vanishing of the function at s=1."},
 {"elladd",0,(void*)elladd,5,"GGG","elladd(E,z1,z2): sum of the points z1 and z2 on elliptic curve E."},
 {"ellak",0,(void*)akell,5,"GG","ellak(E,n): computes the n-th Fourier coefficient of the L-function of the elliptic curve E (assumed E is an integral model)."},
 {"ellan",0,(void*)anell,5,"GL","ellan(E,n): computes the first n Fourier coefficients of the L-function of the elliptic curve E (n<2^24 on a 32-bit machine)."},
 {"ellanalyticrank",0,(void*)ellanalyticrank,5,"GDGp","ellanalyticrank(e, {eps}): returns the order of vanishing at s=1 of the L-function of the elliptic curve e and the value of the first non-zero derivative. To determine this order, it is assumed that any value less than eps is zero. If no value of eps is given, a value of half the current precision is used."},
 {"ellap",0,(void*)ellap,5,"GDG","ellap(E,{p}): computes the trace of Frobenius a_p for the elliptic curve E, defined over Q or a finite field."},
-{"ellbil",0,(void*)bilhell,5,"GGGp","ellbil(E,z1,z2): canonical bilinear form for the points z1,z2 on the elliptic curve E. Either z1 or z2 can also be a vector/matrix of points."},
+{"ellbil",0,(void*)bilhell,5,"GGGp","ellbil(E,z1,z2): deprecated alias for ellheight(E,P,Q)."},
 {"ellcard",0,(void*)ellcard,5,"GDG","ellcard(E,{p}): computes the order of the group E(Fp) for the elliptic curve E, defined over Q or a finite field."},
 {"ellchangecurve",0,(void*)ellchangecurve,5,"GG","ellchangecurve(E,v): change data on elliptic curve according to v=[u,r,s,t]."},
 {"ellchangepoint",0,(void*)ellchangepoint,5,"GG","ellchangepoint(x,v): change data on point or vector of points x on an elliptic curve according to v=[u,r,s,t]."},
@@ -240,16 +301,25 @@ entree functions_basic[]={
 {"elldivpol",0,(void*)elldivpol,5,"GLDn","elldivpol(E,n,{v='x}): n-division polynomial f_n for the curve E in the variable v."},
 {"elleisnum",0,(void*)elleisnum,5,"GLD0,L,p","elleisnum(w,k,{flag=0}): k being an even positive integer, computes the numerical value of the Eisenstein series of weight k at the lattice w, as given by ellperiods. When flag is non-zero and k=4 or 6, this gives the elliptic invariants g2 or g3 with the correct normalization."},
 {"elleta",0,(void*)elleta,5,"Gp","elleta(w): w=[w1,w2], returns the vector [eta1,eta2] of quasi-periods associated to [w1,w2]."},
+{"ellformaldifferential",0,(void*)ellformaldifferential,5,"GDPDn","ellformaldifferential(E, {n=seriesprecision}, {t = 'x}) : E elliptic curve, n integer. Returns n terms of the power series [f, g] such that omega = dx/(2y+a_1x+a_3) = f(t) dt and eta = x(t) * omega = g(t) dt in the local parameter t=-x/y."},
+{"ellformalexp",0,(void*)ellformalexp,5,"GDPDn","ellformalexp(E, {n = seriesprecision}, {z = 'x}) : E elliptic curve, returns n terms of the formal elliptic exponential on E as a series in z"},
+{"ellformallog",0,(void*)ellformallog,5,"GDPDn","ellformallog(E, {n = seriesprecision}, {v = 't}): E elliptic curve, returns n terms of the elliptic logarithm as a series of t =-x/y."},
+{"ellformalpoint",0,(void*)ellformalpoint,5,"GDPDn","ellformalpoint(E, {n = seriesprecision}, {v = 'x}): E elliptic curve, n integer; return the coordinates [x(t), y(t)] on the elliptic curve as a formal expansion in the formal parameter t = -x/y."},
+{"ellformalw",0,(void*)ellformalw,5,"GDPDn","ellformalw(E, {n = seriesprecision}, {t = 'x}): E elliptic curve, n integer; returns n terms of the formal expansion of w = -1/y in the formal parameter t = -x/y."},
 {"ellfromj",0,(void*)ellfromj,5,"G","ellfromj(j): returns the coefficients [a1,a2,a3,a4,a6] of a fixed elliptic curve with j-invariant j."},
 {"ellgenerators",0,(void*)ellgenerators,5,"G","ellgenerators(E): If E is an elliptic curve over the rationals, return the generators of the Mordell-Weil group associated to the curve. This relies on the curve being referenced in the elldata database. If E is an elliptic curve over a finite field Fq as output by ellinit(), return a minimal set of generators for the group E(Fq)."},
 {"ellglobalred",0,(void*)ellglobalred,5,"G","ellglobalred(E): E being an elliptic curve, returns [N,[u,r,s,t],c, faN,L], where N is the conductor of E, [u,r,s,t] leads to the standard model for E, c is the product of the local Tamagawa numbers c_p, faN is factor(N) and L[i] is elllocalred(E, faN[i,1])."},
 {"ellgroup",0,(void*)ellgroup0,5,"GDGD0,L,","ellgroup(E,{p},{flag}): computes the structure of the group E(Fp) If flag is 1, return also generators."},
 {"ellheegner",0,(void*)ellheegner,5,"G","ellheegner(E): return a rational non-torsion point on the elliptic curve E assumed to be of rank 1"},
-{"ellheight",0,(void*)ellheight0,5,"GGD2,L,p","ellheight(E,x,{flag=2}): canonical height of point x on elliptic curve E. flag is optional and selects the algorithm used to compute the Archimedean local height. Its meaning is 0: use theta-functions, 1: use Tate's method, 2: use Mestre's AGM."},
-{"ellheightmatrix",0,(void*)mathell,5,"GGp","ellheightmatrix(E,x): gives the height matrix for vector of points x on elliptic curve E."},
+{"ellheight",0,(void*)ellheight0,5,"GGDGp","ellheight(E,P,{Q}): canonical height of point P on elliptic curve E, resp. the value of the associated bilinear form at (P,Q)."},
+{"ellheightmatrix",0,(void*)ellheightmatrix,5,"GGp","ellheightmatrix(E,x): gives the height matrix for vector of points x on elliptic curve E."},
 {"ellidentify",0,(void*)ellidentify,5,"G","ellidentify(E): look up the elliptic curve E in the elldata database and return [[N, M, ...], C] where N is the name of the curve in Cremona's database, M the minimal model and C the coordinates change (see ellchangecurve)."},
 {"ellinit",0,(void*)ellinit,5,"GDGp","ellinit(x,{D=1}): let x be a vector [a1,a2,a3,a4,a6], or [a4,a6] if a1=a2=a3=0, defining the curve Y^2 + a1.XY + a3.Y = X^3 + a2.X^2 + a4.X + a6; x can also be a string, in which case the curve with matching name is retrieved from the elldata database, if available. This function initializes an elliptic curve over the domain D (inferred from coefficients if omitted)."},
+{"ellisdivisible",0,(void*)ellisdivisible,5,"lGGGD&","ellisdivisible(E,P,n,{&Q})): given E/K and P in E(K), checks whether P = [n]R for some R in E(K) and sets Q to one such R if so; the integer n >= 0 may be given as ellxn(E,n)"},
+{"ellisogeny",0,(void*)ellisogeny,5,"GGD0,L,DnDn","ellisogeny(E, G, {only_image = 0}, {x = 'x}, {y = 'y}): compute the image and isogeny corresponding to the quotient of E by the subgroup G."},
+{"ellisogenyapply",0,(void*)ellisogenyapply,5,"GG","ellisogenyapply(f, g): Given an isogeny f and g either a point P (in the domain of f) or an isogeny, apply f to x: return the image of P under f or the composite isogeny fog."},
 {"ellisoncurve",0,(void*)ellisoncurve,5,"GG","ellisoncurve(E,z): true(1) if z is on elliptic curve E, false(0) if not."},
+{"ellissupersingular",0,(void*)ellissupersingular,5,"iGDG","ellissupersingular(E,{p}): return whether the elliptic curve E, defined over Q or a finite field, is supersingular at p or not."},
 {"ellj",0,(void*)jell,5,"Gp","ellj(x): elliptic j invariant of x."},
 {"elllocalred",0,(void*)elllocalred,5,"GG","elllocalred(E,p): E being an elliptic curve, returns [f,kod,[u,r,s,t],c], where f is the conductor's exponent, kod is the Kodaira type for E at p, [u,r,s,t] is the change of variable needed to make E minimal at p, and c is the local Tamagawa number c_p."},
 {"elllog",0,(void*)elllog,5,"GGGDG","elllog(E,P,G,{o}): return the discrete logarithm of the point P of the elliptic curve E in base G. If present, o represents the order of G. If not present, assume that G generates the curve."},
@@ -258,8 +328,15 @@ entree functions_basic[]={
 {"ellmodulareqn",0,(void*)ellmodulareqn,5,"LDnDn","ellmodulareqn(N,{x},{y}): return a vector [eqn, t] where eqn is a modular equation of level N, for N<500, N prime. This requires the package seadata to be installed.  The equation is either of canonical type (t=0) or of Atkin type (t=1)"},
 {"ellmul",0,(void*)ellmul,5,"GGG","ellmul(E,z,n): n times the point z on elliptic curve E (n in Z)."},
 {"ellneg",0,(void*)ellneg,5,"GG","ellneg(E,z): opposite of the point z on elliptic curve E."},
-{"ellorder",0,(void*)ellorder,5,"GGDG","ellorder(E,z,{o}): order of the point z on the elliptic curve E over Q or a finite field, 0 if non-torsion. The parameter o, if present, represents a non-zero multiple of the order of z."},
+{"ellnonsingularmultiple",0,(void*)ellnonsingularmultiple,5,"GG","ellnonsingularmultiple(E,P):"},
+{"ellorder",0,(void*)ellorder,5,"GGDG","ellorder(E,z,{o}): order of the point z on the elliptic curve E over a number field or a finite field, 0 if non-torsion. The parameter o, if present, represents a non-zero multiple of the order of z."},
 {"ellordinate",0,(void*)ellordinate,5,"GGp","ellordinate(E,x): y-coordinates corresponding to x-ordinate x on elliptic curve E."},
+{"ellpadicL",0,(void*)ellpadicL,5,"GGLD0,L,DGDG","ellpadicL(E, p, n, {r = 0}, {D}, {char}): returns the value  on a character of the derivative of order r of the L-function of  the elliptic curve E (twisted by D > 0, if present). For the moment, only  the case of the trivial character is implemented"},
+{"ellpadicfrobenius",0,(void*)ellpadicfrobenius,5,"GLL","ellpadicfrobenius(E,p,n): matrix of the Frobenius at p>2 in the standard basis of H^1_dR(E) to absolute p-adic precision p^n."},
+{"ellpadicheight",0,(void*)ellpadicheight0,5,"GGLGDG","ellpadicheight(E, p,n, P,{Q}): E elliptic curve/Q, P in E(Q), p prime, n an integer; returns the cyclotomic p-adic heights of P. Resp. the value of the associated bilinear form at (P,Q)."},
+{"ellpadicheightmatrix",0,(void*)ellpadicheightmatrix,5,"GGLG","ellpadicheightmatrix(E,p,n,v): gives the height-pairing matrix for vector of points v on elliptic curve E."},
+{"ellpadiclog",0,(void*)ellpadiclog,5,"GGLG","ellpadiclog(E,p,n,P): returns the logarithm of P (in the kernel of reduction) to absolute p-adic precision p^n."},
+{"ellpadics2",0,(void*)ellpadics2,5,"GGL","ellpadics2(E,p,n): returns s2 to absolute p-adic precision p^n"},
 {"ellperiods",0,(void*)ellperiods,5,"GD0,L,p","ellperiods(w, {flag = 0}): w describes a complex period lattice ([w1,w2] or an ellinit structure). Returns normalized periods [W1,W2] generating the same lattice such that tau := W1/W2 satisfies Im(tau) > 0 and lies in the standard fundamental domain for SL2. If flag is 1, the return value is [[W1,W2], [eta1,eta2]], where eta1, eta2 are the quasi-periods associated to [W1,W2], satisfying eta1 W2 - eta2 W1 = 2 I Pi."},
 {"ellpointtoz",0,(void*)zell,5,"GGp","ellpointtoz(E,P): lattice point z corresponding to the point P on the elliptic curve E."},
 {"ellpow",0,(void*)ellmul,5,"GGG","ellpow(E,z,n): deprecated alias for ellmul."},
@@ -269,19 +346,22 @@ entree functions_basic[]={
 {"ellsub",0,(void*)ellsub,5,"GGG","ellsub(E,z1,z2): difference of the points z1 and z2 on elliptic curve E."},
 {"elltaniyama",0,(void*)elltaniyama,5,"GDP","elltaniyama(E, {d = seriesprecision}): modular parametrization of elliptic curve E/Q."},
 {"elltatepairing",0,(void*)elltatepairing,5,"GGGG","elltatepairing(E, P, Q, m): Computes the Tate pairing of the two points P and Q on the elliptic curve E. The point P must be of m-torsion."},
-{"elltors",0,(void*)elltors0,5,"GD0,L,","elltors(E,{flag=0}): torsion subgroup of elliptic curve E: order, structure, generators. If flag = 0, use division polynomials; if flag = 1, use Lutz-Nagell; if flag = 2, use Doud's algorithm."},
+{"elltors",0,(void*)elltors,5,"G","elltors(E): torsion subgroup of elliptic curve E: order, structure, generators."},
 {"ellweilpairing",0,(void*)ellweilpairing,5,"GGGG","ellweilpairing(E, P, Q, m): Computes the Weil pairing of the two points of m-torsion P and Q on the elliptic curve E."},
 {"ellwp",0,(void*)ellwp0,5,"GDGD0,L,p","ellwp(w,{z='x},{flag=0}): computes the value at z of the Weierstrass P function attached to the lattice w, as given by ellperiods. Optional flag means 0 (default), compute only P(z), 1 compute [P(z),P'(z)]."},
+{"ellxn",0,(void*)ellxn,5,"GLDn","ellxn(E,n,{v='x}): polynomials [phi_n, (psi_n)^2] in variable v, where x([n]P) = phi_n/(psi_n)^2"},
 {"ellzeta",0,(void*)ellzeta,5,"GDGp","ellzeta(w,{z='x}): computes the value at z of the Weierstrass Zeta function attached to the lattice w, as given by ellperiods(,1)."},
 {"ellztopoint",0,(void*)pointell,5,"GGp","ellztopoint(E,z): coordinates of point P on the curve E corresponding to the complex number z."},
 {"erfc",0,(void*)gerfc,3,"Gp","erfc(x): complementary error function."},
-{"errname",0,(void*)errname,11,"G","errname(E): returns the type of the error message E."},
-{"error",0,(void*)error0,11,"vs*","error({str}*): abort script with error message str."},
+{"errname",0,(void*)errname,13,"G","errname(E): returns the type of the error message E."},
+{"error",0,(void*)error0,13,"vs*","error({str}*): abort script with error message str."},
 {"eta",0,(void*)eta0,3,"GD0,L,p","eta(z,{flag=0}): if flag=0, returns prod(n=1,oo, 1-q^n), where q = exp(2 i Pi z) if z is a complex scalar (belonging to the upper half plane); q = z if z is a p-adic number or can be converted to a power series. If flag is non-zero, the function only applies to complex scalars and returns the true eta function, with the factor q^(1/24) included."},
 {"eulerphi",0,(void*)eulerphi,4,"G","eulerphi(x): Euler's totient function of x."},
-{"eval",0,(void*)geval_gp,7,"GC","eval(x): evaluation of x, replacing variables by their value."},
+{"eval",0,(void*)geval_gp,9,"GC","eval(x): evaluation of x, replacing variables by their value."},
 {"exp",0,(void*)gexp,3,"Gp","exp(x): exponential of x."},
 {"expm1",0,(void*)gexpm1,3,"Gp","expm1(x): exp(x)-1."},
+{"extern",0,(void*)gpextern,13,"s","extern(str): execute shell command str, and feeds the result to GP (as if loading from file)."},
+{"externstr",0,(void*)externstr,13,"s","externstr(str): execute shell command str, and returns the result as a vector of GP strings, one component per output line."},
 {"factor",0,(void*)gp_factor0,4,"GDG","factor(x,{lim}): factorization of x. lim is optional and can be set whenever x is of (possibly recursive) rational type. If lim is set return partial factorization, using primes < lim."},
 {"factorback",0,(void*)factorback2,4,"GDG","factorback(f,{e}): given a factorisation f, gives the factored object back. If this is a prime ideal factorisation you must supply the corresponding number field as last argument. If e is present, f has to be a vector of the same length, and we return the product of the f[i]^e[i]."},
 {"factorcantor",0,(void*)factcantor,4,"GG","factorcantor(x,p): factorization mod p of the polynomial x using Cantor-Zassenhaus."},
@@ -289,8 +369,8 @@ entree functions_basic[]={
 {"factorial",0,(void*)mpfactr,4,"Lp","factorial(x): factorial of x, the result being given as a real number."},
 {"factorint",0,(void*)factorint,4,"GD0,L,","factorint(x,{flag=0}): factor the integer x. flag is optional, whose binary digits mean 1: avoid MPQS, 2: avoid first-stage ECM (may fall back on it later), 4: avoid Pollard-Brent Rho and Shanks SQUFOF, 8: skip final ECM (huge composites will be declared prime)."},
 {"factormod",0,(void*)factormod0,4,"GGD0,L,","factormod(x,p,{flag=0}): factors the polynomial x modulo the prime p, using Berlekamp. flag is optional, and can be 0: default or 1: only the degrees of the irreducible factors are given."},
-{"factornf",0,(void*)polfnf,6,"GG","factornf(x,t): factorization of the polynomial x over the number field defined by the polynomial t."},
-{"factorpadic",0,(void*)factorpadic0,7,"GGLD0,L,","factorpadic(pol,p,r): p-adic factorization of the polynomial pol to precision r."},
+{"factornf",0,(void*)polfnf,7,"GG","factornf(x,t): factorization of the polynomial x over the number field defined by the polynomial t."},
+{"factorpadic",0,(void*)factorpadic,9,"GGL","factorpadic(pol,p,r): p-adic factorization of the polynomial pol to precision r."},
 {"ffgen",0,(void*)ffgen,4,"GDn","ffgen(q,{v}): return a generator X mod P(X) for the finite field with q elements. If v is given, the variable name is used to display g, else the variable 'x' is used. Alternative syntax, q = P(X) an irreducible polynomial with t_INTMOD coefficients, return the generator X mod P(X) of the finite field defined by P. If v is given, the variable name is used to display g, else the variable of the polynomial P is used."},
 {"ffinit",0,(void*)ffinit,4,"GLDn","ffinit(p,n,{v='x}): monic irreducible polynomial of degree n over F_p[v]."},
 {"fflog",0,(void*)fflog,4,"GGDG","fflog(x,g,{o}): return the discrete logarithm of the finite field element x in base g. If present, o must represents the multiplicative order of g. If no o is given, assume that g is a primitive root."},
@@ -299,305 +379,338 @@ entree functions_basic[]={
 {"ffprimroot",0,(void*)ffprimroot,4,"GD&","ffprimroot(x, {&o}): return a primitive root of the multiplicative group of the definition field of the finite field element x (not necessarily the same as the field generated by x). If present, o is set to [ord, fa], where ord is the order of the group, and fa its factorization (useful in fflog and fforder)."},
 {"fibonacci",0,(void*)fibo,4,"L","fibonacci(x): fibonacci number of index x (x C-integer)."},
 {"floor",0,(void*)gfloor,2,"G","floor(x): floor of x = largest integer <= x."},
-{"for",0,(void*)forpari,11,"vV=GGI","for(X=a,b,seq): the sequence is evaluated, X going from a up to b."},
-{"forcomposite",0,(void*)forcomposite,11,"vV=GDGI","forcomposite(n=a,{b},seq): the sequence is evaluated, n running over the composite numbers between a and b. Omitting b runs through composites >= a"},
-{"fordiv",0,(void*)fordiv,11,"vGVI","fordiv(n,X,seq): the sequence is evaluated, X running over the divisors of n."},
-{"forell",0,(void*)forell0,11,"vVLLI","forell(E,a,b,seq): execute seq for each elliptic curves E of conductor between a and b in the elldata database."},
-{"forpart",0,(void*)forpart0,11,"vV=GIDGDG","forpart(X=k,seq,{a=k},{n=k}): evaluate seq where the Vecsmall X goes over the partitions of k. Optional parameter n (n=nmax or n=[nmin,nmax]) restricts the length of the partition. Optional parameter a (a=amax or a=[amin,amax]) restricts the range of the parts. Zeros are removed unless one sets amin=0 to get X of fixed length nmax (=k by default)."},
-{"forprime",0,(void*)forprime,11,"vV=GDGI","forprime(p=a,{b},seq): the sequence is evaluated, p running over the primes between a and b. Omitting b runs through primes >= a"},
-{"forqfvec",0,(void*)forqfvec0,8,"vVGDGI","forqfvec(v,q,b,expr): q being a square and symmetric matrix representing a positive definite quadratic form, evaluate expr for all vector v such that q(v)<=b."},
-{"forstep",0,(void*)forstep,11,"vV=GGGI","forstep(X=a,b,s,seq): the sequence is evaluated, X going from a to b in steps of s (can be a vector of steps)."},
-{"forsubgroup",0,(void*)forsubgroup0,11,"vV=GDGI","forsubgroup(H=G,{bound},seq): execute seq for each subgroup H of the abelian group G, whose index is bounded by bound if not omitted. H is given as a left divisor of G in HNF form."},
-{"forvec",0,(void*)forvec,11,"vV=GID0,L,","forvec(X=v,seq,{flag=0}): v being a vector of two-component vectors of length n, the sequence is evaluated with X[i] going from v[i][1] to v[i][2] for i=n,..,1 if flag is zero or omitted. If flag = 1 (resp. flag = 2), restrict to increasing (resp. strictly increasing) sequences."},
+{"fold",0,(void*)fold0,13,"GG","fold(f, A): return f(...f(f(A[1],A[2]),A[3]),...,A[#A])"},
+{"for",0,(void*)forpari,13,"vV=GGI","for(X=a,b,seq): the sequence is evaluated, X going from a up to b."},
+{"forcomposite",0,(void*)forcomposite,13,"vV=GDGI","forcomposite(n=a,{b},seq): the sequence is evaluated, n running over the composite numbers between a and b. Omitting b runs through composites >= a"},
+{"fordiv",0,(void*)fordiv,13,"vGVI","fordiv(n,X,seq): the sequence is evaluated, X running over the divisors of n."},
+{"forell",0,(void*)forell0,13,"vVLLI","forell(E,a,b,seq): execute seq for each elliptic curves E of conductor between a and b in the elldata database."},
+{"forpart",0,(void*)forpart0,13,"vV=GIDGDG","forpart(X=k,seq,{a=k},{n=k}): evaluate seq where the Vecsmall X goes over the partitions of k. Optional parameter n (n=nmax or n=[nmin,nmax]) restricts the length of the partition. Optional parameter a (a=amax or a=[amin,amax]) restricts the range of the parts. Zeros are removed unless one sets amin=0 to get X of fixed length nmax (=k by default)."},
+{"forprime",0,(void*)forprime,13,"vV=GDGI","forprime(p=a,{b},seq): the sequence is evaluated, p running over the primes between a and b. Omitting b runs through primes >= a"},
+{"forqfvec",0,(void*)forqfvec0,10,"vVGDGI","forqfvec(v,q,b,expr): q being a square and symmetric matrix representing a positive definite quadratic form, evaluate expr for all vector v such that q(v)<=b."},
+{"forstep",0,(void*)forstep,13,"vV=GGGI","forstep(X=a,b,s,seq): the sequence is evaluated, X going from a to b in steps of s (can be a vector of steps)."},
+{"forsubgroup",0,(void*)forsubgroup0,13,"vV=GDGI","forsubgroup(H=G,{bound},seq): execute seq for each subgroup H of the abelian group G, whose index is bounded by bound if not omitted. H is given as a left divisor of G in HNF form."},
+{"forvec",0,(void*)forvec,13,"vV=GID0,L,","forvec(X=v,seq,{flag=0}): v being a vector of two-component vectors of length n, the sequence is evaluated with X[i] going from v[i][1] to v[i][2] for i=n,..,1 if flag is zero or omitted. If flag = 1 (resp. flag = 2), restrict to increasing (resp. strictly increasing) sequences."},
 {"frac",0,(void*)gfrac,2,"G","frac(x): fractional part of x = x-floor(x)."},
-{"galoisexport",0,(void*)galoisexport,6,"GD0,L,","galoisexport(gal,{flag}): gal being a Galois group as output by galoisinit, output a string representing the underlying permutation group in GAP notation (default) or Magma notation (flag = 1)."},
-{"galoisfixedfield",0,(void*)galoisfixedfield,6,"GGD0,L,Dn","galoisfixedfield(gal,perm,{flag},{v=y}): gal being a Galois group as output by galoisinit and perm a subgroup, an element of gal.group or a vector of such elements, return [P,x] such that P is a polynomial defining the fixed field of gal[1] by the subgroup generated by perm, and x is a root of P in gal expressed as a polmod in gal.pol. If flag is 1 return only P. If flag is 2 return [P,x,F] where F is the factorization of gal.p [...]
-{"galoisgetpol",0,(void*)galoisgetpol,6,"LD0,L,D1,L,","galoisgetpol(a,{b},{s}): Query the galpol package for a polynomial with Galois group isomorphic to GAP4(a,b), totally real if s=1 (default) and totally complex if s=2.  The output is a vector [pol, den] where pol is the polynomial and den is the common denominator of the conjugates expressed as a polynomial in a root of pol. If b and s are omitted, return the number of isomorphism classes of groups of order a."},
-{"galoisidentify",0,(void*)galoisidentify,6,"G","galoisidentify(gal): gal being a Galois group as output by galoisinit, output the isomorphism class of the underlying abstract group as a two-components vector [o,i], where o is the group order, and i is the group index in the GAP4 small group library."},
-{"galoisinit",0,(void*)galoisinit,6,"GDG","galoisinit(pol,{den}): pol being a polynomial or a number field as output by nfinit defining a Galois extension of Q, compute the Galois group and all necessary information for computing fixed fields. den is optional and has the same meaning as in nfgaloisconj(,4)(see manual)."},
-{"galoisisabelian",0,(void*)galoisisabelian,6,"GD0,L,","galoisisabelian(gal,{flag=0}): gal being as output by galoisinit, return 0 if gal is not abelian, the HNF matrix of gal over gal.gen if flag=0, 1 if flag is 1, and the SNF of gal is flag=2."},
-{"galoisisnormal",0,(void*)galoisisnormal,6,"lGG","galoisisnormal(gal,subgrp): gal being as output by galoisinit, and subgrp a subgroup of gal as output by galoissubgroups, return 1 if subgrp is a normal subgroup of gal, else return 0."},
-{"galoispermtopol",0,(void*)galoispermtopol,6,"GG","galoispermtopol(gal,perm): gal being a Galois group as output by galoisinit and perm a element of gal.group, return the polynomial defining the corresponding Galois automorphism."},
-{"galoissubcyclo",0,(void*)galoissubcyclo,6,"GDGD0,L,Dn","galoissubcyclo(N,H,{fl=0},{v}):Compute a polynomial (in variable v) defining the subfield of Q(zeta_n) fixed by the subgroup H of (Z/nZ)*. N can be an integer n, znstar(n) or bnrinit(bnfinit(y),[n,[1]],1). H can be given by a generator, a set of generator given by a vector or a HNF matrix (see manual). If flag is 1, output only the conductor of the abelian extension. If flag is 2 output [pol,f] where pol is the polynomial and f th [...]
-{"galoissubfields",0,(void*)galoissubfields,6,"GD0,L,Dn","galoissubfields(G,{flags=0},{v}):Output all the subfields of G. flags have the same meaning as for galoisfixedfield."},
-{"galoissubgroups",0,(void*)galoissubgroups,6,"G","galoissubgroups(G):Output all the subgroups of G."},
+{"fromdigits",0,(void*)fromdigits,2,"GDG","fromdigits(x,{b=10}): gives the integer formed by the elements of x seen as the digits of a number in base b."},
+{"galoisexport",0,(void*)galoisexport,7,"GD0,L,","galoisexport(gal,{flag}): gal being a Galois group as output by galoisinit, output a string representing the underlying permutation group in GAP notation (default) or Magma notation (flag = 1)."},
+{"galoisfixedfield",0,(void*)galoisfixedfield,7,"GGD0,L,Dn","galoisfixedfield(gal,perm,{flag},{v=y}): gal being a Galois group as output by galoisinit and perm a subgroup, an element of gal.group or a vector of such elements, return [P,x] such that P is a polynomial defining the fixed field of gal[1] by the subgroup generated by perm, and x is a root of P in gal expressed as a polmod in gal.pol. If flag is 1 return only P. If flag is 2 return [P,x,F] where F is the factorization of gal.p [...]
+{"galoisgetpol",0,(void*)galoisgetpol,7,"LD0,L,D1,L,","galoisgetpol(a,{b},{s}): Query the galpol package for a polynomial with Galois group isomorphic to GAP4(a,b), totally real if s=1 (default) and totally complex if s=2.  The output is a vector [pol, den] where pol is the polynomial and den is the common denominator of the conjugates expressed as a polynomial in a root of pol. If b and s are omitted, return the number of isomorphism classes of groups of order a."},
+{"galoisidentify",0,(void*)galoisidentify,7,"G","galoisidentify(gal): gal being a Galois group as output by galoisinit, output the isomorphism class of the underlying abstract group as a two-components vector [o,i], where o is the group order, and i is the group index in the GAP4 small group library."},
+{"galoisinit",0,(void*)galoisinit,7,"GDG","galoisinit(pol,{den}): pol being a polynomial or a number field as output by nfinit defining a Galois extension of Q, compute the Galois group and all necessary information for computing fixed fields. den is optional and has the same meaning as in nfgaloisconj(,4)(see manual)."},
+{"galoisisabelian",0,(void*)galoisisabelian,7,"GD0,L,","galoisisabelian(gal,{flag=0}): gal being as output by galoisinit, return 0 if gal is not abelian, the HNF matrix of gal over gal.gen if flag=0, 1 if flag is 1, and the SNF of gal is flag=2."},
+{"galoisisnormal",0,(void*)galoisisnormal,7,"lGG","galoisisnormal(gal,subgrp): gal being as output by galoisinit, and subgrp a subgroup of gal as output by galoissubgroups, return 1 if subgrp is a normal subgroup of gal, else return 0."},
+{"galoispermtopol",0,(void*)galoispermtopol,7,"GG","galoispermtopol(gal,perm): gal being a Galois group as output by galoisinit and perm a element of gal.group, return the polynomial defining the corresponding Galois automorphism."},
+{"galoissubcyclo",0,(void*)galoissubcyclo,7,"GDGD0,L,Dn","galoissubcyclo(N,H,{fl=0},{v}):Compute a polynomial (in variable v) defining the subfield of Q(zeta_n) fixed by the subgroup H of (Z/nZ)*. N can be an integer n, znstar(n) or bnrinit(bnfinit(y),[n,[1]],1). H can be given by a generator, a set of generator given by a vector or a HNF matrix (see manual). If flag is 1, output only the conductor of the abelian extension. If flag is 2 output [pol,f] where pol is the polynomial and f th [...]
+{"galoissubfields",0,(void*)galoissubfields,7,"GD0,L,Dn","galoissubfields(G,{flags=0},{v}):Output all the subfields of G. flags have the same meaning as for galoisfixedfield."},
+{"galoissubgroups",0,(void*)galoissubgroups,7,"G","galoissubgroups(G):Output all the subgroups of G."},
 {"gamma",0,(void*)ggamma,3,"Gp","gamma(s): gamma function at s, a complex or p-adic number, or a series."},
 {"gammah",0,(void*)ggammah,3,"Gp","gammah(x): gamma of x+1/2 (x integer)."},
 {"gcd",0,(void*)ggcd0,4,"GDG","gcd(x,{y}): greatest common divisor of x and y."},
 {"gcdext",0,(void*)gcdext0,4,"GG","gcdext(x,y): returns [u,v,d] such that d=gcd(x,y) and u*x+v*y=d."},
-{"genus2red",0,(void*)genus2red,5,"GGDG","genus2red(Q,P,{p}): let Q,P be polynomials with integer coefficients. Determines the reduction at p > 2 of the (proper, smooth) hyperelliptic curve C/Q: y^2+Qy = P, of genus 2. (The special fiber X_p of the minimal regular model X of C over Z.)"},
-{"getabstime",0,(void*)getabstime,11,"l","getabstime(): time (in milliseconds) since startup."},
-{"getenv",0,(void*)gp_getenv,11,"s","getenv(s): value of the environment variable s, 0 if it is not defined."},
-{"getheap",0,(void*)getheap,11,"","getheap(): 2-component vector giving the current number of objects in the heap and the space they occupy."},
-{"getrand",0,(void*)getrand,11,"","getrand(): current value of random number seed."},
-{"getstack",0,(void*)getstack,11,"l","getstack(): current value of stack pointer avma."},
-{"gettime",0,(void*)gettime,11,"l","gettime(): time (in milliseconds) since last call to gettime."},
-{"global",0,NULL,11,NULL,"global(list of variables): obsolete. Scheduled for deletion."},
+{"genus2red",0,(void*)genus2red,5,"GDG","genus2red(P,{p}): let P be a polynomial with integer coefficients. Determines the reduction at p > 2 of the (proper, smooth) hyperelliptic curve C/Q: y^2 = P, of genus 2. (The special fiber X_p of the minimal regular model X of C over Z.)"},
+{"getabstime",0,(void*)getabstime,13,"l","getabstime(): time (in milliseconds) since startup."},
+{"getenv",0,(void*)gp_getenv,13,"s","getenv(s): value of the environment variable s, 0 if it is not defined."},
+{"getheap",0,(void*)getheap,13,"","getheap(): 2-component vector giving the current number of objects in the heap and the space they occupy (in long words)."},
+{"getrand",0,(void*)getrand,13,"","getrand(): current value of random number seed."},
+{"getstack",0,(void*)getstack,13,"l","getstack(): current value of stack pointer avma."},
+{"gettime",0,(void*)gettime,13,"l","gettime(): time (in milliseconds) since last call to gettime."},
+{"getwalltime",0,(void*)getwalltime,13,"","getwalltime(): time (in milliseconds) since the UNIX Epoch."},
+{"global",0,NULL,13,NULL,"global(list of variables): obsolete. Scheduled for deletion."},
 {"hammingweight",0,(void*)hammingweight,2,"lG","hammingweight(x): returns the Hamming weight of x."},
 {"hilbert",0,(void*)hilbert,4,"lGGDG","hilbert(x,y,{p}): Hilbert symbol at p of x,y."},
+{"hyperellcharpoly",0,(void*)hyperellcharpoly,5,"G","hyperellcharpoly(X): X being a non-singular hyperelliptic curve defined over a finite field, return the characteristic polynomial of the Frobenius automorphism.  X can be given either by a squarefree polynomial P such that X:y^2=P(x) or by a vector [P,Q] such that X:y^2+Q(x)*y=P(x) and Q^2+4P is squarefree."},
+{"hyperellpadicfrobenius",0,(void*)hyperellpadicfrobenius,5,"GUL","hyperellpadicfrobenius(Q,p,n): Q being a  rational polynomial of degree d, return the matrix of the Frobenius at p>=d in the standard basis of H^1_dR(E) to absolute p-adic precision p^n."},
 {"hyperu",0,(void*)hyperu,3,"GGGp","hyperu(a,b,x): U-confluent hypergeometric function."},
-{"idealadd",0,(void*)idealadd,6,"GGG","idealadd(nf,x,y): sum of two ideals x and y in the number field defined by nf."},
-{"idealaddtoone",0,(void*)idealaddtoone0,6,"GGDG","idealaddtoone(nf,x,{y}): if y is omitted, when the sum of the ideals in the number field K defined by nf and given in the vector x is equal to Z_K, gives a vector of elements of the corresponding ideals who sum to 1. Otherwise, x and y are ideals, and if they sum up to 1, find one element in each of them such that the sum is 1."},
-{"idealappr",0,(void*)idealappr0,6,"GGD0,L,","idealappr(nf,x,{flag=0}): x being a fractional ideal, gives an element b such that v_p(b)=v_p(x) for all prime ideals p dividing x, and v_p(b)>=0 for all other p. If (optional) flag is non-null x must be a prime ideal factorization with possibly zero exponents."},
-{"idealchinese",0,(void*)idealchinese,6,"GGG","idealchinese(nf,x,y): x being a prime ideal factorization and y a vector of elements, gives an element b such that v_p(b-y_p)>=v_p(x) for all prime ideals p dividing x, and v_p(b)>=0 for all other p."},
-{"idealcoprime",0,(void*)idealcoprime,6,"GGG","idealcoprime(nf,x,y): gives an element b in nf such that b. x is an integral ideal coprime to the integral ideal y."},
-{"idealdiv",0,(void*)idealdiv0,6,"GGGD0,L,","idealdiv(nf,x,y,{flag=0}): quotient x/y of two ideals x and y in HNF in the number field nf. If (optional) flag is non-null, the quotient is supposed to be an integral ideal (slightly faster)."},
-{"idealfactor",0,(void*)idealfactor,6,"GG","idealfactor(nf,x): factorization of the ideal x given in HNF into prime ideals in the number field nf."},
-{"idealfactorback",0,(void*)idealfactorback,6,"GGDGD0,L,","idealfactorback(nf,f,{e},{flag = 0}): given a factorisation f, gives the ideal product back. If e is present, f has to be a vector of the same length, and we return the product of the f[i]^e[i]. If flag is non-zero, perform idealred along the way."},
-{"idealfrobenius",0,(void*)idealfrobenius,6,"GGG","idealfrobenius(nf,gal,pr): Returns the Frobenius element (pr|nf/Q) associated with the unramified prime ideal pr in prid format, in the Galois group gal of the number field nf."},
-{"idealhnf",0,(void*)idealhnf0,6,"GGDG","idealhnf(nf,u,{v}): hermite normal form of the ideal u in the number field nf if v is omitted. If called as idealhnf(nf,u,v), the ideal is given as uZ_K + vZ_K in the number field K defined by nf."},
-{"idealintersect",0,(void*)idealintersect,6,"GGG","idealintersect(nf,A,B): intersection of two ideals A and B in the number field defined by nf."},
-{"idealinv",0,(void*)idealinv,6,"GG","idealinv(nf,x): inverse of the ideal x in the number field nf."},
-{"ideallist",0,(void*)ideallist0,6,"GLD4,L,","ideallist(nf,bound,{flag=4}): vector of vectors L of all idealstar of all ideals of norm<=bound. If (optional) flag is present, its binary digits are toggles meaning 1: give generators; 2: add units; 4: give only the ideals and not the bid."},
-{"ideallistarch",0,(void*)ideallistarch,6,"GGG","ideallistarch(nf,list,arch): list is a vector of vectors of of bid's as output by ideallist. Return a vector of vectors with the same number of components as the original list. The leaves give information about moduli whose finite part is as in original list, in the same order, and Archimedean part is now arch. The information contained is of the same kind as was present in the input."},
-{"ideallog",0,(void*)ideallog,6,"GGG","ideallog(nf,x,bid): if bid is a big ideal, as given by idealstar(nf,I,1) or idealstar(nf,I,2), gives the vector of exponents on the generators bid[2][3] (even if these generators have not been computed)."},
-{"idealmin",0,(void*)idealmin,6,"GGDG","idealmin(nf,ix,{vdir}): pseudo-minimum of the ideal ix in the direction vdir in the number field nf."},
-{"idealmul",0,(void*)idealmul0,6,"GGGD0,L,","idealmul(nf,x,y,{flag=0}): product of the two ideals x and y in the number field nf. If (optional) flag is non-nul, reduce the result."},
-{"idealnorm",0,(void*)idealnorm,6,"GG","idealnorm(nf,x): norm of the ideal x in the number field nf."},
-{"idealnumden",0,(void*)idealnumden,6,"GG","idealnumden(nf,x): returns [A,B], where A,B are coprime integer ideals such that x = A/B"},
-{"idealpow",0,(void*)idealpow0,6,"GGGD0,L,","idealpow(nf,x,k,{flag=0}): k-th power of the ideal x in HNF in the number field nf. If (optional) flag is non-null, reduce the result."},
-{"idealprimedec",0,(void*)idealprimedec,6,"GG","idealprimedec(nf,p): prime ideal decomposition of the prime number p in the number field nf as a vector of 5 component vectors [p,a,e,f,b] representing the prime ideals pZ_K+a. Z_K, e,f as usual, a as vector of components on the integral basis, b Lenstra's constant."},
-{"idealprincipalunits",0,(void*)idealprincipalunits,6,"GGL","idealprincipalunits(nf,pr,k): returns the structure [no, cyc, gen] of the multiplicative group (1 + pr) / (1 + pr^k)^*."},
-{"idealramgroups",0,(void*)idealramgroups,6,"GGG","idealramgroups(nf,gal,pr): let pr be a prime ideal in prid format, and gal the Galois group of the number field nf, return a vector g such that g[1] is the decomposition group of pr, g[2] is the inertia group, g[i] is the (i-2)th ramification group of pr, all trivial subgroups being omitted."},
-{"idealred",0,(void*)idealred0,6,"GGDG","idealred(nf,I,{v=0}): LLL reduction of the ideal I in the number field nf along direction v, in HNF."},
-{"idealstar",0,(void*)idealstar0,6,"GGD1,L,","idealstar(nf,I,{flag=1}): gives the structure of (Z_K/I)^*. flag is optional, and can be 0: simply gives the structure as a 3-component vector v such that v[1] is the order (i.e. eulerphi(I)), v[2] is a vector of cyclic components, and v[3] is a vector giving the corresponding generators. If flag=1 (default), gives idealstarinit, i.e. a 6-component vector [I,v,fa,f2,U,V] where v is as above without the generators, fa is the prime ideal factor [...]
-{"idealtwoelt",0,(void*)idealtwoelt0,6,"GGDG","idealtwoelt(nf,x,{a}): two-element representation of an ideal x in the number field nf. If (optional) a is non-zero, first element will be equal to a."},
-{"idealval",0,(void*)idealval,6,"lGGG","idealval(nf,x,pr): valuation at pr given in idealprimedec format of the ideal x in the number field nf."},
-{"if",0,(void*)ifpari,11,"GDEDE","if(a,{seq1},{seq2}): if a is nonzero, seq1 is evaluated, otherwise seq2. seq1 and seq2 are optional, and if seq2 is omitted, the preceding comma can be omitted also."},
-{"iferr",0,(void*)iferrpari,11,"EVEDE","iferr(seq1,E,seq2{,pred}): evaluates the expression sequence seq1. If an error occurs, set the formal parameter E set to the error data. If pred is not present or evaluates to true, catch the error and evaluate seq2. Both pred and seq2 can reference E."},
+{"idealadd",0,(void*)idealadd,7,"GGG","idealadd(nf,x,y): sum of two ideals x and y in the number field defined by nf."},
+{"idealaddtoone",0,(void*)idealaddtoone0,7,"GGDG","idealaddtoone(nf,x,{y}): if y is omitted, when the sum of the ideals in the number field K defined by nf and given in the vector x is equal to Z_K, gives a vector of elements of the corresponding ideals who sum to 1. Otherwise, x and y are ideals, and if they sum up to 1, find one element in each of them such that the sum is 1."},
+{"idealappr",0,(void*)idealappr0,7,"GGD0,L,","idealappr(nf,x,{flag=0}): x being a fractional ideal, gives an element b such that v_p(b)=v_p(x) for all prime ideals p dividing x, and v_p(b)>=0 for all other p. If (optional) flag is non-null x must be a prime ideal factorization with possibly zero exponents."},
+{"idealchinese",0,(void*)idealchinese,7,"GGG","idealchinese(nf,x,y): x being a prime ideal factorization and y a vector of elements, gives an element b such that v_p(b-y_p)>=v_p(x) for all prime ideals p dividing x, and v_p(b)>=0 for all other p."},
+{"idealcoprime",0,(void*)idealcoprime,7,"GGG","idealcoprime(nf,x,y): gives an element b in nf such that b. x is an integral ideal coprime to the integral ideal y."},
+{"idealdiv",0,(void*)idealdiv0,7,"GGGD0,L,","idealdiv(nf,x,y,{flag=0}): quotient x/y of two ideals x and y in HNF in the number field nf. If (optional) flag is non-null, the quotient is supposed to be an integral ideal (slightly faster)."},
+{"idealfactor",0,(void*)idealfactor,7,"GG","idealfactor(nf,x): factorization of the ideal x given in HNF into prime ideals in the number field nf."},
+{"idealfactorback",0,(void*)idealfactorback,7,"GGDGD0,L,","idealfactorback(nf,f,{e},{flag = 0}): given a factorisation f, gives the ideal product back. If e is present, f has to be a vector of the same length, and we return the product of the f[i]^e[i]. If flag is non-zero, perform idealred along the way."},
+{"idealfrobenius",0,(void*)idealfrobenius,7,"GGG","idealfrobenius(nf,gal,pr): Returns the Frobenius element (pr|nf/Q) associated with the unramified prime ideal pr in prid format, in the Galois group gal of the number field nf."},
+{"idealhnf",0,(void*)idealhnf0,7,"GGDG","idealhnf(nf,u,{v}): hermite normal form of the ideal u in the number field nf if v is omitted. If called as idealhnf(nf,u,v), the ideal is given as uZ_K + vZ_K in the number field K defined by nf."},
+{"idealintersect",0,(void*)idealintersect,7,"GGG","idealintersect(nf,A,B): intersection of two ideals A and B in the number field defined by nf."},
+{"idealinv",0,(void*)idealinv,7,"GG","idealinv(nf,x): inverse of the ideal x in the number field nf."},
+{"ideallist",0,(void*)ideallist0,7,"GLD4,L,","ideallist(nf,bound,{flag=4}): vector of vectors L of all idealstar of all ideals of norm<=bound. If (optional) flag is present, its binary digits are toggles meaning 1: give generators; 2: add units; 4: give only the ideals and not the bid."},
+{"ideallistarch",0,(void*)ideallistarch,7,"GGG","ideallistarch(nf,list,arch): list is a vector of vectors of of bid's as output by ideallist. Return a vector of vectors with the same number of components as the original list. The leaves give information about moduli whose finite part is as in original list, in the same order, and Archimedean part is now arch. The information contained is of the same kind as was present in the input."},
+{"ideallog",0,(void*)ideallog,7,"GGG","ideallog(nf,x,bid): if bid is a big ideal, as given by idealstar(nf,I,1) or idealstar(nf,I,2), gives the vector of exponents on the generators bid[2][3] (even if these generators have not been computed)."},
+{"idealmin",0,(void*)idealmin,7,"GGDG","idealmin(nf,ix,{vdir}): pseudo-minimum of the ideal ix in the direction vdir in the number field nf."},
+{"idealmul",0,(void*)idealmul0,7,"GGGD0,L,","idealmul(nf,x,y,{flag=0}): product of the two ideals x and y in the number field nf. If (optional) flag is non-nul, reduce the result."},
+{"idealnorm",0,(void*)idealnorm,7,"GG","idealnorm(nf,x): norm of the ideal x in the number field nf."},
+{"idealnumden",0,(void*)idealnumden,7,"GG","idealnumden(nf,x): returns [A,B], where A,B are coprime integer ideals such that x = A/B"},
+{"idealpow",0,(void*)idealpow0,7,"GGGD0,L,","idealpow(nf,x,k,{flag=0}): k-th power of the ideal x in HNF in the number field nf. If (optional) flag is non-null, reduce the result."},
+{"idealprimedec",0,(void*)idealprimedec_limit_f,7,"GGD0,L,","idealprimedec(nf,p,{f=0}): prime ideal decomposition of the prime number p in the number field nf as a vector of 5 component vectors [p,a,e,f,b] representing the prime ideals pZ_K+a. Z_K, e,f as usual, a as vector of components on the integral basis, b Lenstra's constant. If f is present and non-zero, restrict the result to primes of residue degree <= f."},
+{"idealprincipalunits",0,(void*)idealprincipalunits,7,"GGL","idealprincipalunits(nf,pr,k): returns the structure [no, cyc, gen] of the multiplicative group (1 + pr) / (1 + pr^k)^*."},
+{"idealramgroups",0,(void*)idealramgroups,7,"GGG","idealramgroups(nf,gal,pr): let pr be a prime ideal in prid format, and gal the Galois group of the number field nf, return a vector g such that g[1] is the decomposition group of pr, g[2] is the inertia group, g[i] is the (i-2)th ramification group of pr, all trivial subgroups being omitted."},
+{"idealred",0,(void*)idealred0,7,"GGDG","idealred(nf,I,{v=0}): LLL reduction of the ideal I in the number field nf along direction v, in HNF."},
+{"idealstar",0,(void*)idealstar0,7,"GGD1,L,","idealstar(nf,I,{flag=1}): gives the structure of (Z_K/I)^*. flag is optional, and can be 0: simply gives the structure as a 3-component vector v such that v[1] is the order (i.e. eulerphi(I)), v[2] is a vector of cyclic components, and v[3] is a vector giving the corresponding generators. If flag=1 (default), gives idealstarinit, i.e. a 6-component vector [I,v,fa,f2,U,V] where v is as above without the generators, fa is the prime ideal factor [...]
+{"idealtwoelt",0,(void*)idealtwoelt0,7,"GGDG","idealtwoelt(nf,x,{a}): two-element representation of an ideal x in the number field nf. If (optional) a is non-zero, first element will be equal to a."},
+{"idealval",0,(void*)gpidealval,7,"GGG","idealval(nf,x,pr): valuation at pr given in idealprimedec format of the ideal x in the number field nf."},
+{"if",0,(void*)ifpari,13,"GDEDE","if(a,{seq1},{seq2}): if a is nonzero, seq1 is evaluated, otherwise seq2. seq1 and seq2 are optional, and if seq2 is omitted, the preceding comma can be omitted also."},
+{"iferr",0,(void*)iferrpari,13,"EVEDE","iferr(seq1,E,seq2{,pred}): evaluates the expression sequence seq1. If an error occurs, set the formal parameter E set to the error data. If pred is not present or evaluates to true, catch the error and evaluate seq2. Both pred and seq2 can reference E."},
 {"imag",0,(void*)gimag,2,"G","imag(x): imaginary part of x."},
 {"incgam",0,(void*)incgam0,3,"GGDGp","incgam(s,x,{g}): incomplete gamma function. g is optional and is the precomputed value of gamma(s)."},
 {"incgamc",0,(void*)incgamc,3,"GGp","incgamc(s,x): complementary incomplete gamma function."},
-{"inline",0,NULL,11,NULL,"inline(x,...,z): declares x,...,z as inline variables [EXPERIMENTAL]"},
-{"install",0,(void*)gpinstall,11,"vrrD\"\",r,D\"\",s,","install(name,code,{gpname},{lib}): load from dynamic library 'lib' the function 'name'. Assign to it the name 'gpname' in this GP session, with prototype 'code'. If 'lib' is omitted, all symbols known to gp (includes the whole 'libpari.so' and possibly others) are available. If 'gpname' is omitted, use 'name'."},
-{"intcirc",0,(void*)intcirc0,9,"V=GGEDGp","intcirc(X=a,R,expr,{tab}): numerical integration of expr on the circle |z-a|=R, divided by 2*I*Pi. tab is as in intnum."},
-{"intformal",0,(void*)integ,7,"GDn","intformal(x,{v}): formal integration of x with respect to v, or to the main variable of x if v is omitted."},
-{"intfouriercos",0,(void*)intfourcos0,9,"V=GGGEDGp","intfouriercos(X=a,b,z,expr,{tab}): numerical integration from a to b of cos(2*Pi*z*X)*expr(X) from a to b, where a, b, and tab are as in intnum. This is the cosine-Fourier transform if a=-infty and b=+infty."},
-{"intfourierexp",0,(void*)intfourexp0,9,"V=GGGEDGp","intfourierexp(X=a,b,z,expr,{tab}): numerical integration from a to b of exp(-2*I*Pi*z*X)*expr(X) from a to b, where a, b, and tab are as in intnum. This is the ordinary Fourier transform if a=-infty and b=+infty. Note the minus sign."},
-{"intfouriersin",0,(void*)intfoursin0,9,"V=GGGEDGp","intfouriersin(X=a,b,z,expr,{tab}): numerical integration from a to b of sin(2*Pi*z*X)*expr(X) from a to b, where a, b, and tab are as in intnum. This is the sine-Fourier transform if a=-infty and b=+infty."},
-{"intfuncinit",0,(void*)intfuncinit0,9,"V=GGED0,L,D0,L,p","intfuncinit(X=a,b,expr,{flag=0},{m=0}): initialize tables for integrations from a to b using a weight expr(X). Essential for integral transforms such as intmellininv, intlaplaceinv and intfourier, since it avoids recomputing all the time the same quantities. Must then be used with intmellininvshort (for intmellininv) and directly with intnum and not with the corresponding integral transforms for the others. See help for intnum fo [...]
-{"intlaplaceinv",0,(void*)intlaplaceinv0,9,"V=GGEDGp","intlaplaceinv(X=sig,z,expr,{tab}): numerical integration on the line real(X) = sig of expr(X)exp(zX)dz/(2*I*Pi), i.e. inverse Laplace transform of expr at z. tab is as in intnum."},
-{"intmellininv",0,(void*)intmellininv0,9,"V=GGEDGp","intmellininv(X=sig,z,expr,{tab}): numerical integration on the line real(X) = sig (or sig[1]) of expr(X)z^(-X)dX/(2*I*Pi), i.e. inverse Mellin transform of s at x. sig is coded as follows: either it is real, and then by default assume s(z) decreases like exp(-z). Or sig = [sigR, al], sigR is the abscissa of integration, and al = 0 for slowly decreasing functions, or al > 0 if s(z) decreases like exp(-al*z). tab is as in intnum. Use int [...]
-{"intmellininvshort",0,(void*)intmellininvshort,9,"GGGp","intmellininvshort(sig,z,tab): numerical integration on the line real(X) = sig (or sig[1]) of s(X)z^(-X)dX/(2*I*Pi), i.e. inverse Mellin transform of s at z. sig is coded as follows: either it is real, and then by default assume s(X) decreases like exp(-X). Or sig = [sigR, al], sigR is the abscissa of integration, and al = 0 for slowly decreasing functions, or al > 0 if s(X) decreases like exp(-al*X). Compulsory table tab has been  [...]
-{"intnum",0,(void*)intnum0,9,"V=GGEDGp","intnum(X=a,b,expr,{tab}): numerical integration of expr from a to b with respect to X. Plus/minus infinity is coded as [+1]/ [-1]. Finally tab is either omitted (let the program choose the integration step), a positive integer m (choose integration step 1/2^m), or data precomputed with intnuminit."},
-{"intnuminit",0,(void*)intnuminit,9,"GGD0,L,p","intnuminit(a,b,{m=0}): initialize tables for integrations from a to b. See help for intnum for coding of a and b. Possible types: compact interval, semi-compact (one extremity at + or - infinity) or R, and very slowly, slowly or exponentially decreasing, or sine or cosine oscillating at infinities."},
-{"intnuminitgen",0,(void*)intnuminitgen0,9,"VGGED0,L,D0,L,p","intnuminitgen(t,a,b,ph,{m=0},{flag=0}): initialize tables for integrations from a to b using abscissas ph(t) and weights ph'(t). Note that there is no equal sign after the variable name t since t always goes from -infty to +infty, but it is ph(t) which goes from a to b, and this is not checked. If flag = 1 or 2, multiply the reserved table length by 4^flag, to avoid corresponding error."},
-{"intnumromb",0,(void*)intnumromb0,9,"V=GGED0,L,p","intnumromb(X=a,b,expr,{flag=0}): numerical integration of expr (smooth in ]a,b[) from a to b with respect to X. flag is optional and mean 0: default. expr can be evaluated exactly on [a,b]; 1: general function; 2: a or b can be plus or minus infinity (chosen suitably), but of same sign; 3: expr has only limits at a or b."},
-{"intnumstep",0,(void*)intnumstep,9,"lp","intnumstep(): gives the default value of m used by all intnum and sumnum routines, such that the integration step is 1/2^m."},
+{"inline",0,NULL,13,NULL,"inline(x,...,z): declares x,...,z as inline variables [EXPERIMENTAL]"},
+{"input",0,(void*)gp_input,13,"","input(): read an expression from the input file or standard input."},
+{"install",0,(void*)gpinstall,13,"vrrD\"\",r,D\"\",s,","install(name,code,{gpname},{lib}): load from dynamic library 'lib' the function 'name'. Assign to it the name 'gpname' in this GP session, with prototype 'code'. If 'lib' is omitted, all symbols known to gp (includes the whole 'libpari.so' and possibly others) are available. If 'gpname' is omitted, use 'name'."},
+{"intcirc",0,(void*)intcirc0,11,"V=GGEDGp","intcirc(X=a,R,expr,{tab}): numerical integration of expr on the circle |z-a|=R, divided by 2*I*Pi. tab is as in intnum."},
+{"intformal",0,(void*)integ,9,"GDn","intformal(x,{v}): formal integration of x with respect to v, or to the main variable of x if v is omitted."},
+{"intfouriercos",0,(void*)intfourcos0,11,"V=GGGEDGp","intfouriercos(X=a,b,z,expr,{tab}): numerical integration from a to b of cos(2*Pi*z*X)*expr(X) from a to b, where a, b, and tab are as in intnum. This is the cosine-Fourier transform if a=-infty and b=+infty."},
+{"intfourierexp",0,(void*)intfourexp0,11,"V=GGGEDGp","intfourierexp(X=a,b,z,expr,{tab}): numerical integration from a to b of exp(-2*I*Pi*z*X)*expr(X) from a to b, where a, b, and tab are as in intnum. This is the ordinary Fourier transform if a=-infty and b=+infty. Note the minus sign."},
+{"intfouriersin",0,(void*)intfoursin0,11,"V=GGGEDGp","intfouriersin(X=a,b,z,expr,{tab}): numerical integration from a to b of sin(2*Pi*z*X)*expr(X) from a to b, where a, b, and tab are as in intnum. This is the sine-Fourier transform if a=-infty and b=+infty."},
+{"intfuncinit",0,(void*)intfuncinit0,11,"V=GGED0,L,D0,L,p","intfuncinit(X=a,b,expr,{flag=0},{m=0}): initialize tables for integrations from a to b using a weight expr(X). Essential for integral transforms such as intmellininv, intlaplaceinv and intfourier, since it avoids recomputing all the time the same quantities. Must then be used with intmellininvshort (for intmellininv) and directly with intnum and not with the corresponding integral transforms for the others. See help for intnum f [...]
+{"intlaplaceinv",0,(void*)intlaplaceinv0,11,"V=GGEDGp","intlaplaceinv(X=sig,z,expr,{tab}): numerical integration on the line real(X) = sig of expr(X)exp(zX)dz/(2*I*Pi), i.e. inverse Laplace transform of expr at z. tab is as in intnum."},
+{"intmellininv",0,(void*)intmellininv0,11,"V=GGEDGp","intmellininv(X=sig,z,expr,{tab}): numerical integration on the line real(X) = sig (or sig[1]) of expr(X)z^(-X)dX/(2*I*Pi), i.e. inverse Mellin transform of s at x. sig is coded as follows: either it is real, and then by default assume s(z) decreases like exp(-z). Or sig = [sigR, al], sigR is the abscissa of integration, and al = 0 for slowly decreasing functions, or al > 0 if s(z) decreases like exp(-al*z). tab is as in intnum. Use in [...]
+{"intmellininvshort",0,(void*)intmellininvshort,11,"GGGp","intmellininvshort(sig,z,tab): numerical integration on the line real(X) = sig (or sig[1]) of s(X)z^(-X)dX/(2*I*Pi), i.e. inverse Mellin transform of s at z. sig is coded as follows: either it is real, and then by default assume s(X) decreases like exp(-X). Or sig = [sigR, al], sigR is the abscissa of integration, and al = 0 for slowly decreasing functions, or al > 0 if s(X) decreases like exp(-al*X). Compulsory table tab has been [...]
+{"intnum",0,(void*)intnum0,11,"V=GGEDGp","intnum(X=a,b,expr,{tab}): numerical integration of expr from a to b with respect to X. Plus/minus infinity is coded as +oo/-oo. Finally tab is either omitted (let the program choose the integration step), a positive integer m (choose integration step 1/2^m), or data precomputed with intnuminit."},
+{"intnuminit",0,(void*)intnuminit,11,"GGD0,L,p","intnuminit(a,b,{m=0}): initialize tables for integrations from a to b. See help for intnum for coding of a and b. Possible types: compact interval, semi-compact (one extremity at + or - infinity) or R, and very slowly, slowly or exponentially decreasing, or sine or cosine oscillating at infinities."},
+{"intnuminitgen",0,(void*)intnuminitgen0,11,"VGGED0,L,D0,L,p","intnuminitgen(t,a,b,ph,{m=0},{flag=0}): initialize tables for integrations from a to b using abscissas ph(t) and weights ph'(t). Note that there is no equal sign after the variable name t since t always goes from -infty to +infty, but it is ph(t) which goes from a to b, and this is not checked. If flag = 1 or 2, multiply the reserved table length by 4^flag, to avoid corresponding error."},
+{"intnumromb",0,(void*)intnumromb0,11,"V=GGED0,L,p","intnumromb(X=a,b,expr,{flag=0}): numerical integration of expr (smooth in ]a,b[) from a to b with respect to X. flag is optional and mean 0: default. expr can be evaluated exactly on [a,b]; 1: general function; 2: a or b can be plus or minus infinity (chosen suitably), but of same sign; 3: expr has only limits at a or b."},
+{"intnumstep",0,(void*)intnumstep,11,"lp","intnumstep(): gives the default value of m used by all intnum and sumnum routines, such that the integration step is 1/2^m."},
 {"isfundamental",0,(void*)isfundamental,4,"lG","isfundamental(x): true(1) if x is a fundamental discriminant (including 1), false(0) if not."},
 {"ispolygonal",0,(void*)ispolygonal,4,"lGGD&","ispolygonal(x,s,{&N}): true(1) if x is an s-gonal number, false(0) if not (s > 2). If N is given set it to n if x is the n-th s-gonal number."},
 {"ispower",0,(void*)ispower,4,"lGDGD&","ispower(x,{k},{&n}): if k > 0 is given, return true (1) if x is a k-th power, false (0) if not. If k is omitted, return the maximal k >= 2 such that x = n^k is a perfect power, or 0 if no such k exist. If n is present, and the function returns a non-zero result, set n to the k-th root of x."},
-{"ispowerful",0,(void*)ispowerful,4,"lG","ispowerful(x): true(1) if x is a powerful integer (valuation at all primes is greater than 1), false(0) if not."},
+{"ispowerful",0,(void*)ispowerful,4,"lG","ispowerful(x): true(1) if x is a powerful integer (valuation at all primes dividing x is greater than 1), false(0) if not."},
 {"isprime",0,(void*)gisprime,4,"GD0,L,","isprime(x,{flag=0}): true(1) if x is a (proven) prime number, false(0) if not. If flag is 0 or omitted, use a combination of algorithms. If flag is 1, the primality is certified by the Pocklington-Lehmer Test. If flag is 2, the primality is certified using the APRCL test."},
 {"isprimepower",0,(void*)isprimepower,4,"lGD&","isprimepower(x,{&n}): if x = p^k is a prime power (p prime, k > 0), return k, else return 0. If n is present, and the function returns a non-zero result, set n to p, the k-th root of x."},
 {"ispseudoprime",0,(void*)gispseudoprime,4,"GD0,L,","ispseudoprime(x,{flag}): true(1) if x is a strong pseudoprime, false(0) if not. If flag is 0 or omitted, use BPSW test, otherwise use strong Rabin-Miller test for flag randomly chosen bases."},
+{"ispseudoprimepower",0,(void*)ispseudoprimepower,4,"lGD&","ispseudoprimepower(x,{&n}): if x = p^k is a pseudo-prime power (p pseudo-prime, k > 0), return k, else return 0. If n is present, and the function returns a non-zero result, set n to p, the k-th root of x."},
 {"issquare",0,(void*)issquareall,4,"lGD&","issquare(x,{&n}): true(1) if x is a square, false(0) if not. If n is given puts the exact square root there if it was computed."},
 {"issquarefree",0,(void*)issquarefree,4,"lG","issquarefree(x): true(1) if x is squarefree, false(0) if not."},
 {"istotient",0,(void*)istotient,4,"lGD&","istotient(x,{&N}): true(1) if x = eulerphi(n) for some integer n, false(0) if not. If N is given, set N = n as well."},
-{"kill",0,(void*)kill0,11,"vr","kill(sym): restores the symbol sym to its ``undefined'' status and kill associated help messages."},
+{"kill",0,(void*)kill0,13,"vr","kill(sym): restores the symbol sym to its ``undefined'' status and kill associated help messages."},
 {"kronecker",0,(void*)kronecker,4,"lGG","kronecker(x,y): kronecker symbol (x/y)."},
 {"lambertw",0,(void*)glambertW,3,"Gp","lambertw(y): solution of the implicit equation x*exp(x)=y."},
-{"lcm",0,(void*)glcm0,4,"GDG","lcm(x,{y}): least common multiple of x and y, i.e. x*y / gcd(x,y)."},
+{"lcm",0,(void*)glcm0,4,"GDG","lcm(x,{y}): least common multiple of x and y, i.e. x*y / gcd(x,y) up to units."},
 {"length",0,(void*)glength,2,"lG","length(x): number of non code words in x, number of characters for a string."},
 {"lex",0,(void*)lexcmp,1,"iGG","lex(x,y): compare x and y lexicographically (1 if x>y, 0 if x=y, -1 if x<y)"},
 {"lift",0,(void*)lift0,2,"GDn","lift(x,{v}): if v is omitted, lifts elements of Z/nZ to Z, of Qp to Q, and of K[x]/(P) to K[x]. Otherwise lift only polmods with main variable v."},
 {"liftall",0,(void*)liftall,2,"G","liftall(x): lifts every element of Z/nZ to Z, of Qp to Q, and of K[x]/(P) to K[x]."},
 {"liftint",0,(void*)liftint,2,"G","liftint(x): lifts every element of Z/nZ to Z, of Qp to Q, and of K[x]/(P) to K[x]."},
 {"liftpol",0,(void*)liftpol,2,"G","liftpol(x): lifts every polmod component of x to polynomials"},
-{"lindep",0,(void*)lindep0,8,"GD0,L,","lindep(v,{flag=0}): integral linear dependencies between components of v. flag is optional, and can be 0: default, guess a suitable accuracy, or positive: accuracy to use for the computation, in decimal digits."},
-{"listcreate",0,(void*)listcreate,8,"D0,L,","listcreate(): creates an empty list."},
-{"listinsert",0,(void*)listinsert,8,"WGL","listinsert(L,x,n): insert x at index n in list L, shifting the remaining elements to the right."},
-{"listkill",0,(void*)listkill,8,"vG","listkill(L): obsolete, retained for backward compatibility."},
-{"listpop",0,(void*)listpop,8,"vWD0,L,","listpop(list,{n}): removes n-th element from list. If n is omitted or greater than the current list length, removes last element."},
-{"listput",0,(void*)listput,8,"WGD0,L,","listput(list,x,{n}): sets n-th element of list equal to x. If n is omitted or greater than the current list length, appends x."},
-{"listsort",0,(void*)listsort,8,"vWD0,L,","listsort(L,{flag=0}): sort the list L in place. If flag is non-zero, suppress all but one occurence of each element in list."},
+{"lindep",0,(void*)lindep0,10,"GD0,L,","lindep(v,{flag=0}): integral linear dependencies between components of v. flag is optional, and can be 0: default, guess a suitable accuracy, or positive: accuracy to use for the computation, in decimal digits."},
+{"listcreate",0,(void*)listcreate,10,"D0,L,","listcreate(): creates an empty list."},
+{"listinsert",0,(void*)listinsert,10,"WGL","listinsert(L,x,n): insert x at index n in list L, shifting the remaining elements to the right."},
+{"listkill",0,(void*)listkill,10,"vG","listkill(L): obsolete, retained for backward compatibility."},
+{"listpop",0,(void*)listpop,10,"vWD0,L,","listpop(list,{n}): removes n-th element from list. If n is omitted or greater than the current list length, removes last element."},
+{"listput",0,(void*)listput,10,"WGD0,L,","listput(list,x,{n}): sets n-th element of list equal to x. If n is omitted or greater than the current list length, appends x."},
+{"listsort",0,(void*)listsort,10,"vWD0,L,","listsort(L,{flag=0}): sort the list L in place. If flag is non-zero, suppress all but one occurence of each element in list."},
 {"lngamma",0,(void*)glngamma,3,"Gp","lngamma(x): logarithm of the gamma function of x."},
-{"local",0,NULL,11,NULL,"local(x,...,z): declare x,...,z as (dynamically scoped) local variables."},
+{"local",0,NULL,13,NULL,"local(x,...,z): declare x,...,z as (dynamically scoped) local variables."},
+{"localprec",0,(void*)localprec,13,"vL","localprec(p): set the real precision to p in the dynamic scope."},
 {"log",0,(void*)glog,3,"Gp","log(x): natural logarithm of x."},
 {"logint",0,(void*)logint0,4,"lGGD&","logint(x,b,&z): return the largest integer e so that b^e <= x, where the parameters b > 1 and x > 0 are both integers. If the parameter z is present, set it to b^e."},
-{"matadjoint",0,(void*)matadjoint0,8,"GD0,L,","matadjoint(M,{flag=0}): adjoint matrix of M using Leverrier-Faddeev's algorithm. If flag is 1, compute the characteristic polynomial independently first."},
-{"matalgtobasis",0,(void*)matalgtobasis,6,"GG","matalgtobasis(nf,x): nfalgtobasis applied to every element of the vector or matrix x."},
-{"matbasistoalg",0,(void*)matbasistoalg,6,"GG","matbasistoalg(nf,x): nfbasistoalg applied to every element of the matrix or vector x."},
-{"matcompanion",0,(void*)matcompanion,8,"G","matcompanion(x): companion matrix to polynomial x."},
-{"matconcat",0,(void*)matconcat,8,"G","matconcat(v): concatenate the entries of v and return the resulting matrix"},
-{"matdet",0,(void*)det0,8,"GD0,L,","matdet(x,{flag=0}): determinant of the matrix x using an appropriate algorithm depending on the coefficients. If (optional) flag is set to 1, use classical Gaussian elimination (usually worse than the default)."},
-{"matdetint",0,(void*)detint,8,"G","matdetint(B): some multiple of the determinant of the lattice generated by the columns of B (0 if not of maximal rank). Useful with mathnfmod."},
-{"matdiagonal",0,(void*)diagonal,8,"G","matdiagonal(x): creates the diagonal matrix whose diagonal entries are the entries of the vector x."},
-{"mateigen",0,(void*)mateigen,8,"GD0,L,p","mateigen(x,{flag=0}): complex eigenvectors of the matrix x given as columns of a matrix H. If flag=1, return [L,H], where L contains the eigenvalues and H the corresponding eigenvectors."},
-{"matfrobenius",0,(void*)matfrobenius,8,"GD0,L,Dn","matfrobenius(M,{flag},{v='x}): Return the Frobenius form of the square matrix M. If flag is 1, return only the elementary divisors as a vector of polynomials in the variable v. If flag is 2, return a two-components vector [F,B] where F is the Frobenius form and B is the basis change so that M=B^-1*F*B."},
-{"mathess",0,(void*)hess,8,"G","mathess(x): Hessenberg form of x."},
-{"mathilbert",0,(void*)mathilbert,8,"L","mathilbert(n): Hilbert matrix of order n."},
-{"mathnf",0,(void*)mathnf0,8,"GD0,L,","mathnf(M,{flag=0}): (upper triangular) Hermite normal form of M, basis for the lattice formed by the columns of M. flag is optional whose value range from 0 to 3 have a binary meaning. Bit 1: complete output, returns a 2-component vector [H,U] such that H is the HNF of M, and U is an invertible matrix such that MU=H. Bit 2: allow polynomial entries, otherwise assume that M is integral. These use a naive algorithm; larger values correspond to more in [...]
-{"mathnfmod",0,(void*)hnfmod,8,"GG","mathnfmod(x,d): (upper triangular) Hermite normal form of x, basis for the lattice formed by the columns of x, where d is a multiple of the non-zero determinant of this lattice."},
-{"mathnfmodid",0,(void*)hnfmodid,8,"GG","mathnfmodid(x,d): (upper triangular) Hermite normal form of x concatenated with matdiagonal(d)"},
-{"mathouseholder",0,(void*)mathouseholder,8,"GG","mathouseholder(Q,v): applies a sequence Q of Householder transforms to the vector or matrix v."},
-{"matid",0,(void*)matid,8,"L","matid(n): identity matrix of order n."},
-{"matimage",0,(void*)matimage0,8,"GD0,L,","matimage(x,{flag=0}): basis of the image of the matrix x. flag is optional and can be set to 0 or 1, corresponding to two different algorithms."},
-{"matimagecompl",0,(void*)imagecompl,8,"G","matimagecompl(x): vector of column indices not corresponding to the indices given by the function matimage."},
-{"matindexrank",0,(void*)indexrank,8,"G","matindexrank(x): gives two extraction vectors (rows and columns) for the matrix x such that the extracted matrix is square of maximal rank."},
-{"matintersect",0,(void*)intersect,8,"GG","matintersect(x,y): intersection of the vector spaces whose bases are the columns of x and y."},
-{"matinverseimage",0,(void*)inverseimage,8,"GG","matinverseimage(x,y): an element of the inverse image of the vector y by the matrix x if one exists, the empty vector otherwise."},
-{"matisdiagonal",0,(void*)isdiagonal,8,"iG","matisdiagonal(x): true(1) if x is a diagonal matrix, false(0) otherwise."},
-{"matker",0,(void*)matker0,8,"GD0,L,","matker(x,{flag=0}): basis of the kernel of the matrix x. flag is optional, and may be set to 0: default; non-zero: x is known to have integral entries."},
-{"matkerint",0,(void*)matkerint0,8,"GD0,L,","matkerint(x,{flag=0}): LLL-reduced Z-basis of the kernel of the matrix x with integral entries. flag is optional, and may be set to 0: default, uses LLL, 1: uses matrixqz (much slower)."},
-{"matmuldiagonal",0,(void*)matmuldiagonal,8,"GG","matmuldiagonal(x,d): product of matrix x by diagonal matrix whose diagonal coefficients are those of the vector d, equivalent but faster than x*matdiagonal(d)."},
-{"matmultodiagonal",0,(void*)matmultodiagonal,8,"GG","matmultodiagonal(x,y): product of matrices x and y, knowing that the result will be a diagonal matrix. Much faster than general multiplication in that case."},
-{"matpascal",0,(void*)matqpascal,8,"LDG","matpascal(n,{q}): Pascal triangle of order n if q is omitted. q-Pascal triangle otherwise."},
-{"matqr",0,(void*)matqr,8,"GD0,L,p","matqr(M,{flag=0}): returns [Q,R], the QR-decomposition of the square invertible matrix M. If flag=1, Q is given as a sequence of Householder transforms (faster and stabler)."},
-{"matrank",0,(void*)rank,8,"lG","matrank(x): rank of the matrix x."},
-{"matrix",0,(void*)matrice,8,"GGDVDVDE","matrix(m,n,{X},{Y},{expr=0}): mXn matrix of expression expr, the row variable X going from 1 to m and the column variable Y going from 1 to n. By default, fill with 0s."},
-{"matrixqz",0,(void*)matrixqz0,8,"GDG","matrixqz(A,{p=0}): if p>=0, transforms the rational or integral mxn (m>=n) matrix A into an integral matrix with gcd of maximal determinants coprime to p. If p=-1, finds a basis of the intersection with Z^n of the lattice spanned by the columns of A. If p=-2, finds a basis of the intersection with Z^n of the Q-vector space spanned by the columns of A."},
-{"matsize",0,(void*)matsize,8,"G","matsize(x): number of rows and columns of the vector/matrix x as a 2-vector."},
-{"matsnf",0,(void*)matsnf0,8,"GD0,L,","matsnf(X,{flag=0}): Smith normal form (i.e. elementary divisors) of the matrix X, expressed as a vector d. Binary digits of flag mean 1: returns [u,v,d] where d=u*X*v, otherwise only the diagonal d is returned, 2: allow polynomial entries, otherwise assume X is integral, 4: removes all information corresponding to entries equal to 1 in d."},
-{"matsolve",0,(void*)gauss,8,"GG","matsolve(M,B): solution of MX=B (M matrix, B column vector)."},
-{"matsolvemod",0,(void*)matsolvemod0,8,"GGGD0,L,","matsolvemod(M,D,B,{flag=0}): one solution of system of congruences MX=B mod D (M matrix, B and D column vectors). If (optional) flag is non-null return all solutions."},
-{"matsupplement",0,(void*)suppl,8,"G","matsupplement(x): supplement the columns of the matrix x to an invertible matrix."},
-{"mattranspose",0,(void*)gtrans,8,"G","mattranspose(x): x~ = transpose of x."},
+{"matadjoint",0,(void*)matadjoint0,10,"GD0,L,","matadjoint(M,{flag=0}): adjoint matrix of M using Leverrier-Faddeev's algorithm. If flag is 1, compute the characteristic polynomial independently first."},
+{"matalgtobasis",0,(void*)matalgtobasis,7,"GG","matalgtobasis(nf,x): nfalgtobasis applied to every element of the vector or matrix x."},
+{"matbasistoalg",0,(void*)matbasistoalg,7,"GG","matbasistoalg(nf,x): nfbasistoalg applied to every element of the matrix or vector x."},
+{"matcompanion",0,(void*)matcompanion,10,"G","matcompanion(x): companion matrix to polynomial x."},
+{"matconcat",0,(void*)matconcat,10,"G","matconcat(v): concatenate the entries of v and return the resulting matrix"},
+{"matdet",0,(void*)det0,10,"GD0,L,","matdet(x,{flag=0}): determinant of the matrix x using an appropriate algorithm depending on the coefficients. If (optional) flag is set to 1, use classical Gaussian elimination (usually worse than the default)."},
+{"matdetint",0,(void*)detint,10,"G","matdetint(B): some multiple of the determinant of the lattice generated by the columns of B (0 if not of maximal rank). Useful with mathnfmod."},
+{"matdiagonal",0,(void*)diagonal,10,"G","matdiagonal(x): creates the diagonal matrix whose diagonal entries are the entries of the vector x."},
+{"mateigen",0,(void*)mateigen,10,"GD0,L,p","mateigen(x,{flag=0}): complex eigenvectors of the matrix x given as columns of a matrix H. If flag=1, return [L,H], where L contains the eigenvalues and H the corresponding eigenvectors."},
+{"matfrobenius",0,(void*)matfrobenius,10,"GD0,L,Dn","matfrobenius(M,{flag},{v='x}): Return the Frobenius form of the square matrix M. If flag is 1, return only the elementary divisors as a vector of polynomials in the variable v. If flag is 2, return a two-components vector [F,B] where F is the Frobenius form and B is the basis change so that M=B^-1*F*B."},
+{"mathess",0,(void*)hess,10,"G","mathess(x): Hessenberg form of x."},
+{"mathilbert",0,(void*)mathilbert,10,"L","mathilbert(n): Hilbert matrix of order n."},
+{"mathnf",0,(void*)mathnf0,10,"GD0,L,","mathnf(M,{flag=0}): (upper triangular) Hermite normal form of M, basis for the lattice formed by the columns of M. flag is optional whose value range from 0 to 3 have a binary meaning. Bit 1: complete output, returns a 2-component vector [H,U] such that H is the HNF of M, and U is an invertible matrix such that MU=H. Bit 2: allow polynomial entries, otherwise assume that M is integral. These use a naive algorithm; larger values correspond to more i [...]
+{"mathnfmod",0,(void*)hnfmod,10,"GG","mathnfmod(x,d): (upper triangular) Hermite normal form of x, basis for the lattice formed by the columns of x, where d is a multiple of the non-zero determinant of this lattice."},
+{"mathnfmodid",0,(void*)hnfmodid,10,"GG","mathnfmodid(x,d): (upper triangular) Hermite normal form of x concatenated with matdiagonal(d)"},
+{"mathouseholder",0,(void*)mathouseholder,10,"GG","mathouseholder(Q,v): applies a sequence Q of Householder transforms to the vector or matrix v."},
+{"matid",0,(void*)matid,10,"L","matid(n): identity matrix of order n."},
+{"matimage",0,(void*)matimage0,10,"GD0,L,","matimage(x,{flag=0}): basis of the image of the matrix x. flag is optional and can be set to 0 or 1, corresponding to two different algorithms."},
+{"matimagecompl",0,(void*)imagecompl,10,"G","matimagecompl(x): vector of column indices not corresponding to the indices given by the function matimage."},
+{"matindexrank",0,(void*)indexrank,10,"G","matindexrank(x): gives two extraction vectors (rows and columns) for the matrix x such that the extracted matrix is square of maximal rank."},
+{"matintersect",0,(void*)intersect,10,"GG","matintersect(x,y): intersection of the vector spaces whose bases are the columns of x and y."},
+{"matinverseimage",0,(void*)inverseimage,10,"GG","matinverseimage(x,y): an element of the inverse image of the vector y by the matrix x if one exists, the empty vector otherwise."},
+{"matisdiagonal",0,(void*)isdiagonal,10,"iG","matisdiagonal(x): true(1) if x is a diagonal matrix, false(0) otherwise."},
+{"matker",0,(void*)matker0,10,"GD0,L,","matker(x,{flag=0}): basis of the kernel of the matrix x. flag is optional, and may be set to 0: default; non-zero: x is known to have integral entries."},
+{"matkerint",0,(void*)matkerint0,10,"GD0,L,","matkerint(x,{flag=0}): LLL-reduced Z-basis of the kernel of the matrix x with integral entries. flag is deprecated, and may be set to 0 or 1 for backward compatibility."},
+{"matmuldiagonal",0,(void*)matmuldiagonal,10,"GG","matmuldiagonal(x,d): product of matrix x by diagonal matrix whose diagonal coefficients are those of the vector d, equivalent but faster than x*matdiagonal(d)."},
+{"matmultodiagonal",0,(void*)matmultodiagonal,10,"GG","matmultodiagonal(x,y): product of matrices x and y, knowing that the result will be a diagonal matrix. Much faster than general multiplication in that case."},
+{"matpascal",0,(void*)matqpascal,10,"LDG","matpascal(n,{q}): Pascal triangle of order n if q is omitted. q-Pascal triangle otherwise."},
+{"matqr",0,(void*)matqr,10,"GD0,L,p","matqr(M,{flag=0}): returns [Q,R], the QR-decomposition of the square invertible matrix M. If flag=1, Q is given as a sequence of Householder transforms (faster and stabler)."},
+{"matrank",0,(void*)rank,10,"lG","matrank(x): rank of the matrix x."},
+{"matrix",0,(void*)matrice,10,"GGDVDVDE","matrix(m,n,{X},{Y},{expr=0}): mXn matrix of expression expr, the row variable X going from 1 to m and the column variable Y going from 1 to n. By default, fill with 0s."},
+{"matrixqz",0,(void*)matrixqz0,10,"GDG","matrixqz(A,{p=0}): if p>=0, transforms the rational or integral mxn (m>=n) matrix A into an integral matrix with gcd of maximal determinants coprime to p. If p=-1, finds a basis of the intersection with Z^n of the lattice spanned by the columns of A. If p=-2, finds a basis of the intersection with Z^n of the Q-vector space spanned by the columns of A."},
+{"matsize",0,(void*)matsize,10,"G","matsize(x): number of rows and columns of the vector/matrix x as a 2-vector."},
+{"matsnf",0,(void*)matsnf0,10,"GD0,L,","matsnf(X,{flag=0}): Smith normal form (i.e. elementary divisors) of the matrix X, expressed as a vector d. Binary digits of flag mean 1: returns [u,v,d] where d=u*X*v, otherwise only the diagonal d is returned, 2: allow polynomial entries, otherwise assume X is integral, 4: removes all information corresponding to entries equal to 1 in d."},
+{"matsolve",0,(void*)gauss,10,"GG","matsolve(M,B): solution of MX=B (M matrix, B column vector)."},
+{"matsolvemod",0,(void*)matsolvemod0,10,"GGGD0,L,","matsolvemod(M,D,B,{flag=0}): one solution of system of congruences MX=B mod D (M matrix, B and D column vectors). If (optional) flag is non-null return all solutions."},
+{"matsupplement",0,(void*)suppl,10,"G","matsupplement(x): supplement the columns of the matrix x to an invertible matrix."},
+{"mattranspose",0,(void*)gtrans,10,"G","mattranspose(x): x~ = transpose of x."},
 {"max",0,(void*)gmax,1,"GG","max(x,y): maximum of x and y"},
 {"min",0,(void*)gmin,1,"GG","min(x,y): minimum of x and y"},
-{"minpoly",0,(void*)minpoly,8,"GDn","minpoly(A,{v='x}): minimal polynomial of the matrix or polmod A."},
-{"modreverse",0,(void*)modreverse,6,"G","modreverse(z): reverse polmod of the polmod z, if it exists."},
+{"minpoly",0,(void*)minpoly,10,"GDn","minpoly(A,{v='x}): minimal polynomial of the matrix or polmod A."},
+{"modreverse",0,(void*)modreverse,7,"G","modreverse(z): reverse polmod of the polmod z, if it exists."},
 {"moebius",0,(void*)moebius,4,"lG","moebius(x): Moebius function of x."},
-{"my",0,NULL,11,NULL,"my(x,...,z): declare x,...,z as lexically-scoped local variables."},
-{"newtonpoly",0,(void*)newtonpoly,6,"GG","newtonpoly(x,p): Newton polygon of polynomial x with respect to the prime p."},
-{"next",0,(void*)next0,11,"D1,L,","next({n=1}): interrupt execution of current instruction sequence, and start another iteration from the n-th innermost enclosing loops."},
+{"msatkinlehner",0,(void*)msatkinlehner,6,"GLDG","msatkinlehner(M,Q,{H}): Let M be a full modular symbol space of level N, as given by msinit, let Q | N, (Q,N/Q) = 1, and let H be a subspace stable under the Atkin-Lehner involution w_Q. Return the matrix of w_Q acting on H (M if omitted)."},
+{"mscuspidal",0,(void*)mscuspidal,6,"GD0,L,","mscuspidal(M, {flag=0}): M being a full modular symbol space, as given by msinit, return its cuspidal part S. If flag = 1, return [S,E] its decomposition into Eisenstein and cuspidal parts"},
+{"mseisenstein",0,(void*)mseisenstein,6,"G","mseisenstein(M): M being a full modular symbol space, as given by msinit, return its Eisenstein subspace"},
+{"mseval",0,(void*)mseval,6,"GGDG","mseval(M,s,{p}): M being a full modular symbol space, as given by msinit, s being a modular symbol from M and p being a path between two elements in P^1(Q), return s(p)."},
+{"msfromell",0,(void*)msfromell,6,"GD1,L,","msfromell(E, {sign=1}): return the [M, x], where M is msinit(N,2) and x is the modular symbol in M associated to the elliptic curve E/Q."},
+{"mshecke",0,(void*)mshecke,6,"GLDG","mshecke(M,p,{H}): M being a full modular symbol space, as given by msinit, p being a prime number, and H being a Hecke-stable subspace (M if omitted), return the matrix of T_p acting on H (U_p if p divides the level)."},
+{"msinit",0,(void*)msinit,6,"GGD0,L,","msinit(G, V, {sign=0}): given G a finite index subgroup of SL(2,Z) and a finite dimensional representation V of GL(2,Q), creates a space of modular symbols, the G-module Hom_G(Div^0(P^1 Q), V). This is canonically isomorphic to H^1_c(X(G), V), and allows to compute modular forms for G. If sign is present and non-zero, it must be +1 or -1 and we consider the subspace defined by Ker (Sigma - sign), where Sigma is induced by [-1,0;0,1]. Currently the o [...]
+{"msissymbol",0,(void*)msissymbol,6,"lGG","msissymbol(M,s): M being a full modular symbol space, as given by msinit, check whether s is a modular symbol associated to M"},
+{"msnew",0,(void*)msnew,6,"G","msnew(M): M being a full modular symbol space, as given by msinit, return its new cuspidal subspace"},
+{"mspathgens",0,(void*)mspathgens,6,"G","mspathgens(M): M being a full modular symbol space, as given by msinit, return a set of Z[G]-generators for Div^0(P^1 Q). The output is [g,R], where g is a minimal system of generators and R the vector of Z[G]-relations between the given generators."},
+{"mspathlog",0,(void*)mspathlog,6,"GG","mspathlog(M,p): M being a full modular symbol space, as given by msinit and p being a path between two elements in P^1(Q), return (p_i) in Z[G] such that p = \\sum p_i g_i, and the g_i are fixed Z[G]-generators for Div^0(P^1 Q), see mspathgens."},
+{"msqexpansion",0,(void*)msqexpansion,6,"GGDP","msqexpansion(M,projH,{B = seriesprecision}): M being a full modular symbol space, as given by msinit, and projH being a projector on a Hecke-simple subspace, return the Fourier coefficients [a_n, n <= B] of the corresponding normalized newform. If B omitted, use seriesprecision"},
+{"mssplit",0,(void*)mssplit,6,"GG","mssplit(M,H): M being a full modular symbol space, as given by msinit, and H being a subspace, split H into Hecke-simple subspaces."},
+{"msstar",0,(void*)msstar,6,"GDG","msstar(M,{H}): M being a full modular symbol space, as given by msinit, return the matrix of the * involution, induced by complex conjugation, acting on the (stable) subspace H (M if omitted)."},
+{"my",0,NULL,13,NULL,"my(x,...,z): declare x,...,z as lexically-scoped local variables."},
+{"newtonpoly",0,(void*)newtonpoly,7,"GG","newtonpoly(x,p): Newton polygon of polynomial x with respect to the prime p."},
+{"next",0,(void*)next0,13,"D1,L,","next({n=1}): interrupt execution of current instruction sequence, and start another iteration from the n-th innermost enclosing loops."},
 {"nextprime",0,(void*)nextprime,4,"G","nextprime(x): smallest pseudoprime >= x."},
-{"nfalgtobasis",0,(void*)algtobasis,6,"GG","nfalgtobasis(nf,x): transforms the algebraic number x into a column vector on the integral basis nf.zk."},
-{"nfbasis",0,(void*)nfbasis_gp,6,"GDGDG","nfbasis(T): integral basis of the field Q[a], where a is a root of the polynomial T, using the round 4 algorithm. An argument [T,listP] is possible, where listP is a list of primes (to get an order which is maximal at certain primes only) or a prime bound."},
-{"nfbasistoalg",0,(void*)basistoalg,6,"GG","nfbasistoalg(nf,x): transforms the column vector x on the integral basis into an algebraic number."},
-{"nfcertify",0,(void*)nfcertify,6,"G","nfcertify(nf): returns a vector of composite integers used to certify nf.zk and nf.disc unconditionally (both are correct when the output is the empty vector)."},
-{"nfdetint",0,(void*)nfdetint,6,"GG","nfdetint(nf,x): multiple of the ideal determinant of the pseudo generating set x."},
-{"nfdisc",0,(void*)nfdisc_gp,6,"GDGDG","nfdisc(T): discriminant of the number field defined by the polynomial T. An argument [T,listP] is possible, where listP is a list of primes or a prime bound."},
-{"nfeltadd",0,(void*)nfadd,6,"GGG","nfadd(nf,x,y): element x+y in nf."},
-{"nfeltdiv",0,(void*)nfdiv,6,"GGG","nfdiv(nf,x,y): element x/y in nf."},
-{"nfeltdiveuc",0,(void*)nfdiveuc,6,"GGG","nfdiveuc(nf,x,y): gives algebraic integer q such that x-by is small."},
-{"nfeltdivmodpr",0,(void*)nfdivmodpr,6,"GGGG","nfeltdivmodpr(nf,x,y,pr): element x/y modulo pr in nf, where pr is in modpr format (see nfmodprinit)."},
-{"nfeltdivrem",0,(void*)nfdivrem,6,"GGG","nfeltdivrem(nf,x,y): gives [q,r] such that r=x-by is small."},
-{"nfeltmod",0,(void*)nfmod,6,"GGG","nfeltmod(nf,x,y): gives r such that r=x-by is small with q algebraic integer."},
-{"nfeltmul",0,(void*)nfmul,6,"GGG","nfmul(nf,x,y): element x.y in nf."},
-{"nfeltmulmodpr",0,(void*)nfmulmodpr,6,"GGGG","nfeltmulmodpr(nf,x,y,pr): element x.y modulo pr in nf, where pr is in modpr format (see nfmodprinit)."},
-{"nfeltnorm",0,(void*)nfnorm,6,"GG","nfeltnorm(nf,x): norm of x."},
-{"nfeltpow",0,(void*)nfpow,6,"GGG","nfeltpow(nf,x,k): element x^k in nf."},
-{"nfeltpowmodpr",0,(void*)nfpowmodpr,6,"GGGG","nfeltpowmodpr(nf,x,k,pr): element x^k modulo pr in nf, where pr is in modpr format (see nfmodprinit)."},
-{"nfeltreduce",0,(void*)nfreduce,6,"GGG","nfeltreduce(nf,a,id): gives r such that a-r is in the ideal id and r is small."},
-{"nfeltreducemodpr",0,(void*)nfreducemodpr,6,"GGG","nfeltreducemodpr(nf,x,pr): element x modulo pr in nf, where pr is in modpr format (see nfmodprinit)."},
-{"nfelttrace",0,(void*)nftrace,6,"GG","nfelttrace(nf,x): trace of x."},
-{"nfeltval",0,(void*)nfval,6,"lGGG","nfeltval(nf,x,pr): valuation of element x at the prime pr as output by idealprimedec."},
-{"nffactor",0,(void*)nffactor,6,"GG","nffactor(nf,T): factor polynomial T in number field nf."},
-{"nffactorback",0,(void*)nffactorback,6,"GGDG","nffactorback(nf,f,{e}): given a factorisation f, returns the factored object back as an nf element."},
-{"nffactormod",0,(void*)nffactormod,6,"GGG","nffactormod(nf,Q,pr): factor polynomial Q modulo prime ideal pr in number field nf."},
-{"nfgaloisapply",0,(void*)galoisapply,6,"GGG","nfgaloisapply(nf,aut,x): Apply the Galois automorphism aut to the object x (element or ideal) in the number field nf."},
-{"nfgaloisconj",0,(void*)galoisconj0,6,"GD0,L,DGp","nfgaloisconj(nf,{flag=0},{d}): list of conjugates of a root of the polynomial x=nf.pol in the same number field. flag is optional (set to 0 by default), meaning 0: use combination of flag 4 and 1, always complete; 1: use nfroots; 2 : use complex numbers, LLL on integral basis (not always complete); 4: use Allombert's algorithm, complete if the field is Galois of degree <= 35 (see manual for details). nf can be simply a polynomial."},
-{"nfhilbert",0,(void*)nfhilbert0,6,"lGGGDG","nfhilbert(nf,a,b,{pr}): if pr is omitted, global Hilbert symbol (a,b) in nf, that is 1 if X^2-aY^2-bZ^2 has a non-trivial solution (X,Y,Z) in nf, -1 otherwise. Otherwise compute the local symbol modulo the prime ideal pr."},
-{"nfhnf",0,(void*)nfhnf,6,"GG","nfhnf(nf,x): if x=[A,I], gives a pseudo-basis of the module sum A_jI_j"},
-{"nfhnfmod",0,(void*)nfhnfmod,6,"GGG","nfhnfmod(nf,x,detx): if x=[A,I], and detx is a multiple of the ideal determinant of x, gives a pseudo-basis of the module sum A_jI_j."},
-{"nfinit",0,(void*)nfinit0,6,"GD0,L,p","nfinit(pol,{flag=0}): pol being a nonconstant irreducible polynomial, gives the vector: [pol,[r1,r2],discf,index,[M,MC,T2,T,different] (see manual),r1+r2 first roots, integral basis, matrix of power basis in terms of integral basis, multiplication table of basis]. flag is optional and can be set to 0: default; 1: do not compute different; 2: first use polred to find a simpler polynomial; 3: outputs a two-element vector [nf,Mod(a,P)], where nf is as [...]
-{"nfisideal",0,(void*)isideal,6,"lGG","nfisideal(nf,x): true(1) if x is an ideal in the number field nf, false(0) if not."},
-{"nfisincl",0,(void*)nfisincl,6,"GG","nfisincl(x,y): tests whether the number field x is isomorphic to a subfield of y (where x and y are either polynomials or number fields as output by nfinit). Return 0 if not, and otherwise all the isomorphisms. If y is a number field, a faster algorithm is used."},
-{"nfisisom",0,(void*)nfisisom,6,"GG","nfisisom(x,y): as nfisincl but tests whether x is isomorphic to y."},
-{"nfkermodpr",0,(void*)nfkermodpr,6,"GGG","nfkermodpr(nf,x,pr): kernel of the matrix x in Z_K/pr, where pr is in modpr format (see nfmodprinit)."},
-{"nfmodprinit",0,(void*)nfmodprinit,6,"GG","nfmodprinit(nf,pr): transform the 5 element row vector pr representing a prime ideal into modpr format necessary for all operations mod pr in the number field nf (see manual for details about the format)."},
-{"nfnewprec",0,(void*)nfnewprec,6,"Gp","nfnewprec(nf): transform the number field data nf into new data using the current (usually larger) precision."},
-{"nfroots",0,(void*)nfroots,6,"DGG","nfroots({nf},x): roots of polynomial x belonging to nf (Q if omitted) without multiplicity."},
-{"nfrootsof1",0,(void*)rootsof1,6,"G","nfrootsof1(nf): number of roots of unity and primitive root of unity in the number field nf."},
-{"nfsnf",0,(void*)nfsnf,6,"GG","nfsnf(nf,x): if x=[A,I,J], outputs [c_1,...c_n] Smith normal form of x."},
-{"nfsolvemodpr",0,(void*)nfsolvemodpr,6,"GGGG","nfsolvemodpr(nf,a,b,P): solution of a*x=b in Z_K/P, where a is a matrix and b a column vector, and where P is in modpr format (see nfmodprinit)."},
-{"nfsubfields",0,(void*)nfsubfields,6,"GD0,L,","nfsubfields(pol,{d=0}): find all subfields of degree d of number field defined by pol (all subfields if d is null or omitted). Result is a vector of subfields, each being given by [g,h], where g is an absolute equation and h expresses one of the roots of g in terms of the root x of the polynomial defining nf."},
+{"nfalgtobasis",0,(void*)algtobasis,7,"GG","nfalgtobasis(nf,x): transforms the algebraic number x into a column vector on the integral basis nf.zk."},
+{"nfbasis",0,(void*)nfbasis_gp,7,"G","nfbasis(T): integral basis of the field Q[a], where a is a root of the polynomial T, using the round 4 algorithm. An argument [T,listP] is possible, where listP is a list of primes (to get an order which is maximal at certain primes only) or a prime bound."},
+{"nfbasistoalg",0,(void*)basistoalg,7,"GG","nfbasistoalg(nf,x): transforms the column vector x on the integral basis into an algebraic number."},
+{"nfcertify",0,(void*)nfcertify,7,"G","nfcertify(nf): returns a vector of composite integers used to certify nf.zk and nf.disc unconditionally (both are correct when the output is the empty vector)."},
+{"nfcompositum",0,(void*)nfcompositum,7,"GGGD0,L,","nfcompositum(nf,P,Q,{flag=0}): vector of all possible compositums of the number fields defined by the polynomials P and Q; flag is optional, whose binary digits mean 1: output for each compositum, not only the compositum polynomial pol, but a vector [R,a,b,k] where a (resp. b) is a root of P (resp. Q) expressed as a polynomial modulo R, and a small integer k such that al2+k*al1 is the chosen root of R; 2: assume that the number fields d [...]
+{"nfdetint",0,(void*)nfdetint,7,"GG","nfdetint(nf,x): multiple of the ideal determinant of the pseudo generating set x."},
+{"nfdisc",0,(void*)nfdisc,7,"G","nfdisc(T): discriminant of the number field defined by the polynomial T. An argument [T,listP] is possible, where listP is a list of primes or a prime bound."},
+{"nfeltadd",0,(void*)nfadd,7,"GGG","nfadd(nf,x,y): element x+y in nf."},
+{"nfeltdiv",0,(void*)nfdiv,7,"GGG","nfdiv(nf,x,y): element x/y in nf."},
+{"nfeltdiveuc",0,(void*)nfdiveuc,7,"GGG","nfdiveuc(nf,x,y): gives algebraic integer q such that x-by is small."},
+{"nfeltdivmodpr",0,(void*)nfdivmodpr,7,"GGGG","nfeltdivmodpr(nf,x,y,pr): element x/y modulo pr in nf, where pr is in modpr format (see nfmodprinit)."},
+{"nfeltdivrem",0,(void*)nfdivrem,7,"GGG","nfeltdivrem(nf,x,y): gives [q,r] such that r=x-by is small."},
+{"nfeltmod",0,(void*)nfmod,7,"GGG","nfeltmod(nf,x,y): gives r such that r=x-by is small with q algebraic integer."},
+{"nfeltmul",0,(void*)nfmul,7,"GGG","nfmul(nf,x,y): element x.y in nf."},
+{"nfeltmulmodpr",0,(void*)nfmulmodpr,7,"GGGG","nfeltmulmodpr(nf,x,y,pr): element x.y modulo pr in nf, where pr is in modpr format (see nfmodprinit)."},
+{"nfeltnorm",0,(void*)nfnorm,7,"GG","nfeltnorm(nf,x): norm of x."},
+{"nfeltpow",0,(void*)nfpow,7,"GGG","nfeltpow(nf,x,k): element x^k in nf."},
+{"nfeltpowmodpr",0,(void*)nfpowmodpr,7,"GGGG","nfeltpowmodpr(nf,x,k,pr): element x^k modulo pr in nf, where pr is in modpr format (see nfmodprinit)."},
+{"nfeltreduce",0,(void*)nfreduce,7,"GGG","nfeltreduce(nf,a,id): gives r such that a-r is in the ideal id and r is small."},
+{"nfeltreducemodpr",0,(void*)nfreducemodpr,7,"GGG","nfeltreducemodpr(nf,x,pr): element x modulo pr in nf, where pr is in modpr format (see nfmodprinit)."},
+{"nfelttrace",0,(void*)nftrace,7,"GG","nfelttrace(nf,x): trace of x."},
+{"nfeltval",0,(void*)gpnfvalrem,7,"GGGD&","nfeltval(nf,x,pr,{&y}): valuation of element x at the prime pr as output by idealprimedec."},
+{"nffactor",0,(void*)nffactor,7,"GG","nffactor(nf,T): factor polynomial T in number field nf."},
+{"nffactorback",0,(void*)nffactorback,7,"GGDG","nffactorback(nf,f,{e}): given a factorisation f, returns the factored object back as an nf element."},
+{"nffactormod",0,(void*)nffactormod,7,"GGG","nffactormod(nf,Q,pr): factor polynomial Q modulo prime ideal pr in number field nf."},
+{"nfgaloisapply",0,(void*)galoisapply,7,"GGG","nfgaloisapply(nf,aut,x): Apply the Galois automorphism aut to the object x (element or ideal) in the number field nf."},
+{"nfgaloisconj",0,(void*)galoisconj0,7,"GD0,L,DGp","nfgaloisconj(nf,{flag=0},{d}): list of conjugates of a root of the polynomial x=nf.pol in the same number field. flag is optional (set to 0 by default), meaning 0: use combination of flag 4 and 1, always complete; 1: use nfroots; 2 : use complex numbers, LLL on integral basis (not always complete); 4: use Allombert's algorithm, complete if the field is Galois of degree <= 35 (see manual for details). nf can be simply a polynomial."},
+{"nfgrunwaldwang",0,(void*)nfgrunwaldwang,7,"GGGGDn","nfgrunwaldwang(nf,Lpr,Ld,pl,{v='x}): a polynomial in the variable v defining a cyclic extension of nf (given in nf or bnf form) with local behaviour prescribed by Lpr, Ld and pl: the extension has local degree a multiple of Ld[i] at the prime Lpr[i], and the extension is complex at the i-th real place of nf if pl[i]=-1 (no condition if pl[i]=0). The extension has degree the LCM of the local degrees."},
+{"nfhilbert",0,(void*)nfhilbert0,7,"lGGGDG","nfhilbert(nf,a,b,{pr}): if pr is omitted, global Hilbert symbol (a,b) in nf, that is 1 if X^2-aY^2-bZ^2 has a non-trivial solution (X,Y,Z) in nf, -1 otherwise. Otherwise compute the local symbol modulo the prime ideal pr."},
+{"nfhnf",0,(void*)nfhnf0,7,"GGD0,L,","nfhnf(nf,x,{flag=0}): if x=[A,I], gives a pseudo-basis [B,J] of the module sum A_jI_j. If flag is non-zero, return [[B,J], U], where U is the transformation matrix such that AU = [0|B]"},
+{"nfhnfmod",0,(void*)nfhnfmod,7,"GGG","nfhnfmod(nf,x,detx): if x=[A,I], and detx is a multiple of the ideal determinant of x, gives a pseudo-basis of the module sum A_jI_j."},
+{"nfinit",0,(void*)nfinit0,7,"GD0,L,p","nfinit(pol,{flag=0}): pol being a nonconstant irreducible polynomial, gives the vector: [pol,[r1,r2],discf,index,[M,MC,T2,T,different] (see manual),r1+r2 first roots, integral basis, matrix of power basis in terms of integral basis, multiplication table of basis]. flag is optional and can be set to 0: default; 1: do not compute different; 2: first use polred to find a simpler polynomial; 3: outputs a two-element vector [nf,Mod(a,P)], where nf is as [...]
+{"nfisideal",0,(void*)isideal,7,"lGG","nfisideal(nf,x): true(1) if x is an ideal in the number field nf, false(0) if not."},
+{"nfisincl",0,(void*)nfisincl,7,"GG","nfisincl(x,y): tests whether the number field x is isomorphic to a subfield of y (where x and y are either polynomials or number fields as output by nfinit). Return 0 if not, and otherwise all the isomorphisms. If y is a number field, a faster algorithm is used."},
+{"nfisisom",0,(void*)nfisisom,7,"GG","nfisisom(x,y): as nfisincl but tests whether x is isomorphic to y."},
+{"nfkermodpr",0,(void*)nfkermodpr,7,"GGG","nfkermodpr(nf,x,pr): kernel of the matrix x in Z_K/pr, where pr is in modpr format (see nfmodprinit)."},
+{"nfmodprinit",0,(void*)nfmodprinit,7,"GG","nfmodprinit(nf,pr): transform the 5 element row vector pr representing a prime ideal into modpr format necessary for all operations mod pr in the number field nf (see manual for details about the format)."},
+{"nfnewprec",0,(void*)nfnewprec,7,"Gp","nfnewprec(nf): transform the number field data nf into new data using the current (usually larger) precision."},
+{"nfroots",0,(void*)nfroots,7,"DGG","nfroots({nf},x): roots of polynomial x belonging to nf (Q if omitted) without multiplicity."},
+{"nfrootsof1",0,(void*)rootsof1,7,"G","nfrootsof1(nf): number of roots of unity and primitive root of unity in the number field nf."},
+{"nfsnf",0,(void*)nfsnf0,7,"GGD0,L,","nfsnf(nf,x,{flag=0}): if x=[A,I,J], outputs D=[d_1,...d_n] Smith normal form of x. If flag is non-zero return [D,U,V], where UAV = Id."},
+{"nfsolvemodpr",0,(void*)nfsolvemodpr,7,"GGGG","nfsolvemodpr(nf,a,b,P): solution of a*x=b in Z_K/P, where a is a matrix and b a column vector, and where P is in modpr format (see nfmodprinit)."},
+{"nfsplitting",0,(void*)nfsplitting,7,"GDG","nfsplitting(nf,{d}): defining polynomial for the splitting field of the number field nf; if d is given, it must be the degree of the splitting field"},
+{"nfsubfields",0,(void*)nfsubfields,7,"GD0,L,","nfsubfields(pol,{d=0}): find all subfields of degree d of number field defined by pol (all subfields if d is null or omitted). Result is a vector of subfields, each being given by [g,h], where g is an absolute equation and h expresses one of the roots of g in terms of the root x of the polynomial defining nf."},
 {"norm",0,(void*)gnorm,2,"G","norm(x): norm of x."},
-{"norml2",0,(void*)gnorml2,8,"G","norml2(x): square of the L2-norm of x."},
-{"normlp",0,(void*)gnormlp,8,"GDGp","normlp(x,{p}): Lp-norm of x; sup norm if p is omitted."},
+{"norml2",0,(void*)gnorml2,10,"G","norml2(x): square of the L2-norm of x."},
+{"normlp",0,(void*)gnormlp,10,"GDGp","normlp(x,{p}): Lp-norm of x; sup norm if p is omitted."},
 {"numbpart",0,(void*)numbpart,4,"G","numbpart(n): number of partitions of n."},
 {"numdiv",0,(void*)numdiv,4,"G","numdiv(x): number of divisors of x."},
 {"numerator",0,(void*)numer,2,"G","numerator(x): numerator of x."},
 {"numtoperm",0,(void*)numtoperm,2,"LG","numtoperm(n,k): permutation number k (mod n!) of n letters (n C-integer)."},
 {"omega",0,(void*)omega,4,"lG","omega(x): number of distinct prime divisors of x."},
-{"padicappr",0,(void*)padicappr,7,"GG","padicappr(pol,a): p-adic roots of the polynomial pol congruent to a mod p."},
-{"padicfields",0,(void*)padicfields0,7,"GGD0,L,","padicfields(p, N, {flag=0}): returns polynomials generating all the extensions of degree N of the field of p-adic rational numbers; N is allowed to be a 2-component vector [n,d], in which case, returns the extensions of degree n and discriminant p^d. flag is optional, and can be 0: default, 1: return also the ramification index, the residual degree, the valuation of the discriminant and the number of conjugate fields, or 2: return only th [...]
+{"oo",0,(void*)mkoo,2,"","oo: infinity."},
+{"padicappr",0,(void*)padicappr,9,"GG","padicappr(pol,a): p-adic roots of the polynomial pol congruent to a mod p."},
+{"padicfields",0,(void*)padicfields0,9,"GGD0,L,","padicfields(p, N, {flag=0}): returns polynomials generating all the extensions of degree N of the field of p-adic rational numbers; N is allowed to be a 2-component vector [n,d], in which case, returns the extensions of degree n and discriminant p^d. flag is optional, and can be 0: default, 1: return also the ramification index, the residual degree, the valuation of the discriminant and the number of conjugate fields, or 2: return only th [...]
 {"padicprec",0,(void*)padicprec,2,"lGG","padicprec(x,p): absolute p-adic precision of object x."},
-{"parapply",0,(void*)parapply,11,"GG","parapply(f, x): parallel evaluation of f on the elements of x."},
-{"pareval",0,(void*)pareval,11,"G","pareval(x): parallel evaluation of the elements of the vector of closures x."},
-{"parfor",0,(void*)parfor,11,"vV=GDGJDVDI","parfor(i=a,{b},expr1,{j},{expr2}): evaluates the sequence expr2 (dependent on i and j) for i between a and b, in random order, computed in parallel. Substitute for j the value of expr1 (dependent on i). If b is omitted, the loop will not stop."},
-{"parforprime",0,(void*)parforprime,11,"vV=GDGJDVDI","parforprime(p=a,{b},expr1,{j},{expr2}): evaluates the sequence expr2 (dependent on p and j) for p prime between a and b, in random order, computed in parallel. Substitute for j the value of expr1 (dependent on i). If b is omitted, the loop will not stop."},
-{"parselect",0,(void*)parselect,11,"GGD0,L,","parselect(f, A, {flag = 0}): (parallel select) selects elements of A according to the selection function f which is tested in parallel. If flag is 1, return the indices of those elements (indirect selection)"},
-{"parsum",0,(void*)parsum,11,"V=GGJDG","parsum(i=a,b,expr,{x}): x plus the sum (X goes from a to b) of expression expr, evaluated in parallel (in random order)"},
+{"parapply",0,(void*)parapply,13,"GG","parapply(f, x): parallel evaluation of f on the elements of x."},
+{"pareval",0,(void*)pareval,13,"G","pareval(x): parallel evaluation of the elements of the vector of closures x."},
+{"parfor",0,(void*)parfor0,13,"vV=GDGJDVDI","parfor(i=a,{b},expr1,{j},{expr2}): evaluates the sequence expr2 (dependent on i and j) for i between a and b, in random order, computed in parallel. Substitute for j the value of expr1 (dependent on i). If b is omitted, the loop will not stop."},
+{"parforprime",0,(void*)parforprime0,13,"vV=GDGJDVDI","parforprime(p=a,{b},expr1,{j},{expr2}): evaluates the sequence expr2 (dependent on p and j) for p prime between a and b, in random order, computed in parallel. Substitute for j the value of expr1 (dependent on p). If b is omitted, the loop will not stop."},
+{"parselect",0,(void*)parselect,13,"GGD0,L,","parselect(f, A, {flag = 0}): (parallel select) selects elements of A according to the selection function f which is tested in parallel. If flag is 1, return the indices of those elements (indirect selection)"},
+{"parsum",0,(void*)parsum,13,"V=GGJDG","parsum(i=a,b,expr,{x}): x plus the sum (X goes from a to b) of expression expr, evaluated in parallel (in random order)"},
 {"partitions",0,(void*)partitions,4,"LDGDG","partitions(k,{a=k},{n=k})): vector of partitions of the integer k. You can restrict the length of the partitions with parameter n (n=nmax or n=[nmin,nmax]), or the range of the parts with parameter a (a=amax or a=[amin,amax]). By default remove zeros, but one can set amin=0 to get X of fixed length nmax (=k by default)."},
-{"parvector",0,(void*)parvector,11,"LVJ","parvector(N,i,expr): as vector(N,i,expr) but the evaluations of expr are done in parallel."},
+{"parvector",0,(void*)parvector,13,"LVJ","parvector(N,i,expr): as vector(N,i,expr) but the evaluations of expr are done in parallel."},
 {"permtonum",0,(void*)permtonum,2,"G","permtonum(x): ordinal (between 1 and n!) of permutation x."},
-{"polchebyshev",0,(void*)polchebyshev_eval,7,"LD1,L,DG","polchebyshev(n,{flag=1},{a='x}): Chebychev polynomial of the first (flag = 1) or second (flag = 2) kind, of degree n, evaluated at a."},
-{"polcoeff",0,(void*)polcoeff0,7,"GLDn","polcoeff(x,n,{v}): coefficient of degree n of x, or the n-th component for vectors or matrices (for which it is simpler to use x[]). With respect to the main variable if v is omitted, with respect to the variable v otherwise."},
-{"polcompositum",0,(void*)polcompositum0,6,"GGD0,L,","polcompositum(P,Q,{flag=0}): vector of all possible compositums of the number fields defined by the polynomials P and Q. If (optional) flag is set (i.e non-null), output for each compositum, not only the compositum polynomial pol, but a vector [R,a,b,k] where a (resp. b) is a root of P (resp. Q) expressed as a polynomial modulo R, and a small integer k such that al2+k*al1 is the chosen root of R."},
-{"polcyclo",0,(void*)polcyclo_eval,7,"LDG","polcyclo(n,{a = 'x}): n-th cyclotomic polynomial evaluated at a."},
-{"polcyclofactors",0,(void*)polcyclofactors,7,"G","polcyclofactors(f): returns a vector of polynomials, whose product is the product of distinct cyclotomic polynomials dividing f."},
-{"poldegree",0,(void*)poldegree,7,"lGDn","poldegree(x,{v}): degree of the polynomial or rational function x with respect to main variable if v is omitted, with respect to v otherwise. For scalar x, return 0 is x is non-zero and a negative number otherwise."},
-{"poldisc",0,(void*)poldisc0,7,"GDn","poldisc(pol,{v}): discriminant of the polynomial pol, with respect to main variable if v is omitted, with respect to v otherwise."},
-{"poldiscreduced",0,(void*)reduceddiscsmith,7,"G","poldiscreduced(f): vector of elementary divisors of Z[a]/f'(a)Z[a], where a is a root of the polynomial f."},
-{"polgalois",0,(void*)polgalois,6,"Gp","polgalois(T): Galois group of the polynomial T (see manual for group coding). Return [n, s, k, name] where n is the group order, s the signature, k the index and name is the GAP4 name of the transitive group."},
-{"polgraeffe",0,(void*)polgraeffe,7,"G","polgraeffe(f): returns the Graeffe transform g of f, such that g(x^2) = f(x)f(-x)"},
-{"polhensellift",0,(void*)polhensellift,7,"GGGL","polhensellift(A, B, p, e): lift the factorization B of A modulo p to a factorization modulo p^e using Hensel lift. The factors in B must be pairwise relatively prime modulo p."},
-{"polhermite",0,(void*)polhermite_eval,7,"LDG","polhermite(n,{a='x}): Hermite polynomial H(n,v) of degree n, evaluated at a."},
-{"polinterpolate",0,(void*)polint,7,"GDGDGD&","polinterpolate(X,{Y},{x},{&e}): polynomial interpolation at x according to data vectors X, Y (ie return P such that P(X[i]) = Y[i] for all i). If Y is omitted, return P such that P(i) = X[i]. If present, e will contain an error estimate on the returned value."},
-{"poliscyclo",0,(void*)poliscyclo,7,"lG","poliscyclo(f): returns 0 if f is not a cyclotomic polynomial, and n > 0 if f = Phi_n, the n-th cyclotomic polynomial."},
-{"poliscycloprod",0,(void*)poliscycloprod,7,"lG","poliscycloprod(f): returns 1 if f is a product of cyclotomic polynonials, and 0 otherwise."},
-{"polisirreducible",0,(void*)isirreducible,7,"lG","polisirreducible(pol): true(1) if pol is an irreducible non-constant polynomial, false(0) if pol is reducible or constant."},
-{"pollead",0,(void*)pollead,7,"GDn","pollead(x,{v}): leading coefficient of polynomial or series x, or x itself if x is a scalar. Error otherwise. With respect to the main variable of x if v is omitted, with respect to the variable v otherwise."},
-{"pollegendre",0,(void*)pollegendre_eval,7,"LDG","pollegendre(n,{a='x}): legendre polynomial of degree n evaluated at a."},
-{"polrecip",0,(void*)polrecip,7,"G","polrecip(pol): reciprocal polynomial of pol."},
-{"polred",0,(void*)polred0,6,"GD0,L,DG","polred(T,{flag=0}): Deprecated, use polredbest. Reduction of the polynomial T (gives minimal polynomials only). The following binary digits of (optional) flag are significant 1: partial reduction, 2: gives also elements."},
-{"polredabs",0,(void*)polredabs0,6,"GD0,L,","polredabs(T,{flag=0}): a smallest generating polynomial of the number field for the T2 norm on the roots, with smallest index for the minimal T2 norm. flag is optional, whose binary digit mean 1: give the element whose characteristic polynomial is the given polynomial. 4: give all polynomials of minimal T2 norm (give only one of P(x) and P(-x))."},
-{"polredbest",0,(void*)polredbest,6,"GD0,L,","polredbest(T,{flag=0}): reduction of the polynomial T (gives minimal polynomials only). If flag=1, gives also elements."},
-{"polredord",0,(void*)polredord,6,"G","polredord(x): reduction of the polynomial x, staying in the same order."},
-{"polresultant",0,(void*)polresultant0,7,"GGDnD0,L,","polresultant(x,y,{v},{flag=0}): resultant of the polynomials x and y, with respect to the main variables of x and y if v is omitted, with respect to the variable v otherwise. flag is optional, and can be 0: default, uses either the subresultant algorithm, a modular algorithm or Sylvester's matrix, depending on the inputs; 1 uses Sylvester's matrix (should always be slower than the default)."},
-{"polresultantext",0,(void*)polresultantext0,7,"GGDn","polresultantext(A,B,{v}): return [U,V,R] such that R=polresultant(A,B,v) and U*A+V*B = R, where A and B are polynomials."},
-{"polroots",0,(void*)roots,7,"Gp","polroots(x): complex roots of the polynomial x using Schonhage's method, as modified by Gourdon."},
+{"polchebyshev",0,(void*)polchebyshev_eval,9,"LD1,L,DG","polchebyshev(n,{flag=1},{a='x}): Chebychev polynomial of the first (flag = 1) or second (flag = 2) kind, of degree n, evaluated at a."},
+{"polclass",0,(void*)polclass,9,"GDn","polclass(D, {x = 'x}): return the Hilbert class polynomial for the disciminant D."},
+{"polcoeff",0,(void*)polcoeff0,9,"GLDn","polcoeff(x,n,{v}): coefficient of degree n of x, or the n-th component for vectors or matrices (for which it is simpler to use x[]). With respect to the main variable if v is omitted, with respect to the variable v otherwise."},
+{"polcompositum",0,(void*)polcompositum0,7,"GGD0,L,","polcompositum(P,Q,{flag=0}): vector of all possible compositums of the number fields defined by the polynomials P and Q; flag is optional, whose binary digits mean 1: output for each compositum, not only the compositum polynomial pol, but a vector [R,a,b,k] where a (resp. b) is a root of P (resp. Q) expressed as a polynomial modulo R, and a small integer k such that al2+k*al1 is the chosen root of R; 2: assume that the number fields d [...]
+{"polcyclo",0,(void*)polcyclo_eval,9,"LDG","polcyclo(n,{a = 'x}): n-th cyclotomic polynomial evaluated at a."},
+{"polcyclofactors",0,(void*)polcyclofactors,9,"G","polcyclofactors(f): returns a vector of polynomials, whose product is the product of distinct cyclotomic polynomials dividing f."},
+{"poldegree",0,(void*)gppoldegree,9,"GDn","poldegree(x,{v}): degree of the polynomial or rational function x with respect to main variable if v is omitted, with respect to v otherwise. For scalar x, return 0 is x is non-zero and -oo otherwise."},
+{"poldisc",0,(void*)poldisc0,9,"GDn","poldisc(pol,{v}): discriminant of the polynomial pol, with respect to main variable if v is omitted, with respect to v otherwise."},
+{"poldiscreduced",0,(void*)reduceddiscsmith,9,"G","poldiscreduced(f): vector of elementary divisors of Z[a]/f'(a)Z[a], where a is a root of the polynomial f."},
+{"polgalois",0,(void*)polgalois,7,"Gp","polgalois(T): Galois group of the polynomial T (see manual for group coding). Return [n, s, k, name] where n is the group order, s the signature, k the index and name is the GAP4 name of the transitive group."},
+{"polgraeffe",0,(void*)polgraeffe,9,"G","polgraeffe(f): returns the Graeffe transform g of f, such that g(x^2) = f(x)f(-x)"},
+{"polhensellift",0,(void*)polhensellift,9,"GGGL","polhensellift(A, B, p, e): lift the factorization B of A modulo p to a factorization modulo p^e using Hensel lift. The factors in B must be pairwise relatively prime modulo p."},
+{"polhermite",0,(void*)polhermite_eval,9,"LDG","polhermite(n,{a='x}): Hermite polynomial H(n,v) of degree n, evaluated at a."},
+{"polinterpolate",0,(void*)polint,9,"GDGDGD&","polinterpolate(X,{Y},{x},{&e}): polynomial interpolation at x according to data vectors X, Y (ie return P such that P(X[i]) = Y[i] for all i). If Y is omitted, return P such that P(i) = X[i]. If present, e will contain an error estimate on the returned value."},
+{"poliscyclo",0,(void*)poliscyclo,9,"lG","poliscyclo(f): returns 0 if f is not a cyclotomic polynomial, and n > 0 if f = Phi_n, the n-th cyclotomic polynomial."},
+{"poliscycloprod",0,(void*)poliscycloprod,9,"lG","poliscycloprod(f): returns 1 if f is a product of cyclotomic polynonials, and 0 otherwise."},
+{"polisirreducible",0,(void*)isirreducible,9,"lG","polisirreducible(pol): true(1) if pol is an irreducible non-constant polynomial, false(0) if pol is reducible or constant."},
+{"pollead",0,(void*)pollead,9,"GDn","pollead(x,{v}): leading coefficient of polynomial or series x, or x itself if x is a scalar. Error otherwise. With respect to the main variable of x if v is omitted, with respect to the variable v otherwise."},
+{"pollegendre",0,(void*)pollegendre_eval,9,"LDG","pollegendre(n,{a='x}): legendre polynomial of degree n evaluated at a."},
+{"polmodular",0,(void*)polmodular,9,"LDGDnD0,L,","polmodular(L, {x = 'x}, {y = 'y}, {compute_derivs = 0}): return the modular polynomial of level L."},
+{"polrecip",0,(void*)polrecip,9,"G","polrecip(pol): reciprocal polynomial of pol."},
+{"polred",0,(void*)polred0,7,"GD0,L,DG","polred(T,{flag=0}): Deprecated, use polredbest. Reduction of the polynomial T (gives minimal polynomials only). The following binary digits of (optional) flag are significant 1: partial reduction, 2: gives also elements."},
+{"polredabs",0,(void*)polredabs0,7,"GD0,L,","polredabs(T,{flag=0}): a smallest generating polynomial of the number field for the T2 norm on the roots, with smallest index for the minimal T2 norm. flag is optional, whose binary digit mean 1: give the element whose characteristic polynomial is the given polynomial. 4: give all polynomials of minimal T2 norm (give only one of P(x) and P(-x))."},
+{"polredbest",0,(void*)polredbest,7,"GD0,L,","polredbest(T,{flag=0}): reduction of the polynomial T (gives minimal polynomials only). If flag=1, gives also elements."},
+{"polredord",0,(void*)polredord,7,"G","polredord(x): reduction of the polynomial x, staying in the same order."},
+{"polresultant",0,(void*)polresultant0,9,"GGDnD0,L,","polresultant(x,y,{v},{flag=0}): resultant of the polynomials x and y, with respect to the main variables of x and y if v is omitted, with respect to the variable v otherwise. flag is optional, and can be 0: default, uses either the subresultant algorithm, a modular algorithm or Sylvester's matrix, depending on the inputs; 1 uses Sylvester's matrix (should always be slower than the default)."},
+{"polresultantext",0,(void*)polresultantext0,9,"GGDn","polresultantext(A,B,{v}): return [U,V,R] such that R=polresultant(A,B,v) and U*A+V*B = R, where A and B are polynomials."},
+{"polroots",0,(void*)roots,9,"Gp","polroots(x): complex roots of the polynomial x using Schonhage's method, as modified by Gourdon."},
 {"polrootsff",0,(void*)polrootsff,4,"GDGDG","polrootsff(x,{p},{a}): returns the roots of the polynomial x in the finite field F_p[X]/a(X)F_p[X]. a or p can be omitted if x has t_FFELT coefficients."},
-{"polrootsmod",0,(void*)rootmod0,7,"GGD0,L,","polrootsmod(pol,p,{flag=0}): roots mod the prime p of the polynomial pol. flag is optional, and can be 0: default, or 1: use a naive search, useful for small p."},
-{"polrootspadic",0,(void*)rootpadic,7,"GGL","polrootspadic(x,p,r): p-adic roots of the polynomial x to precision r."},
-{"polsturm",0,(void*)sturmpart,7,"lGDGDG","polsturm(pol,{a},{b}): number of real roots of the squarefree polynomial pol in the interval ]a,b] (which are respectively taken to be -oo or +oo when omitted)."},
-{"polsubcyclo",0,(void*)polsubcyclo,7,"LLDn","polsubcyclo(n,d,{v='x}): finds an equation (in variable v) for the d-th degree subfields of Q(zeta_n). Output is a polynomial, or a vector of polynomials if there are several such fields or none."},
-{"polsylvestermatrix",0,(void*)sylvestermatrix,7,"GG","polsylvestermatrix(x,y): forms the sylvester matrix associated to the two polynomials x and y. Warning: the polynomial coefficients are in columns, not in rows."},
-{"polsym",0,(void*)polsym,7,"GL","polsym(x,n): column vector of symmetric powers of the roots of x up to n."},
-{"poltchebi",0,(void*)polchebyshev1,7,"LDn","poltchebi(n,{v='x}): deprecated alias for polchebyshev"},
-{"poltschirnhaus",0,(void*)tschirnhaus,6,"G","poltschirnhaus(x): random Tschirnhausen transformation of the polynomial x."},
+{"polrootsmod",0,(void*)rootmod0,9,"GGD0,L,","polrootsmod(pol,p,{flag=0}): roots mod the prime p of the polynomial pol. flag is optional, and can be 0: default, or 1: use a naive search, useful for small p."},
+{"polrootspadic",0,(void*)rootpadic,9,"GGL","polrootspadic(x,p,r): p-adic roots of the polynomial x to precision r."},
+{"polrootsreal",0,(void*)realroots,9,"GDGp","polrootsreal(T, {ab}): real roots of the polynomial T with rational coefficients, using Uspensky's method. In interval ab = [a,b] if present."},
+{"polsturm",0,(void*)sturmpart,9,"lGDGDG","polsturm(T,{ab}): number of real roots of the squarefree polynomial T (in the interval ab = [a,b] if present)."},
+{"polsubcyclo",0,(void*)polsubcyclo,9,"LLDn","polsubcyclo(n,d,{v='x}): finds an equation (in variable v) for the d-th degree subfields of Q(zeta_n). Output is a polynomial, or a vector of polynomials if there are several such fields or none."},
+{"polsylvestermatrix",0,(void*)sylvestermatrix,9,"GG","polsylvestermatrix(x,y): forms the sylvester matrix associated to the two polynomials x and y. Warning: the polynomial coefficients are in columns, not in rows."},
+{"polsym",0,(void*)polsym,9,"GL","polsym(x,n): column vector of symmetric powers of the roots of x up to n."},
+{"poltchebi",0,(void*)polchebyshev1,9,"LDn","poltchebi(n,{v='x}): deprecated alias for polchebyshev"},
+{"poltschirnhaus",0,(void*)tschirnhaus,7,"G","poltschirnhaus(x): random Tschirnhausen transformation of the polynomial x."},
 {"polylog",0,(void*)polylog0,3,"LGD0,L,p","polylog(m,x,{flag=0}): m-th polylogarithm of x. flag is optional, and can be 0: default, 1: D_m~-modified m-th polylog of x, 2: D_m-modified m-th polylog of x, 3: P_m-modified m-th polylog of x."},
-{"polzagier",0,(void*)polzag,7,"LL","polzagier(n,m): Zagier's polynomials of index n,m."},
+{"polzagier",0,(void*)polzag,9,"LL","polzagier(n,m): Zagier's polynomials of index n,m."},
+{"powers",0,(void*)gpowers,1,"GL","powers(x,n): return the vector [1,x,...,x^n]"},
 {"precision",0,(void*)precision0,2,"GD0,L,","precision(x,{n}): if n is present, return x at precision n. If n is omitted, return real precision of object x."},
 {"precprime",0,(void*)precprime,4,"G","precprime(x): largest pseudoprime <= x, 0 if x<=1."},
 {"prime",0,(void*)prime,4,"L","prime(n): returns the n-th prime (n C-integer)."},
 {"primepi",0,(void*)primepi,4,"G","primepi(x): the prime counting function pi(x) = #{p <= x, p prime}."},
 {"primes",0,(void*)primes0,4,"G","primes(n): returns the vector of the first n primes (integer), or the primes in interval n = [a,b]."},
-{"print",0,(void*)print,11,"vs*","print({str}*): outputs its string arguments (in raw format) ending with a newline."},
-{"print1",0,(void*)print1,11,"vs*","print1({str}*): outputs its string arguments (in raw format) without ending with newline."},
-{"printf",0,(void*)printf0,11,"vss*","printf(fmt,{x}*): prints its arguments according to the format fmt."},
-{"printsep",0,(void*)printsep,11,"vss*","printsep(sep,{str}*): outputs its string arguments (in raw format), separated by 'sep', ending with a newline."},
-{"printsep1",0,(void*)printsep1,11,"vss*","printsep(sep,{str}*): outputs its string arguments (in raw format), separated by 'sep', without ending with a newline."},
-{"printtex",0,(void*)printtex,11,"vs*","printtex({str}*): outputs its string arguments in TeX format."},
-{"prod",0,(void*)produit,9,"V=GGEDG","prod(X=a,b,expr,{x=1}): x times the product (X runs from a to b) of expression."},
-{"prodeuler",0,(void*)prodeuler0,9,"V=GGEp","prodeuler(X=a,b,expr): Euler product (X runs over the primes between a and b) of real or complex expression."},
-{"prodinf",0,(void*)prodinf0,9,"V=GED0,L,p","prodinf(X=a,expr,{flag=0}): infinite product (X goes from a to infinity) of real or complex expression. flag can be 0 (default) or 1, in which case compute the product of the 1+expr instead."},
+{"print",0,(void*)print,13,"vs*","print({str}*): outputs its string arguments (in raw format) ending with a newline."},
+{"print1",0,(void*)print1,13,"vs*","print1({str}*): outputs its string arguments (in raw format) without ending with newline."},
+{"printf",0,(void*)printf0,13,"vss*","printf(fmt,{x}*): prints its arguments according to the format fmt."},
+{"printsep",0,(void*)printsep,13,"vss*","printsep(sep,{str}*): outputs its string arguments (in raw format), separated by 'sep', ending with a newline."},
+{"printsep1",0,(void*)printsep1,13,"vss*","printsep(sep,{str}*): outputs its string arguments (in raw format), separated by 'sep', without ending with a newline."},
+{"printtex",0,(void*)printtex,13,"vs*","printtex({str}*): outputs its string arguments in TeX format."},
+{"prod",0,(void*)produit,11,"V=GGEDG","prod(X=a,b,expr,{x=1}): x times the product (X runs from a to b) of expression."},
+{"prodeuler",0,(void*)prodeuler0,11,"V=GGEp","prodeuler(X=a,b,expr): Euler product (X runs over the primes between a and b) of real or complex expression."},
+{"prodinf",0,(void*)prodinf0,11,"V=GED0,L,p","prodinf(X=a,expr,{flag=0}): infinite product (X goes from a to infinity) of real or complex expression. flag can be 0 (default) or 1, in which case compute the product of the 1+expr instead."},
 {"psi",0,(void*)gpsi,3,"Gp","psi(x): psi-function at x."},
-{"qfauto",0,(void*)qfauto0,8,"GDG","qfauto(G,{fl}): automorphism group of the positive definite quadratic form G."},
-{"qfautoexport",0,(void*)qfautoexport,8,"GD0,L,","qfautoexport(qfa,{flag}): qfa being an automorphism group as output by qfauto, output a string representing the underlying matrix group in GAP notation (default) or Magma notation (flag = 1)."},
+{"qfauto",0,(void*)qfauto0,10,"GDG","qfauto(G,{fl}): automorphism group of the positive definite quadratic form G."},
+{"qfautoexport",0,(void*)qfautoexport,10,"GD0,L,","qfautoexport(qfa,{flag}): qfa being an automorphism group as output by qfauto, output a string representing the underlying matrix group in GAP notation (default) or Magma notation (flag = 1)."},
 {"qfbclassno",0,(void*)qfbclassno0,4,"GD0,L,","qfbclassno(D,{flag=0}): class number of discriminant D using Shanks's method by default. If (optional) flag is set to 1, use Euler products."},
 {"qfbcompraw",0,(void*)qfbcompraw,4,"GG","qfbcompraw(x,y): Gaussian composition without reduction of the binary quadratic forms x and y."},
 {"qfbhclassno",0,(void*)hclassno,4,"G","qfbhclassno(x): Hurwitz-Kronecker class number of x>0."},
-{"qfbil",0,(void*)qfbil,8,"GGDG","qfbil(x,y,{q}): evaluate the bilinear form q (symmetric matrix) at (x,y); if q omitted, use the standard Euclidean scalar product."},
+{"qfbil",0,(void*)qfbil,10,"GGDG","qfbil(x,y,{q}): evaluate the bilinear form q (symmetric matrix) at (x,y); if q omitted, use the standard Euclidean scalar product."},
 {"qfbnucomp",0,(void*)nucomp,4,"GGG","qfbnucomp(x,y,L): composite of primitive positive definite quadratic forms x and y using nucomp and nudupl, where L=[|D/4|^(1/4)] is precomputed."},
 {"qfbnupow",0,(void*)nupow,4,"GG","qfbnupow(x,n): n-th power of primitive positive definite quadratic form x using nucomp and nudupl."},
 {"qfbpowraw",0,(void*)qfbpowraw,4,"GL","qfbpowraw(x,n): n-th power without reduction of the binary quadratic form x."},
 {"qfbprimeform",0,(void*)primeform,4,"GGp","qfbprimeform(x,p): returns the prime form of discriminant x, whose first coefficient is p."},
 {"qfbred",0,(void*)qfbred0,4,"GD0,L,DGDGDG","qfbred(x,{flag=0},{d},{isd},{sd}): reduction of the binary quadratic form x. All other args. are optional. The arguments d, isd and sd, if present, supply the values of the discriminant, floor(sqrt(d)) and sqrt(d) respectively. If d<0, its value is not used and all references to Shanks's distance hereafter are meaningless. flag can be any of 0: default, uses Shanks's distance function d; 1: use d, do a single reduction step; 2: do not use d; 3 [...]
+{"qfbredsl2",0,(void*)qfbredsl2,4,"GDG","qfbredsl2(x,{data}): reduction of the binary quadratic form x, return [y,g] where y is reduced and g in Sl(2,Z) is such that g.x = y; data, if present, must be equal to [D, sqrtint(D)], where D > 0 is the discriminant of x."},
 {"qfbsolve",0,(void*)qfbsolve,4,"GG","qfbsolve(Q,p): Return [x,y] so that Q(x,y)=p where Q is a binary quadratic form and p a prime number, or 0 if there is no solution."},
-{"qfgaussred",0,(void*)qfgaussred,8,"G","qfgaussred(q): square reduction of the (symmetric) matrix q (returns a square matrix whose i-th diagonal term is the coefficient of the i-th square in which the coefficient of the i-th variable is 1)."},
-{"qfisom",0,(void*)qfisom0,8,"GGDG","qfisom(G,H,{fl}): find an isomorphism between the integral positive definite quadratic forms G and H if it exists. G can also be given by a qfisominit structure which is preferable if several forms need to be compared to G."},
-{"qfisominit",0,(void*)qfisominit0,8,"GDG","qfisominit(G,{fl}): G being a square and symmetric matrix representing an integral positive definite quadratic form, this function return a structure allowing to compute isomorphisms between G and other quadratic form faster."},
-{"qfjacobi",0,(void*)jacobi,8,"Gp","qfjacobi(A): eigenvalues and orthogonal matrix of eigenvectors of the real symmetric matrix A."},
-{"qflll",0,(void*)qflll0,8,"GD0,L,","qflll(x,{flag=0}): LLL reduction of the vectors forming the matrix x (gives the unimodular transformation matrix T such that x*T is LLL-reduced). flag is optional, and can be 0: default, 1: assumes x is integral, 2: assumes x is integral, returns a partially reduced basis, 4: assumes x is integral, returns [K,T] where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 but x may have polynomial coefficients, 8: same as 0 but x may h [...]
-{"qflllgram",0,(void*)qflllgram0,8,"GD0,L,","qflllgram(G,{flag=0}): LLL reduction of the lattice whose gram matrix is G (gives the unimodular transformation matrix). flag is optional and can be 0: default,1: assumes x is integral, 4: assumes x is integral, returns [K,T],  where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 but x may have polynomial coefficients, 8: same as 0 but x may have polynomial coefficients."},
-{"qfminim",0,(void*)qfminim0,8,"GDGDGD0,L,p","qfminim(x,{b},{m},{flag=0}): x being a square and symmetric matrix representing a positive definite quadratic form, this function deals with the vectors of x whose norm is less than or equal to b, enumerated using the Fincke-Pohst algorithm, storing at most m vectors (no limit if m is omitted). The function searches for the minimal non-zero vectors if b is omitted. The precise behavior depends on flag. 0: seeks at most 2m vectors (unless m om [...]
-{"qfnorm",0,(void*)qfnorm,8,"GDG","qfnorm(x,{q}): evaluate the binary quadratic form q (symmetric matrix) at x; if q omitted, use the standard Euclidean form."},
-{"qfperfection",0,(void*)perf,8,"G","qfperfection(G): rank of matrix of xx~ for x minimal vectors of a gram matrix G."},
-{"qfrep",0,(void*)qfrep0,8,"GGD0,L,","qfrep(q,B,{flag=0}): vector of (half) the number of vectors of norms from 1 to B for the integral and definite quadratic form q. If flag is 1, count vectors of even norm from 1 to 2B."},
-{"qfsign",0,(void*)qfsign,8,"G","qfsign(x): signature of the symmetric matrix x."},
+{"qfgaussred",0,(void*)qfgaussred,10,"G","qfgaussred(q): square reduction of the (symmetric) matrix q (returns a square matrix whose i-th diagonal term is the coefficient of the i-th square in which the coefficient of the i-th variable is 1)."},
+{"qfisom",0,(void*)qfisom0,10,"GGDG","qfisom(G,H,{fl}): find an isomorphism between the integral positive definite quadratic forms G and H if it exists. G can also be given by a qfisominit structure which is preferable if several forms need to be compared to G."},
+{"qfisominit",0,(void*)qfisominit0,10,"GDG","qfisominit(G,{fl}): G being a square and symmetric matrix representing an integral positive definite quadratic form, this function return a structure allowing to compute isomorphisms between G and other quadratic form faster."},
+{"qfjacobi",0,(void*)jacobi,10,"Gp","qfjacobi(A): eigenvalues and orthogonal matrix of eigenvectors of the real symmetric matrix A."},
+{"qflll",0,(void*)qflll0,10,"GD0,L,","qflll(x,{flag=0}): LLL reduction of the vectors forming the matrix x (gives the unimodular transformation matrix T such that x*T is LLL-reduced). flag is optional, and can be 0: default, 1: assumes x is integral, 2: assumes x is integral, returns a partially reduced basis, 4: assumes x is integral, returns [K,T] where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 but x may have polynomial coefficients, 8: same as 0 but x may  [...]
+{"qflllgram",0,(void*)qflllgram0,10,"GD0,L,","qflllgram(G,{flag=0}): LLL reduction of the lattice whose gram matrix is G (gives the unimodular transformation matrix). flag is optional and can be 0: default,1: assumes x is integral, 4: assumes x is integral, returns [K,T],  where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 but x may have polynomial coefficients, 8: same as 0 but x may have polynomial coefficients."},
+{"qfminim",0,(void*)qfminim0,10,"GDGDGD0,L,p","qfminim(x,{b},{m},{flag=0}): x being a square and symmetric matrix representing a positive definite quadratic form, this function deals with the vectors of x whose norm is less than or equal to b, enumerated using the Fincke-Pohst algorithm, storing at most m vectors (no limit if m is omitted). The function searches for the minimal non-zero vectors if b is omitted. The precise behavior depends on flag. 0: seeks at most 2m vectors (unless m o [...]
+{"qfnorm",0,(void*)qfnorm,10,"GDG","qfnorm(x,{q}): evaluate the binary quadratic form q (symmetric matrix) at x; if q omitted, use the standard Euclidean form."},
+{"qfparam",0,(void*)qfparam,10,"GGD0,L,","qfparam(G, sol, {flag = 0}): coefficients of binary quadratic forms that parametrize the solutions of the ternary quadratic form G, using the particular solution sol."},
+{"qfperfection",0,(void*)perf,10,"G","qfperfection(G): rank of matrix of xx~ for x minimal vectors of a gram matrix G."},
+{"qfrep",0,(void*)qfrep0,10,"GGD0,L,","qfrep(q,B,{flag=0}): vector of (half) the number of vectors of norms from 1 to B for the integral and definite quadratic form q. If flag is 1, count vectors of even norm from 1 to 2B."},
+{"qfsign",0,(void*)qfsign,10,"G","qfsign(x): signature of the symmetric matrix x."},
+{"qfsolve",0,(void*)qfsolve,10,"G","qfsolve(G): solve over Q the quadratic equation X^t G X = 0, where G is a symmetric matrix."},
 {"quadclassunit",0,(void*)quadclassunit0,4,"GD0,L,DGp","quadclassunit(D,{flag=0},{tech=[]}): compute the structure of the class group and the regulator of the quadratic field of discriminant D. See manual for the optional technical parameters."},
 {"quaddisc",0,(void*)quaddisc,4,"G","quaddisc(x): discriminant of the quadratic field Q(sqrt(x))."},
 {"quadgen",0,(void*)quadgen,4,"G","quadgen(D): standard generator of quadratic order of discriminant D."},
@@ -608,61 +721,64 @@ entree functions_basic[]={
 {"quadunit",0,(void*)quadunit,4,"G","quadunit(D): fundamental unit of the quadratic field of discriminant D where D must be positive."},
 {"random",0,(void*)genrand,2,"DG","random({N=2^31}): random object, depending on the type of N. Integer between 0 and N-1 (t_INT), int mod N (t_INTMOD), element in a finite field (t_FFELT), point on an elliptic curve (ellinit mod p or over a finite field)."},
 {"randomprime",0,(void*)randomprime,4,"DG","randomprime({N = 2^31}): returns a strong pseudo prime in [2, N-1]."},
-{"readvec",0,(void*)gp_readvec_file,11,"D\"\",s,","readvec({filename}): create a vector whose components are the evaluation of all the expressions found in the input file filename."},
+{"read",0,(void*)gp_read_file,13,"D\"\",s,","read({filename}): read from the input file filename. If filename is omitted, reread last input file, be it from read() or \\r."},
+{"readstr",0,(void*)readstr,13,"D\"\",s,","readstr({filename}): returns the vector of GP strings containing the lines in filename."},
+{"readvec",0,(void*)gp_readvec_file,13,"D\"\",s,","readvec({filename}): create a vector whose components are the evaluation of all the expressions found in the input file filename."},
 {"real",0,(void*)greal,2,"G","real(x): real part of x."},
 {"removeprimes",0,(void*)removeprimes,4,"DG","removeprimes({x=[]}): remove primes in the vector x from the prime table. x can also be a single integer. List the current extra primes if x is omitted."},
-{"return",0,(void*)return0,11,"DG","return({x=0}): return from current subroutine with result x."},
-{"rnfalgtobasis",0,(void*)rnfalgtobasis,6,"GG","rnfalgtobasis(rnf,x): relative version of nfalgtobasis, where rnf is a relative numberfield."},
-{"rnfbasis",0,(void*)rnfbasis,6,"GG","rnfbasis(bnf,M): given a projective Z_K-module M as output by rnfpseudobasis or rnfsteinitz, gives either a basis of M if it is free, or an n+1-element generating set."},
-{"rnfbasistoalg",0,(void*)rnfbasistoalg,6,"GG","rnfbasistoalg(rnf,x): relative version of nfbasistoalg, where rnf is a relative numberfield."},
-{"rnfcharpoly",0,(void*)rnfcharpoly,6,"GGGDn","rnfcharpoly(nf,T,a,{var='x}): characteristic polynomial of a over nf, where a belongs to the algebra defined by T over nf. Returns a polynomial in variable var (x by default)."},
-{"rnfconductor",0,(void*)rnfconductor,6,"GG","rnfconductor(bnf,pol): conductor of the Abelian extension of bnf defined by pol. The result is [conductor,rayclassgroup,subgroup], where conductor is the conductor itself, rayclassgroup the structure of the corresponding full ray class group, and subgroup the HNF defining the norm group (Artin or Takagi group) on the given generators rayclassgroup[3]."},
-{"rnfdedekind",0,(void*)rnfdedekind,6,"GGDGD0,L,","rnfdedekind(nf,pol,{pr},{flag=0}): relative Dedekind criterion over the number field K, represented by nf, applied to the order O_K[X]/(P), modulo the prime ideal pr (at all primes if pr omitted, in which case flag is automatically set to 1). P is assumed to be monic, irreducible, in O_K[X]. Returns [max,basis,v], where basis is a pseudo-basis of the enlarged order, max is 1 iff this order is pr-maximal, and v is the valuation at pr of t [...]
-{"rnfdet",0,(void*)rnfdet,6,"GG","rnfdet(nf,M): given a pseudo-matrix M, compute its determinant."},
-{"rnfdisc",0,(void*)rnfdiscf,6,"GG","rnfdisc(nf,pol): given a pol with coefficients in nf, gives a 2-component vector [D,d], where D is the relative ideal discriminant, and d is the relative discriminant in nf^*/nf*^2."},
-{"rnfeltabstorel",0,(void*)rnfeltabstorel,6,"GG","rnfeltabstorel(rnf,x): transforms the element x from absolute to relative representation."},
-{"rnfeltdown",0,(void*)rnfeltdown,6,"GG","rnfeltdown(rnf,x): expresses x on the base field if possible; returns an error otherwise."},
-{"rnfeltnorm",0,(void*)rnfeltnorm,6,"GG","rnfeltnorm(rnf,x): returns the relative norm N_{L/K}(x), as an element of K"},
-{"rnfeltreltoabs",0,(void*)rnfeltreltoabs,6,"GG","rnfeltreltoabs(rnf,x): transforms the element x from relative to absolute representation."},
-{"rnfelttrace",0,(void*)rnfelttrace,6,"GG","rnfelttrace(rnf,x): returns the relative trace N_{L/K}(x), as an element of K"},
-{"rnfeltup",0,(void*)rnfeltup,6,"GG","rnfeltup(rnf,x): expresses x (belonging to the base field) on the relative field."},
-{"rnfequation",0,(void*)rnfequation0,6,"GGD0,L,","rnfequation(nf,pol,{flag=0}): given a pol with coefficients in nf, gives an absolute equation z of the number field defined by pol. flag is optional, and can be 0: default, or non-zero, gives [z,al,k], where z defines the absolute equation L/Q as in the default behavior, al expresses as an element of L a root of the polynomial defining the base field nf, and k is a small integer such that t = b + k al is a root of z, for b a root of pol."},
-{"rnfhnfbasis",0,(void*)rnfhnfbasis,6,"GG","rnfhnfbasis(bnf,x): given an order x as output by rnfpseudobasis, gives either a true HNF basis of the order if it exists, zero otherwise."},
-{"rnfidealabstorel",0,(void*)rnfidealabstorel,6,"GG","rnfidealabstorel(rnf,x): transforms the ideal x from absolute to relative representation."},
-{"rnfidealdown",0,(void*)rnfidealdown,6,"GG","rnfidealdown(rnf,x): finds the intersection of the ideal x with the base field."},
-{"rnfidealhnf",0,(void*)rnfidealhnf,6,"GG","rnfidealhnf(rnf,x): relative version of idealhnf, where rnf is a relative numberfield."},
-{"rnfidealmul",0,(void*)rnfidealmul,6,"GGG","rnfidealmul(rnf,x,y): relative version of idealmul, where rnf is a relative numberfield."},
-{"rnfidealnormabs",0,(void*)rnfidealnormabs,6,"GG","rnfidealnormabs(rnf,x): absolute norm of the ideal x."},
-{"rnfidealnormrel",0,(void*)rnfidealnormrel,6,"GG","rnfidealnormrel(rnf,x): relative norm of the ideal x."},
-{"rnfidealreltoabs",0,(void*)rnfidealreltoabs,6,"GG","rnfidealreltoabs(rnf,x): transforms the ideal x from relative to absolute representation."},
-{"rnfidealtwoelt",0,(void*)rnfidealtwoelement,6,"GG","rnfidealtwoelt(rnf,x): relative version of idealtwoelt, where rnf is a relative numberfield."},
-{"rnfidealup",0,(void*)rnfidealup,6,"GG","rnfidealup(rnf,x): lifts the ideal x (of the base field) to the relative field."},
-{"rnfinit",0,(void*)rnfinit,6,"GG","rnfinit(nf,pol): pol being an irreducible polynomial defined over the number field nf, initializes a vector of data necessary for working in relative number fields (rnf functions). See manual for technical details."},
-{"rnfisabelian",0,(void*)rnfisabelian,6,"lGG","rnfisabelian(nf,T): T being a relative polynomial with coefficients in nf, return 1 if it defines an abelian extension, and 0 otherwise."},
-{"rnfisfree",0,(void*)rnfisfree,6,"lGG","rnfisfree(bnf,x): given an order x as output by rnfpseudobasis or rnfsteinitz, outputs true (1) or false (0) according to whether the order is free or not."},
-{"rnfisnorm",0,(void*)rnfisnorm,6,"GGD0,L,","rnfisnorm(T,a,{flag=0}): T is as output by rnfisnorminit applied to L/K. Tries to tell whether a is a norm from L/K. Returns a vector [x,q] where a=Norm(x)*q. Looks for a solution which is a S-integer, with S a list of places in K containing the ramified primes, generators of the class group of ext, as well as those primes dividing a. If L/K is Galois, omit flag, otherwise it is used to add more places to S: all the places above the primes p < [...]
-{"rnfisnorminit",0,(void*)rnfisnorminit,6,"GGD2,L,","rnfisnorminit(pol,polrel,{flag=2}): let K be defined by a root of pol, L/K the extension defined by polrel. Compute technical data needed by rnfisnorm to solve norm equations Nx = a, for x in L, and a in K. If flag=0, do not care whether L/K is Galois or not; if flag = 1, assume L/K is Galois; if flag = 2, determine whether L/K is Galois."},
-{"rnfkummer",0,(void*)rnfkummer,6,"GDGD0,L,p","rnfkummer(bnr,{subgp},{d=0}): bnr being as output by bnrinit, finds a relative equation for the class field corresponding to the module in bnr and the given congruence subgroup (the ray class field if subgp is omitted). d can be zero (default), or positive, and in this case the output is the list of all relative equations of degree d for the given bnr, with the same conductor as (bnr, subgp)."},
-{"rnflllgram",0,(void*)rnflllgram,6,"GGGp","rnflllgram(nf,pol,order): given a pol with coefficients in nf and an order as output by rnfpseudobasis or similar, gives [[neworder],U], where neworder is a reduced order and U is the unimodular transformation matrix."},
-{"rnfnormgroup",0,(void*)rnfnormgroup,6,"GG","rnfnormgroup(bnr,pol): norm group (or Artin or Takagi group) corresponding to the Abelian extension of bnr.bnf defined by pol, where the module corresponding to bnr is assumed to be a multiple of the conductor. The result is the HNF defining the norm group on the generators in bnr.gen."},
-{"rnfpolred",0,(void*)rnfpolred,6,"GGp","rnfpolred(nf,pol): given a pol with coefficients in nf, finds a list of relative polynomials defining some subfields, hopefully simpler."},
-{"rnfpolredabs",0,(void*)rnfpolredabs,6,"GGD0,L,","rnfpolredabs(nf,pol,{flag=0}): given a pol with coefficients in nf, finds a relative simpler polynomial defining the same field. Binary digits of flag mean: 1: return also the element whose characteristic polynomial is the given polynomial, 2: return an absolute polynomial, 16: partial reduction."},
-{"rnfpolredbest",0,(void*)rnfpolredbest,6,"GGD0,L,","rnfpolredbest(nf,pol,{flag=0}): given a pol with coefficients in nf, finds a relative polynomial P defining the same field, hopefully simpler than pol; flag can be 0: default, 1: return [P,a], where a is a root of pol 2: return an absolute polynomial Pabs, 3: return [Pabs, a,b], where a is a root of nf.pol and b is a root of pol."},
-{"rnfpseudobasis",0,(void*)rnfpseudobasis,6,"GG","rnfpseudobasis(nf,pol): given a pol with coefficients in nf, gives a 4-component vector [A,I,D,d] where [A,I] is a pseudo basis of the maximal order in HNF on the power basis, D is the relative ideal discriminant, and d is the relative discriminant in nf^*/nf*^2."},
-{"rnfsteinitz",0,(void*)rnfsteinitz,6,"GG","rnfsteinitz(nf,x): given an order x as output by rnfpseudobasis, gives [A,I,D,d] where (A,I) is a pseudo basis where all the ideals except perhaps the last are trivial."},
+{"return",0,(void*)return0,13,"DG","return({x=0}): return from current subroutine with result x."},
+{"rnfalgtobasis",0,(void*)rnfalgtobasis,7,"GG","rnfalgtobasis(rnf,x): relative version of nfalgtobasis, where rnf is a relative numberfield."},
+{"rnfbasis",0,(void*)rnfbasis,7,"GG","rnfbasis(bnf,M): given a projective Z_K-module M as output by rnfpseudobasis or rnfsteinitz, gives either a basis of M if it is free, or an n+1-element generating set."},
+{"rnfbasistoalg",0,(void*)rnfbasistoalg,7,"GG","rnfbasistoalg(rnf,x): relative version of nfbasistoalg, where rnf is a relative numberfield."},
+{"rnfcharpoly",0,(void*)rnfcharpoly,7,"GGGDn","rnfcharpoly(nf,T,a,{var='x}): characteristic polynomial of a over nf, where a belongs to the algebra defined by T over nf. Returns a polynomial in variable var (x by default)."},
+{"rnfconductor",0,(void*)rnfconductor,7,"GG","rnfconductor(bnf,pol): conductor of the Abelian extension of bnf defined by pol. The result is [conductor,rayclassgroup,subgroup], where conductor is the conductor itself, rayclassgroup the structure of the corresponding full ray class group, and subgroup the HNF defining the norm group (Artin or Takagi group) on the given generators rayclassgroup[3]."},
+{"rnfdedekind",0,(void*)rnfdedekind,7,"GGDGD0,L,","rnfdedekind(nf,pol,{pr},{flag=0}): relative Dedekind criterion over the number field K, represented by nf, applied to the order O_K[X]/(P), modulo the prime ideal pr (at all primes if pr omitted, in which case flag is automatically set to 1). P is assumed to be monic, irreducible, in O_K[X]. Returns [max,basis,v], where basis is a pseudo-basis of the enlarged order, max is 1 iff this order is pr-maximal, and v is the valuation at pr of t [...]
+{"rnfdet",0,(void*)rnfdet,7,"GG","rnfdet(nf,M): given a pseudo-matrix M, compute its determinant."},
+{"rnfdisc",0,(void*)rnfdiscf,7,"GG","rnfdisc(nf,pol): given a pol with coefficients in nf, gives a 2-component vector [D,d], where D is the relative ideal discriminant, and d is the relative discriminant in nf^*/nf*^2."},
+{"rnfeltabstorel",0,(void*)rnfeltabstorel,7,"GG","rnfeltabstorel(rnf,x): transforms the element x from absolute to relative representation."},
+{"rnfeltdown",0,(void*)rnfeltdown,7,"GG","rnfeltdown(rnf,x): expresses x on the base field if possible; returns an error otherwise."},
+{"rnfeltnorm",0,(void*)rnfeltnorm,7,"GG","rnfeltnorm(rnf,x): returns the relative norm N_{L/K}(x), as an element of K"},
+{"rnfeltreltoabs",0,(void*)rnfeltreltoabs,7,"GG","rnfeltreltoabs(rnf,x): transforms the element x from relative to absolute representation."},
+{"rnfelttrace",0,(void*)rnfelttrace,7,"GG","rnfelttrace(rnf,x): returns the relative trace N_{L/K}(x), as an element of K"},
+{"rnfeltup",0,(void*)rnfeltup,7,"GG","rnfeltup(rnf,x): expresses x (belonging to the base field) on the relative field."},
+{"rnfequation",0,(void*)rnfequation0,7,"GGD0,L,","rnfequation(nf,pol,{flag=0}): given a pol with coefficients in nf, gives an absolute equation z of the number field defined by pol. flag is optional, and can be 0: default, or non-zero, gives [z,al,k], where z defines the absolute equation L/Q as in the default behavior, al expresses as an element of L a root of the polynomial defining the base field nf, and k is a small integer such that t = b + k al is a root of z, for b a root of pol."},
+{"rnfhnfbasis",0,(void*)rnfhnfbasis,7,"GG","rnfhnfbasis(bnf,x): given an order x as output by rnfpseudobasis, gives either a true HNF basis of the order if it exists, zero otherwise."},
+{"rnfidealabstorel",0,(void*)rnfidealabstorel,7,"GG","rnfidealabstorel(rnf,x): transforms the ideal x from absolute to relative representation."},
+{"rnfidealdown",0,(void*)rnfidealdown,7,"GG","rnfidealdown(rnf,x): finds the intersection of the ideal x with the base field."},
+{"rnfidealhnf",0,(void*)rnfidealhnf,7,"GG","rnfidealhnf(rnf,x): relative version of idealhnf, where rnf is a relative numberfield."},
+{"rnfidealmul",0,(void*)rnfidealmul,7,"GGG","rnfidealmul(rnf,x,y): relative version of idealmul, where rnf is a relative numberfield."},
+{"rnfidealnormabs",0,(void*)rnfidealnormabs,7,"GG","rnfidealnormabs(rnf,x): absolute norm of the ideal x."},
+{"rnfidealnormrel",0,(void*)rnfidealnormrel,7,"GG","rnfidealnormrel(rnf,x): relative norm of the ideal x."},
+{"rnfidealreltoabs",0,(void*)rnfidealreltoabs,7,"GG","rnfidealreltoabs(rnf,x): transforms the ideal x from relative to absolute representation."},
+{"rnfidealtwoelt",0,(void*)rnfidealtwoelement,7,"GG","rnfidealtwoelt(rnf,x): relative version of idealtwoelt, where rnf is a relative numberfield."},
+{"rnfidealup",0,(void*)rnfidealup,7,"GG","rnfidealup(rnf,x): lifts the ideal x (of the base field) to the relative field."},
+{"rnfinit",0,(void*)rnfinit,7,"GG","rnfinit(nf,pol): pol being an irreducible polynomial defined over the number field nf, initializes a vector of data necessary for working in relative number fields (rnf functions). See manual for technical details."},
+{"rnfisabelian",0,(void*)rnfisabelian,7,"lGG","rnfisabelian(nf,T): T being a relative polynomial with coefficients in nf, return 1 if it defines an abelian extension, and 0 otherwise."},
+{"rnfisfree",0,(void*)rnfisfree,7,"lGG","rnfisfree(bnf,x): given an order x as output by rnfpseudobasis or rnfsteinitz, outputs true (1) or false (0) according to whether the order is free or not."},
+{"rnfisnorm",0,(void*)rnfisnorm,7,"GGD0,L,","rnfisnorm(T,a,{flag=0}): T is as output by rnfisnorminit applied to L/K. Tries to tell whether a is a norm from L/K. Returns a vector [x,q] where a=Norm(x)*q. Looks for a solution which is a S-integer, with S a list of places in K containing the ramified primes, generators of the class group of ext, as well as those primes dividing a. If L/K is Galois, omit flag, otherwise it is used to add more places to S: all the places above the primes p < [...]
+{"rnfisnorminit",0,(void*)rnfisnorminit,7,"GGD2,L,","rnfisnorminit(pol,polrel,{flag=2}): let K be defined by a root of pol, L/K the extension defined by polrel. Compute technical data needed by rnfisnorm to solve norm equations Nx = a, for x in L, and a in K. If flag=0, do not care whether L/K is Galois or not; if flag = 1, assume L/K is Galois; if flag = 2, determine whether L/K is Galois."},
+{"rnfkummer",0,(void*)rnfkummer,7,"GDGD0,L,p","rnfkummer(bnr,{subgp},{d=0}): bnr being as output by bnrinit, finds a relative equation for the class field corresponding to the module in bnr and the given congruence subgroup (the ray class field if subgp is omitted). d can be zero (default), or positive, and in this case the output is the list of all relative equations of degree d for the given bnr, with the same conductor as (bnr, subgp)."},
+{"rnflllgram",0,(void*)rnflllgram,7,"GGGp","rnflllgram(nf,pol,order): given a pol with coefficients in nf and an order as output by rnfpseudobasis or similar, gives [[neworder],U], where neworder is a reduced order and U is the unimodular transformation matrix."},
+{"rnfnormgroup",0,(void*)rnfnormgroup,7,"GG","rnfnormgroup(bnr,pol): norm group (or Artin or Takagi group) corresponding to the Abelian extension of bnr.bnf defined by pol, where the module corresponding to bnr is assumed to be a multiple of the conductor. The result is the HNF defining the norm group on the generators in bnr.gen."},
+{"rnfpolred",0,(void*)rnfpolred,7,"GGp","rnfpolred(nf,pol): given a pol with coefficients in nf, finds a list of relative polynomials defining some subfields, hopefully simpler."},
+{"rnfpolredabs",0,(void*)rnfpolredabs,7,"GGD0,L,","rnfpolredabs(nf,pol,{flag=0}): given a pol with coefficients in nf, finds a relative simpler polynomial defining the same field. Binary digits of flag mean: 1: return also the element whose characteristic polynomial is the given polynomial, 2: return an absolute polynomial, 16: partial reduction."},
+{"rnfpolredbest",0,(void*)rnfpolredbest,7,"GGD0,L,","rnfpolredbest(nf,pol,{flag=0}): given a pol with coefficients in nf, finds a relative polynomial P defining the same field, hopefully simpler than pol; flag can be 0: default, 1: return [P,a], where a is a root of pol 2: return an absolute polynomial Pabs, 3: return [Pabs, a,b], where a is a root of nf.pol and b is a root of pol."},
+{"rnfpseudobasis",0,(void*)rnfpseudobasis,7,"GG","rnfpseudobasis(nf,pol): given a pol with coefficients in nf, gives a 4-component vector [A,I,D,d] where [A,I] is a pseudo basis of the maximal order in HNF on the power basis, D is the relative ideal discriminant, and d is the relative discriminant in nf^*/nf*^2."},
+{"rnfsteinitz",0,(void*)rnfsteinitz,7,"GG","rnfsteinitz(nf,x): given an order x as output by rnfpseudobasis, gives [A,I,D,d] where (A,I) is a pseudo basis where all the ideals except perhaps the last are trivial."},
 {"round",0,(void*)round0,2,"GD&","round(x,{&e}): take the nearest integer to all the coefficients of x. If e is present, do not take into account loss of integer part precision, and set e = error estimate in bits."},
-{"select",0,(void*)select0,11,"GGD0,L,","select(f, A, {flag = 0}): selects elements of A according to the selection function f. If flag is 1, return the indices of those elements (indirect selection)"},
-{"seralgdep",0,(void*)seralgdep,8,"GLL","seralgdep(s,p,r): find a linear relation between powers (1,s, ..., s^p) of the series s, with polynomial coefficients of degree <= r."},
-{"serconvol",0,(void*)convol,7,"GG","serconvol(x,y): convolution (or Hadamard product) of two power series."},
-{"serlaplace",0,(void*)laplace,7,"G","serlaplace(x): replaces the power series sum of a_n*x^n/n! by sum of a_n*x^n. For the reverse operation, use serconvol(x,exp(X))."},
-{"serreverse",0,(void*)serreverse,7,"G","serreverse(s): reversion of the power series s."},
-{"setbinop",0,(void*)setbinop,8,"GGDG","setbinop(f,X,{Y}): the set {f(x,y), x in X, y in Y}. If Y is omitted, assume that X = Y and that f is symmetric."},
-{"setintersect",0,(void*)setintersect,8,"GG","setintersect(x,y): intersection of the sets x and y."},
-{"setisset",0,(void*)setisset,8,"lG","setisset(x): true(1) if x is a set (row vector with strictly increasing entries), false(0) if not."},
-{"setminus",0,(void*)setminus,8,"GG","setminus(x,y): set of elements of x not belonging to y."},
-{"setrand",0,(void*)setrand,11,"vG","setrand(n): reset the seed of the random number generator to n."},
-{"setsearch",0,(void*)setsearch,8,"lGGD0,L,","setsearch(S,x,{flag=0}): determines whether x belongs to the set (or sorted list) S. If flag is 0 or omitted, returns 0 if it does not, otherwise returns the index j such that x==S[j]. If flag is non-zero, return 0 if x belongs to S, otherwise the index j where it should be inserted."},
-{"setunion",0,(void*)setunion,8,"GG","setunion(x,y): union of the sets x and y."},
+{"select",0,(void*)select0,13,"GGD0,L,","select(f, A, {flag = 0}): selects elements of A according to the selection function f. If flag is 1, return the indices of those elements (indirect selection)"},
+{"self",0,(void*)pari_self,13,"m","self(): return the calling function or closure. Useful for defining anonymous recursive functions."},
+{"seralgdep",0,(void*)seralgdep,10,"GLL","seralgdep(s,p,r): find a linear relation between powers (1,s, ..., s^p) of the series s, with polynomial coefficients of degree <= r."},
+{"serconvol",0,(void*)convol,9,"GG","serconvol(x,y): convolution (or Hadamard product) of two power series."},
+{"serlaplace",0,(void*)laplace,9,"G","serlaplace(x): replaces the power series sum of a_n*x^n/n! by sum of a_n*x^n. For the reverse operation, use serconvol(x,exp(X))."},
+{"serreverse",0,(void*)serreverse,9,"G","serreverse(s): reversion of the power series s."},
+{"setbinop",0,(void*)setbinop,10,"GGDG","setbinop(f,X,{Y}): the set {f(x,y), x in X, y in Y}. If Y is omitted, assume that X = Y and that f is symmetric."},
+{"setintersect",0,(void*)setintersect,10,"GG","setintersect(x,y): intersection of the sets x and y."},
+{"setisset",0,(void*)setisset,10,"lG","setisset(x): true(1) if x is a set (row vector with strictly increasing entries), false(0) if not."},
+{"setminus",0,(void*)setminus,10,"GG","setminus(x,y): set of elements of x not belonging to y."},
+{"setrand",0,(void*)setrand,13,"vG","setrand(n): reset the seed of the random number generator to n."},
+{"setsearch",0,(void*)setsearch,10,"lGGD0,L,","setsearch(S,x,{flag=0}): determines whether x belongs to the set (or sorted list) S. If flag is 0 or omitted, returns 0 if it does not, otherwise returns the index j such that x==S[j]. If flag is non-zero, return 0 if x belongs to S, otherwise the index j where it should be inserted."},
+{"setunion",0,(void*)setunion,10,"GG","setunion(x,y): union of the sets x and y."},
 {"shift",0,(void*)gshift,1,"GL","shift(x,n): shift x left n bits if n>=0, right -n bits if n<0."},
 {"shiftmul",0,(void*)gmul2n,1,"GL","shiftmul(x,n): multiply x by 2^n (n>=0 or n<0)"},
 {"sigma",0,(void*)sumdivk,4,"GD1,L,","sigma(x,{k=1}): sum of the k-th powers of the divisors of x. k is optional and if omitted is assumed to be equal to 1."},
@@ -671,66 +787,70 @@ entree functions_basic[]={
 {"sin",0,(void*)gsin,3,"Gp","sin(x): sine of x."},
 {"sinh",0,(void*)gsinh,3,"Gp","sinh(x): hyperbolic sine of x."},
 {"sizebyte",0,(void*)gsizebyte,2,"lG","sizebyte(x): number of bytes occupied by the complete tree of the object x."},
-{"sizedigit",0,(void*)sizedigit,2,"lG","sizedigit(x): maximum number of decimal digits minus one of (the coefficients of) x."},
-{"solve",0,(void*)zbrent0,9,"V=GGEp","solve(X=a,b,expr): real root of expression expr (X between a and b), where expr(a)*expr(b)<=0."},
+{"sizedigit",0,(void*)sizedigit,2,"lG","sizedigit(x): rough upper bound for the number of decimal digits of (the components of) $x$. DEPRECATED."},
+{"solve",0,(void*)zbrent0,11,"V=GGEp","solve(X=a,b,expr): real root of expression expr (X between a and b), where expr(a)*expr(b)<=0."},
 {"sqr",0,(void*)gsqr,3,"G","sqr(x): square of x. NOT identical to x*x."},
 {"sqrt",0,(void*)gsqrt,3,"Gp","sqrt(x): square root of x."},
 {"sqrtint",0,(void*)sqrtint,4,"G","sqrtint(x): integer square root of x, where x is a non-negative integer."},
 {"sqrtn",0,(void*)gsqrtn,3,"GGD&p","sqrtn(x,n,{&z}): nth-root of x, n must be integer. If present, z is set to a suitable root of unity to recover all solutions. If it was not possible, z is set to zero."},
 {"sqrtnint",0,(void*)sqrtnint,4,"GL","sqrtnint(x,n): integer n-th root of x, where x is non-negative integer."},
 {"stirling",0,(void*)stirling,4,"LLD1,L,","stirling(n,k,{flag=1}): If flag=1 (default) return the Stirling number of the first kind s(n,k), if flag=2, return the Stirling number of the second kind S(n,k)."},
-{"subgrouplist",0,(void*)subgrouplist0,6,"GDGD0,L,","subgrouplist(bnr,{bound},{flag=0}): bnr being as output by bnrinit or a list of cyclic components of a finite Abelian group G, outputs the list of subgroups of G (of index bounded by bound, if not omitted), given as HNF left divisors of the SNF matrix corresponding to G. If flag=0 (default) and bnr is as output by bnrinit, gives only the subgroups for which the modulus is the conductor."},
-{"subst",0,(void*)gsubst,7,"GnG","subst(x,y,z): in expression x, replace the variable y by the expression z."},
-{"substpol",0,(void*)gsubstpol,7,"GGG","substpol(x,y,z): in expression x, replace the polynomial y by the expression z, using remainder decomposition of x."},
-{"substvec",0,(void*)gsubstvec,7,"GGG","substvec(x,v,w): in expression x, make a best effort to replace the variables v1,...,vn by the expression w1,...,wn."},
-{"sum",0,(void*)somme,9,"V=GGEDG","sum(X=a,b,expr,{x=0}): x plus the sum (X goes from a to b) of expression expr."},
-{"sumalt",0,(void*)sumalt0,9,"V=GED0,L,p","sumalt(X=a,expr,{flag=0}): Cohen-Villegas-Zagier's acceleration of alternating series expr, X starting at a. flag is optional, and can be 0: default, or 1: uses a slightly different method using Zagier's polynomials."},
+{"subgrouplist",0,(void*)subgrouplist0,7,"GDGD0,L,","subgrouplist(bnr,{bound},{flag=0}): bnr being as output by bnrinit or a list of cyclic components of a finite Abelian group G, outputs the list of subgroups of G (of index bounded by bound, if not omitted), given as HNF left divisors of the SNF matrix corresponding to G. If flag=0 (default) and bnr is as output by bnrinit, gives only the subgroups for which the modulus is the conductor."},
+{"subst",0,(void*)gsubst,9,"GnG","subst(x,y,z): in expression x, replace the variable y by the expression z."},
+{"substpol",0,(void*)gsubstpol,9,"GGG","substpol(x,y,z): in expression x, replace the polynomial y by the expression z, using remainder decomposition of x."},
+{"substvec",0,(void*)gsubstvec,9,"GGG","substvec(x,v,w): in expression x, make a best effort to replace the variables v1,...,vn by the expression w1,...,wn."},
+{"sum",0,(void*)somme,11,"V=GGEDG","sum(X=a,b,expr,{x=0}): x plus the sum (X goes from a to b) of expression expr."},
+{"sumalt",0,(void*)sumalt0,11,"V=GED0,L,p","sumalt(X=a,expr,{flag=0}): Cohen-Villegas-Zagier's acceleration of alternating series expr, X starting at a. flag is optional, and can be 0: default, or 1: uses a slightly different method using Zagier's polynomials."},
 {"sumdedekind",0,(void*)sumdedekind,4,"GG","sumdedekind(h,k): Dedekind sum associated to h,k"},
-{"sumdigits",0,(void*)sumdigits,4,"G","sumdigits(n): sum of (decimal) digits in the integer n."},
-{"sumdiv",0,(void*)sumdivexpr,9,"GVE","sumdiv(n,X,expr): sum of expression expr, X running over the divisors of n."},
-{"sumdivmult",0,(void*)sumdivmultexpr,9,"GVE","sumdivmult(n,d,expr): sum of multiplicative function expr, d running over the divisors of n."},
-{"sumformal",0,(void*)sumformal,7,"GDn","sumformal(f,{v}): formal sum of f with respect to v, or to the main variable of f if v is omitted."},
-{"suminf",0,(void*)suminf0,9,"V=GEp","suminf(X=a,expr): infinite sum (X goes from a to infinity) of real or complex expression expr."},
-{"sumnum",0,(void*)sumnum0,9,"V=GGEDGD0,L,p","sumnum(X=a,sig,expr,{tab},{flag=0}): numerical summation of expr from X = ceiling(a) to +infinity. sig is either a scalar or a two-component vector coding the function's decrease rate at infinity. It is assumed that the scalar part of sig is to the right of all poles of expr. If present, tab must be initialized by sumnuminit. If flag is nonzero, assumes that conj(expr(z)) = expr(conj(z))."},
-{"sumnumalt",0,(void*)sumnumalt0,9,"V=GGEDGD0,L,p","sumnumalt(X=a,sig,expr,{tab},{flag=0}): numerical summation of (-1)^X expr(X) from X = ceiling(a) to +infinity. Note that the (-1)^X must not be included. sig is either a scalar or a two-component vector coded as in intnum, and the scalar part is larger than all the real parts of the poles of expr. Uses intnum, hence tab is as in intnum. If flag is nonzero, assumes that the function to be summed satisfies conj(f(z))=f(conj(z)), and then [...]
-{"sumnuminit",0,(void*)sumnuminit,9,"GD0,L,D1,L,p","sumnuminit(sig, {m=0}, {sgn=1}): initialize tables for numerical summation. sgn is 1 (in fact >= 0), the default, for sumnum (ordinary sums) or -1 (in fact < 0) for sumnumalt (alternating sums). sig is as in sumnum and m is as in intnuminit."},
-{"sumpos",0,(void*)sumpos0,9,"V=GED0,L,p","sumpos(X=a,expr,{flag=0}): sum of positive (or negative) series expr, the formal variable X starting at a. flag is optional, and can be 0: default, or 1: uses a slightly different method using Zagier's polynomials."},
+{"sumdigits",0,(void*)sumdigits0,4,"GDG","sumdigits(n,{B=10}): sum of digits in the integer n, when written in base B."},
+{"sumdiv",0,(void*)sumdivexpr,11,"GVE","sumdiv(n,X,expr): sum of expression expr, X running over the divisors of n."},
+{"sumdivmult",0,(void*)sumdivmultexpr,11,"GVE","sumdivmult(n,d,expr): sum of multiplicative function expr, d running over the divisors of n."},
+{"sumformal",0,(void*)sumformal,9,"GDn","sumformal(f,{v}): formal sum of f with respect to v, or to the main variable of f if v is omitted."},
+{"suminf",0,(void*)suminf0,11,"V=GEp","suminf(X=a,expr): infinite sum (X goes from a to infinity) of real or complex expression expr."},
+{"sumnum",0,(void*)sumnum0,11,"V=GGEDGD0,L,p","sumnum(X=a,sig,expr,{tab},{flag=0}): numerical summation of expr from X = ceiling(a) to +infinity. sig is either a scalar or a two-component vector coding the function's decrease rate at infinity. It is assumed that the scalar part of sig is to the right of all poles of expr. If present, tab must be initialized by sumnuminit. If flag is nonzero, assumes that conj(expr(z)) = expr(conj(z))."},
+{"sumnumalt",0,(void*)sumnumalt0,11,"V=GGEDGD0,L,p","sumnumalt(X=a,sig,expr,{tab},{flag=0}): numerical summation of (-1)^X expr(X) from X = ceiling(a) to +infinity. Note that the (-1)^X must not be included. sig is either a scalar or a two-component vector coded as in intnum, and the scalar part is larger than all the real parts of the poles of expr. Uses intnum, hence tab is as in intnum. If flag is nonzero, assumes that the function to be summed satisfies conj(f(z))=f(conj(z)), and the [...]
+{"sumnuminit",0,(void*)sumnuminit,11,"GD0,L,D1,L,p","sumnuminit(sig, {m=0}, {sgn=1}): initialize tables for numerical summation. sgn is 1 (in fact >= 0), the default, for sumnum (ordinary sums) or -1 (in fact < 0) for sumnumalt (alternating sums). sig is as in sumnum and m is as in intnuminit."},
+{"sumpos",0,(void*)sumpos0,11,"V=GED0,L,p","sumpos(X=a,expr,{flag=0}): sum of positive (or negative) series expr, the formal variable X starting at a. flag is optional, and can be 0: default, or 1: uses a slightly different method using Zagier's polynomials."},
+{"system",0,(void*)gpsystem,13,"vs","system(str): str being a string, execute the system command str."},
 {"tan",0,(void*)gtan,3,"Gp","tan(x): tangent of x."},
 {"tanh",0,(void*)gtanh,3,"Gp","tanh(x): hyperbolic tangent of x."},
-{"taylor",0,(void*)tayl,7,"GnDP","taylor(x,t,{d=seriesprecision}): taylor expansion of x with respect to t, adding O(t^d) to all components of x."},
+{"taylor",0,(void*)tayl,9,"GnDP","taylor(x,t,{d=seriesprecision}): taylor expansion of x with respect to t, adding O(t^d) to all components of x."},
 {"teichmuller",0,(void*)teich,3,"G","teichmuller(x): teichmuller character of p-adic number x."},
 {"theta",0,(void*)theta,3,"GGp","theta(q,z): Jacobi sine theta-function."},
 {"thetanullk",0,(void*)thetanullk,3,"GLp","thetanullk(q,k): k-th derivative at z=0 of theta(q,z)."},
-{"thue",0,(void*)thue,7,"GGDG","thue(tnf,a,{sol}): solve the equation P(x,y)=a, where tnf was created with thueinit(P), and sol, if present, contains the solutions of Norm(x)=a modulo units in the number field defined by P. If tnf was computed without assuming GRH (flag 1 in thueinit), the result is unconditional. If tnf is a polynomial, compute thue(thueinit(P,0), a)."},
-{"thueinit",0,(void*)thueinit,7,"GD0,L,p","thueinit(P,{flag=0}): initialize the tnf corresponding to P, that will be used to solve Thue equations P(x,y) = some-integer. If flag is non-zero, certify the result unconditionaly. Otherwise, assume GRH (much faster of course)."},
-{"trace",0,(void*)gtrace,8,"G","trace(x): trace of x."},
-{"trap",0,(void*)trap0,11,"DrDEDE","trap({e}, {rec}, seq): try to execute seq, trapping runtime error e (all of them if e omitted); sequence rec is executed if the error occurs and is the result of the command. THIS FUNCTION IS OBSOLETE: use \"IFERR\""},
+{"thue",0,(void*)thue,9,"GGDG","thue(tnf,a,{sol}): solve the equation P(x,y)=a, where tnf was created with thueinit(P), and sol, if present, contains the solutions of Norm(x)=a modulo units in the number field defined by P. If tnf was computed without assuming GRH (flag 1 in thueinit), the result is unconditional. If tnf is a polynomial, compute thue(thueinit(P,0), a)."},
+{"thueinit",0,(void*)thueinit,9,"GD0,L,p","thueinit(P,{flag=0}): initialize the tnf corresponding to P, that will be used to solve Thue equations P(x,y) = some-integer. If flag is non-zero, certify the result unconditionaly. Otherwise, assume GRH (much faster of course)."},
+{"trace",0,(void*)gtrace,10,"G","trace(x): trace of x."},
+{"trap",0,(void*)trap0,13,"DrDEDE","trap({e}, {rec}, seq): try to execute seq, trapping runtime error e (all of them if e omitted); sequence rec is executed if the error occurs and is the result of the command. THIS FUNCTION IS OBSOLETE: use \"IFERR\""},
 {"truncate",0,(void*)trunc0,2,"GD&","truncate(x,{&e}): truncation of x; when x is a power series,take away the O(X^). If e is present, do not take into account loss of integer part precision, and set e = error estimate in bits."},
-{"type",0,(void*)type0,11,"G","type(x): return the type of the GEN x."},
-{"uninline",0,NULL,11,NULL,"uninline(): forget all inline variables [EXPERIMENTAL]"},
-{"until",0,(void*)untilpari,11,"vEI","until(a,seq): evaluate the expression sequence seq until a is nonzero."},
-{"valuation",0,(void*)gvaluation,2,"lGG","valuation(x,p): valuation of x with respect to p."},
+{"type",0,(void*)type0,13,"G","type(x): return the type of the GEN x."},
+{"uninline",0,NULL,13,NULL,"uninline(): forget all inline variables [EXPERIMENTAL]"},
+{"until",0,(void*)untilpari,13,"vEI","until(a,seq): evaluate the expression sequence seq until a is nonzero."},
+{"valuation",0,(void*)gpvaluation,2,"GG","valuation(x,p): valuation of x with respect to p."},
+{"varhigher",0,(void*)varhigher,2,"sDn","varhigher(name,{v}): return a variable 'name' whose priority is higher than the priority of v (of all existing variables if v is omitted)."},
 {"variable",0,(void*)gpolvar,2,"DG","variable({x}): main variable of object x. Gives p for p-adic x, 0 if no variable can be associated to x. Returns the list of user variables if x is omitted."},
-{"vecextract",0,(void*)extract0,8,"GGDG","vecextract(x,y,{z}): extraction of the components of the matrix or vector x according to y and z. If z is omitted, y represents columns, otherwise y corresponds to rows and z to columns. y and z can be vectors (of indices), strings (indicating ranges as in \"1..10\") or masks (integers whose binary representation indicates the indices to extract, from left to right 1, 2, 4, 8, etc.)."},
+{"variables",0,(void*)variables_vec,2,"DG","variables({x}): all variables occuring in object x, sorted by decreasing priority. Returns the list of user variables if x is omitted."},
+{"varlower",0,(void*)varlower,2,"sDn","varlower(name,{v}): return a variable 'name' whose priority is lower than the priority of v (of all existing variables if v is omitted."},
+{"vecextract",0,(void*)extract0,10,"GGDG","vecextract(x,y,{z}): extraction of the components of the matrix or vector x according to y and z. If z is omitted, y represents columns, otherwise y corresponds to rows and z to columns. y and z can be vectors (of indices), strings (indicating ranges as in \"1..10\") or masks (integers whose binary representation indicates the indices to extract, from left to right 1, 2, 4, 8, etc.)."},
 {"vecmax",0,(void*)vecmax0,1,"GD&","vecmax(x,{&v}): largest entry in the vector/matrix x. If v is present, set it to the index of a largest entry (indirect max)."},
 {"vecmin",0,(void*)vecmin0,1,"GD&","vecmin(x,{&v}): smallest entry in the vector/matrix x. If v is present, set it to the index of a smallest entry (indirect min)."},
-{"vecsearch",0,(void*)vecsearch,8,"lGGDG","vecsearch(v,x,{cmpf}): determines whether x belongs to the sorted vector v. If the comparison function cmpf is explicitly given, assume that v was sorted according to vecsort(, cmpf)."},
-{"vecsort",0,(void*)vecsort0,8,"GDGD0,L,","vecsort(x,{cmpf},{flag=0}): sorts the vector of vectors (or matrix) x in ascending order, according to the comparison function cmpf, if not omitted. (If cmpf is an integer, sort according to the value of the k-th component of each entry.) Binary digits of flag (if present) mean: 1: indirect sorting, return the permutation instead of the permuted vector, 2: sort using lexicographic order, 4: use descending instead of ascending order, 8: remove du [...]
-{"vecsum",0,(void*)vecsum,8,"G","vecsum(v): return the sum of the component of the vector v"},
-{"vector",0,(void*)vecteur,8,"GDVDE","vector(n,{X},{expr=0}): row vector with n components of expression expr (X ranges from 1 to n). By default, fill with 0s."},
-{"vectorsmall",0,(void*)vecteursmall,8,"GDVDE","vectorsmall(n,{X},{expr=0}): VECSMALL with n components of expression expr (X ranges from 1 to n) which must be small integers. By default, fill with 0s."},
-{"vectorv",0,(void*)vvecteur,8,"GDVDE","vectorv(n,{X},{expr=0}): column vector with n components of expression expr (X ranges from 1 to n). By default, fill with 0s."},
-{"version",0,(void*)pari_version,11,"","version(): returns the PARI version as [major,minor,patch] or [major,minor,patch,VCSversion]."},
-{"warning",0,(void*)warning0,11,"vs*","warning({str}*): display warning message str"},
+{"vecsearch",0,(void*)vecsearch,10,"lGGDG","vecsearch(v,x,{cmpf}): determines whether x belongs to the sorted vector v. If the comparison function cmpf is explicitly given, assume that v was sorted according to vecsort(, cmpf)."},
+{"vecsort",0,(void*)vecsort0,10,"GDGD0,L,","vecsort(x,{cmpf},{flag=0}): sorts the vector of vectors (or matrix) x in ascending order, according to the comparison function cmpf, if not omitted. (If cmpf is an integer, sort according to the value of the k-th component of each entry.) Binary digits of flag (if present) mean: 1: indirect sorting, return the permutation instead of the permuted vector, 2: sort using lexicographic order, 4: use descending instead of ascending order, 8: remove d [...]
+{"vecsum",0,(void*)vecsum,10,"G","vecsum(v): return the sum of the components of the vector v"},
+{"vector",0,(void*)vecteur,10,"GDVDE","vector(n,{X},{expr=0}): row vector with n components of expression expr (X ranges from 1 to n). By default, fill with 0s."},
+{"vectorsmall",0,(void*)vecteursmall,10,"GDVDE","vectorsmall(n,{X},{expr=0}): VECSMALL with n components of expression expr (X ranges from 1 to n) which must be small integers. By default, fill with 0s."},
+{"vectorv",0,(void*)vvecteur,10,"GDVDE","vectorv(n,{X},{expr=0}): column vector with n components of expression expr (X ranges from 1 to n). By default, fill with 0s."},
+{"version",0,(void*)pari_version,13,"","version(): returns the PARI version as [major,minor,patch] or [major,minor,patch,VCSversion]."},
+{"warning",0,(void*)warning0,13,"vs*","warning({str}*): display warning message str"},
 {"weber",0,(void*)weber0,3,"GD0,L,p","weber(x,{flag=0}): One of Weber's f function of x. flag is optional, and can be 0: default, function f(x)=exp(-i*Pi/24)*eta((x+1)/2)/eta(x), 1: function f1(x)=eta(x/2)/eta(x) 2: function f2(x)=sqrt(2)*eta(2*x)/eta(x). Note that j = (f^24-16)^3/f^24 = (f1^24+16)^3/f1^24 = (f2^24+16)^3/f2^24."},
-{"while",0,(void*)whilepari,11,"vEI","while(a,seq): while a is nonzero evaluate the expression sequence seq. Otherwise 0."},
-{"write",0,(void*)write0,11,"vss*","write(filename,{str}*): appends the remaining arguments (same output as print) to filename."},
-{"write1",0,(void*)write1,11,"vss*","write1(filename,{str}*): appends the remaining arguments (same output as print1) to filename."},
-{"writebin",0,(void*)gpwritebin,11,"vsDG","writebin(filename,{x}): write x as a binary object to file filename. If x is omitted, write all session variables."},
-{"writetex",0,(void*)writetex,11,"vss*","writetex(filename,{str}*): appends the remaining arguments (same format as print) to filename, in TeX format."},
+{"while",0,(void*)whilepari,13,"vEI","while(a,seq): while a is nonzero evaluate the expression sequence seq. Otherwise 0."},
+{"write",0,(void*)write0,13,"vss*","write(filename,{str}*): appends the remaining arguments (same output as print) to filename."},
+{"write1",0,(void*)write1,13,"vss*","write1(filename,{str}*): appends the remaining arguments (same output as print1) to filename."},
+{"writebin",0,(void*)gpwritebin,13,"vsDG","writebin(filename,{x}): write x as a binary object to file filename. If x is omitted, write all session variables."},
+{"writetex",0,(void*)writetex,13,"vss*","writetex(filename,{str}*): appends the remaining arguments (same format as print) to filename, in TeX format."},
 {"zeta",0,(void*)gzeta,3,"Gp","zeta(s): Riemann zeta function at s with s a complex or a p-adic number."},
-{"zetak",0,(void*)gzetakall,6,"GGD0,L,p","zetak(nfz,x,{flag=0}): Dedekind zeta function of the number field nfz at x, where nfz is the vector computed by zetakinit (NOT by nfinit); flag is optional, and can be 0: default, compute zetak, or non-zero: compute the lambdak function, i.e. with the gamma factors."},
-{"zetakinit",0,(void*)initzeta,6,"Gp","zetakinit(bnf): compute number field information necessary to use zetak. bnf may also be an irreducible polynomial."},
+{"zetak",0,(void*)gzetakall,7,"GGD0,L,p","zetak(nfz,x,{flag=0}): Dedekind zeta function of the number field nfz at x, where nfz is the vector computed by zetakinit (NOT by nfinit); flag is optional, and can be 0: default, compute zetak, or non-zero: compute the lambdak function, i.e. with the gamma factors."},
+{"zetakinit",0,(void*)initzeta,7,"Gp","zetakinit(bnf): compute number field information necessary to use zetak. bnf may also be an irreducible polynomial."},
 {"zncoppersmith",0,(void*)zncoppersmith,4,"GGGDG","zncoppersmith(P, N, X, {B=N}): finds all integers x with |x| <= X such that  gcd(N, P(x)) >= B. X should be smaller than exp((log B)^2 / (deg(P) log N))."},
 {"znlog",0,(void*)znlog,4,"GGDG","znlog(x,g,{o}): return the discrete logarithm of x in (Z/nZ)* in base g. If present, o represents the multiplicative order of g. Return [] if no solution exist."},
 {"znorder",0,(void*)znorder,4,"GDG","znorder(x,{o}): order of the integermod x in (Z/nZ)*. Optional o represents a multiple of the order of the element."},
diff --git a/src/language/intnum.c b/src/language/intnum.c
index 8bd60c4..2fed8cf 100644
--- a/src/language/intnum.c
+++ b/src/language/intnum.c
@@ -146,11 +146,10 @@ static GEN
 rom_bsmall(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long prec)
 {
   if (gcmpgs(a,-100) >= 0) return qrom2(E,eval,a,b,prec);
-  if (b == gen_1 || gcmpgs(b, -1) >= 0) /* a < -100, b >= -1 */
-    return gadd(qromi(E,eval,a,gen_m1,prec), /* split at -1 */
-                qrom2(E,eval,gen_m1,b,prec));
-  /* a < -100, b < -1 */
-  return qromi(E,eval,a,b,prec);
+  if (gcmpgs(b, -1) < 0)   return qromi(E,eval,a,b,prec); /* a<-100, b<-1 */
+  /* a<-100, b>=-1, split at -1 */
+  return gadd(qromi(E,eval,a,gen_m1,prec),
+              qrom2(E,eval,gen_m1,b,prec));
 }
 
 static GEN
@@ -264,27 +263,20 @@ checktab(GEN tab)
       && checktabsimp(gel(tab,2));
 }
 
-static long
-findmforinit(long m, long prec)
+long
+intnumstep(long prec)
 {
-  long p, r;
-
-  if (m <= 0)
-  {
-    p = (long)prec2nbits_mul(prec, 0.3);
-    m = 2; r = 4;
-    while (r < p) { m++; r <<= 1; }
-  }
+  long m = 2, r = 4, p = (long)prec2nbits_mul(prec, 0.3);
+  while (r < p) { m++; r <<= 1; }
   return m;
 }
 
-long
-intnumstep(long prec) { return findmforinit(0, prec); }
-
 static void
-intinit_start(intdata *D, long m0, long flext, long prec)
+intinit_start(intdata *D, long m, long flext, long prec)
 {
-  long m = findmforinit(m0, prec), lim = 20L<<m;
+  long lim;
+  if (m <= 0) m = intnumstep(prec);
+  lim = 20L<<m;
   if (flext > 0) lim = lim << (2*flext);
   D->m = m;
   D->eps = prec2nbits(prec);
@@ -324,7 +316,7 @@ divr2_ip(GEN x) { shiftr_inplace(x, -1); return x; }
 static GEN
 inittanhsinh(long m, long prec)
 {
-  pari_sp av, ltop = avma;
+  pari_sp av;
   GEN h, et, ct, st, ext, ex, xp, wp;
   long k, nt = -1, lim;
   intdata D; intinit_start(&D, m, 0, prec);
@@ -348,7 +340,7 @@ inittanhsinh(long m, long prec)
     affrr(xp, gel(D.tabxp,k));
     affrr(wp, gel(D.tabwp,k)); et = gerepileuptoleaf(av, mulrr(et, ex));
   }
-  return gerepilecopy(ltop, intinit_end(&D, nt, 0));
+  return intinit_end(&D, nt, 0);
 }
 
 /* phi(t)=sinh(sinh(t)) : from -\infty to \infty, slowly decreasing, at least
@@ -356,7 +348,7 @@ inittanhsinh(long m, long prec)
 static GEN
 initsinhsinh(long m, long prec)
 {
-  pari_sp av, ltop = avma;
+  pari_sp av;
   GEN h, et, ct, st, ext, exu, ex, xp, wp;
   long k, nt = -1, lim;
   intdata D; intinit_start(&D, m, 0, prec);
@@ -380,7 +372,7 @@ initsinhsinh(long m, long prec)
     affrr(xp, gel(D.tabxp,k));
     affrr(wp, gel(D.tabwp,k)); et = gerepileuptoleaf(av, mulrr(et, ex));
   }
-  return gerepilecopy(ltop, intinit_end(&D, nt, 0));
+  return intinit_end(&D, nt, 0);
 }
 
 /* phi(t)=2sinh(t) : from -\infty to \infty, exponentially decreasing as
@@ -388,7 +380,7 @@ initsinhsinh(long m, long prec)
 static GEN
 initsinh(long m, long prec)
 {
-  pari_sp av, ltop = avma;
+  pari_sp av;
   GEN h, et, ex, eti, xp, wp;
   long k, nt = -1, lim;
   intdata D; intinit_start(&D, m, 0, prec);
@@ -409,7 +401,7 @@ initsinh(long m, long prec)
     affrr(xp, gel(D.tabxp,k));
     affrr(wp, gel(D.tabwp,k)); et = gerepileuptoleaf(av, mulrr(et, ex));
   }
-  return gerepilecopy(ltop, intinit_end(&D, nt, 0));
+  return intinit_end(&D, nt, 0);
 }
 
 /* phi(t)=exp(2sinh(t)) : from 0 to \infty, slowly decreasing at least as
@@ -417,7 +409,6 @@ initsinh(long m, long prec)
 static GEN
 initexpsinh(long m, long prec)
 {
-  pari_sp ltop = avma;
   GEN h, et, eti, ex, xp;
   long k, nt = -1, lim;
   intdata D; intinit_start(&D, m, 0, prec);
@@ -440,14 +431,14 @@ initexpsinh(long m, long prec)
     gel(D.tabwm,k) = mulrr(gel(D.tabxm,k), t);
     if (expo(gel(D.tabxm,k)) < -D.eps) { nt = k-1; break; }
   }
-  return gerepilecopy(ltop, intinit_end(&D, nt, nt));
+  return intinit_end(&D, nt, nt);
 }
 
 /* phi(t)=exp(t-exp(-t)) : from 0 to \infty, exponentially decreasing. */
 static GEN
 initexpexp(long m, long prec)
 {
-  pari_sp av, ltop = avma;
+  pari_sp av;
   GEN kh, h, et, eti, ex, xp, xm, wp, wm;
   long k, nt = -1, lim;
   intdata D; intinit_start(&D, m, 0, prec);
@@ -474,14 +465,14 @@ initexpexp(long m, long prec)
     affrr(xm, gel(D.tabxm,k));
     affrr(wm, gel(D.tabwm,k)); et = gerepileuptoleaf(av, mulrr(et, ex));
   }
-  return gerepilecopy(ltop, intinit_end(&D, nt, nt));
+  return intinit_end(&D, nt, nt);
 }
 
 /* phi(t)=(Pi/h)t/(1-exp(-sinh(t))) : from 0 to \infty, sine oscillation. */
 static GEN
 initnumsine(long m, long prec)
 {
-  pari_sp av, ltop = avma;
+  pari_sp av;
   GEN h, et, eti, ex, st, ct, extp, extm, extp1, extm1, extp2, extm2, kpi, kct;
   GEN xp, xm, wp, wm, pi = mppi(prec);
   long k, nt = -1, lim;
@@ -517,7 +508,7 @@ initnumsine(long m, long prec)
     affrr(xm, gel(D.tabxm,k));
     affrr(wm, gel(D.tabwm,k)); et = gerepileuptoleaf(av, mulrr(et, ex));
   }
-  return gerepilecopy(ltop, intinit_end(&D, nt, nt));
+  return intinit_end(&D, nt, nt);
 }
 
 static GEN
@@ -535,7 +526,7 @@ suminit_start(GEN sig)
   }
   else sig2 = gen_0;
   if (!isinR(sig)) pari_err_TYPE("sumnum",sig);
-  return mkvec2(mkvec(gen_1), sig2);
+  return mkvec2(mkoo(), sig2);
 }
 
 /* phi(t) depending on sig[2] as in intnum, with weights phi'(t)tanh(Pi*phi(t))
@@ -552,7 +543,7 @@ sumnuminit(GEN sig, long m, long sgn, long prec)
   b = suminit_start(sig);
   flii = gequal0(gel(b,2));
   if (flii)
-    tab = intnuminit(mkvec(gen_m1), mkvec(gen_1), m, prec);
+    tab = intnuminit(mkmoo(), mkoo(), m, prec);
   else
     tab = intnuminit(gen_0, b, m, prec);
   eps = prec2nbits(prec);
@@ -765,12 +756,12 @@ intninfinf(void *E, GEN (*eval)(void*, GEN), GEN tab)
 /* general num integration routine int_a^b f(t)dt, where a and b are as follows:
  (1) a scalar : the scalar, no singularity worse than logarithmic at a.
  (2) [a, e] : the scalar a, singularity exponent -1 < e <= 0.
- (3) [1], [-1] : +\infty, -\infty, slowly decreasing function.
- (4) [[+-1], a], a nonnegative real : +-\infty, function behaving like
+ (3) oo, -oo : +\infty, -\infty, slowly decreasing function.
+ (4) [[+-oo], a], a nonnegative real : +-\infty, function behaving like
       exp(-a|t|) at +-\infty.
- (5) [[+-1], e], e < -1 : +-\infty, function behaving like t^e
+ (5) [[+-oo], e], e < -1 : +-\infty, function behaving like t^e
       at +-\infty.
- (5) [[+-1], a*I], a real : +-\infty, function behaving like cos(at) if a>0
+ (5) [[+-oo], a*I], a real : +-\infty, function behaving like cos(at) if a>0
      and like sin(at) if a < 0 at +-\infty.
 */
 
@@ -778,8 +769,8 @@ intninfinf(void *E, GEN (*eval)(void*, GEN), GEN tab)
 enum {
   f_REG    = 0, /* regular function */
   f_SING   = 1, /* algebraic singularity */
-  f_YSLOW  = 2, /* +\infty, slowly decreasing */
-  f_YVSLO  = 3, /* +\infty, very slowly decreasing */
+  f_YSLOW  = 2, /* +\infty, slowly decreasing, at least x^(-2)  */
+  f_YVSLO  = 3, /* +\infty, very slowly decreasing, worse than x^(-2) */
   f_YFAST  = 4, /* +\infty, exponentially decreasing */
   f_YOSCS  = 5, /* +\infty, sine oscillating */
   f_YOSCC  = 6  /* +\infty, cosine oscillating */
@@ -813,7 +804,7 @@ err_code(GEN a, const char *name)
   pari_err_TYPE(s, a);
 }
 
-/* a = [[+/-1], alpha]*/
+/* a = [[+/-oo], alpha]*/
 static long
 code_aux(GEN a, const char *name)
 {
@@ -839,22 +830,31 @@ static long
 transcode(GEN a, const char *name)
 {
   GEN a1, a2;
-  if (typ(a) != t_VEC) return f_REG;
+  switch(typ(a))
+  {
+    case t_VEC: break;
+    case t_INFINITY: return inf_get_sign(a) == 1 ? f_YSLOW: -f_YSLOW;
+    default: return f_REG;
+  }
   switch(lg(a))
   {
     case 2: return gsigne(gel(a,1)) > 0 ? f_YSLOW : -f_YSLOW;
-    case 3: a1 = gel(a,1); a2 = gel(a,2); break;
+    case 3: break;
     default: err_code(a,name);
   }
   a1 = gel(a,1);
   a2 = gel(a,2);
-  if (typ(a1) != t_VEC)
+  switch(typ(a1))
   {
-    if (!isinC(a1) || !isinR(a2) || gcmpgs(a2, -1) <= 0) err_code(a,name);
-    return gsigne(a2) < 0 ? f_SING : f_REG;
+    case t_VEC:
+      if (lg(a1) != 2) err_code(a,name);
+      return gsigne(gel(a1,1)) * code_aux(a, name);
+    case t_INFINITY:
+      return inf_get_sign(a1) * code_aux(a, name);
+    default:
+      if (!isinC(a1) || !isinR(a2) || gcmpgs(a2, -1) <= 0) err_code(a,name);
+      return gsigne(a2) < 0 ? f_SING : f_REG;
   }
-  if (lg(a1) != 2) err_code(a,name);
-  return gsigne(gel(a1,1)) * code_aux(a, name);
 }
 
 /* computes the necessary tabs, knowing a, b and m */
@@ -918,80 +918,70 @@ exptab(GEN tab, GEN k, long prec)
   return v;
 }
 
-GEN
-intnuminit(GEN a, GEN b, long m, long prec)
+static GEN
+init_fin(GEN b, long codeb, long m, long l, long prec)
+{
+  switch(labs(codeb))
+  {
+    case f_REG:
+    case f_SING:  return inittanhsinh(m,l);
+    case f_YSLOW: return initexpsinh(m,l);
+    case f_YVSLO: return exptab(initexpsinh(m,l), gel(b,2), prec);
+    case f_YFAST: return homtab(initexpexp(m,l), f_getycplx(b,l));
+    /* f_YOSCS, f_YOSCC */
+    default: return homtab(initnumsine(m,l),f_getycplx(b,l));
+  }
+}
+
+static GEN
+intnuminit_i(GEN a, GEN b, long m, long prec)
 {
   long codea, codeb, l;
-  GEN T, U, km, kma, kmb, tmp;
+  GEN T, kma, kmb, tmp;
 
   if (m > 30) pari_err_OVERFLOW("intnuminit [m]");
   l = prec+EXTRAPREC;
   codea = transcode(a, "a");
   codeb = transcode(b, "b");
-  if (is_fin_f(codea) && is_fin_f(codeb)) return inittanhsinh(m, l);
   if (labs(codea) > labs(codeb)) { swap(a, b); lswap(codea, codeb); }
   if (codea == f_REG)
   {
-    km = f_getycplx(b, l);
+    T = init_fin(b, codeb, m,l,prec);
     switch(labs(codeb))
     {
-      case f_YSLOW: return initexpsinh(m, l);
-      case f_YVSLO: return exptab(initexpsinh(m, l), gel(b,2), prec);
-      case f_YFAST: return homtab(initexpexp(m, l), km);
-      case f_YOSCS:
-        if (typ(a) == t_VEC || gequal0(a)) return homtab(initnumsine(m, l), km);
-            /* fall through */
-      case f_YOSCC:
-        T = cgetg(3, t_VEC);
-        gel(T,1) = inittanhsinh(m, l);
-        gel(T,2) = homtab(initnumsine(m, l), km);
-        return T;
+      case f_YOSCS: if (gequal0(a)) break;
+      case f_YOSCC: T = mkvec2(inittanhsinh(m,l), T);
     }
+    return T;
   }
   if (codea == f_SING)
   {
-    km = f_getycplx(b, l);
-    T = cgetg(3, t_VEC);
-    gel(T,1) = inittanhsinh(m, l);
-    switch(labs(codeb))
-    {
-      case f_YSLOW: gel(T,2) = initexpsinh(m, l); break;
-      case f_YVSLO: gel(T,2) = exptab(initexpsinh(m, l), gel(b,2), prec); break;
-      case f_YFAST: gel(T,2) = homtab(initexpexp(m, l), km); break;
-      case f_YOSCS: case f_YOSCC:
-        gel(T,2) = homtab(initnumsine(m, l), km); break;
-    }
+    T = init_fin(b,codeb, m,l,prec);
+    T = mkvec2(inittanhsinh(m,l), T);
     return T;
   }
+  /* now a and b are infinite */
   if (codea * codeb > 0) return gen_0;
-  kma = f_getycplx(a, l);
-  kmb = f_getycplx(b, l);
-  codea = labs(codea);
-  codeb = labs(codeb);
+  kma = f_getycplx(a,l); codea = labs(codea);
+  kmb = f_getycplx(b,l); codeb = labs(codeb);
   if (codea == f_YSLOW && codeb == f_YSLOW) return initsinhsinh(m, l);
   if (codea == f_YFAST && codeb == f_YFAST && gequal(kma, kmb))
-    return homtab(initsinh(m, l), kmb);
+    return homtab(initsinh(m,l), kmb);
   T = cgetg(3, t_VEC);
   switch (codea)
   {
-    case f_YSLOW: gel(T,1) = initexpsinh(m, l);
-      switch (codeb)
-      {
-        case f_YVSLO: gel(T,2) = exptab(gel(T,1), gel(b,2), prec); return T;
-        case f_YFAST: gel(T,2) = homtab(initexpexp(m, l), kmb); return T;
-        case f_YOSCS: case f_YOSCC:
-          gel(T,2) = homtab(initnumsine(m, l), kmb); return T;
-      }
+    case f_YSLOW:
     case f_YVSLO:
-      tmp = initexpsinh(m, l);
-      gel(T,1) = exptab(tmp, gel(a,2), prec);
+      tmp = initexpsinh(m,l);
+      gel(T,1) = codea == f_YSLOW? tmp: exptab(tmp, gel(a,2), prec);
       switch (codeb)
       {
         case f_YVSLO: gel(T,2) = exptab(tmp, gel(b,2), prec); return T;
-        case f_YFAST: gel(T,2) = homtab(initexpexp(m, l), kmb); return T;
+        case f_YFAST: gel(T,2) = homtab(initexpexp(m,l), kmb); return T;
         case f_YOSCS:
-        case f_YOSCC: gel(T,2) = homtab(initnumsine(m, l), kmb); return T;
+        case f_YOSCC: gel(T,2) = homtab(initnumsine(m,l), kmb); return T;
       }
+      break;
     case f_YFAST:
       tmp = initexpexp(m, l);
       gel(T,1) = homtab(tmp, kma);
@@ -1001,22 +991,25 @@ intnuminit(GEN a, GEN b, long m, long prec)
         case f_YOSCS:
         case f_YOSCC: gel(T,2) = homtab(initnumsine(m, l), kmb); return T;
       }
-    case f_YOSCS: case f_YOSCC: tmp = initnumsine(m, l);
-      gel(T,1) = homtab(tmp, kma);
+    case f_YOSCS: case f_YOSCC:
+      tmp = initnumsine(m, l);
+      gel(T,1) = homtab(tmp,kma);
       if (codea == f_YOSCC && codeb == f_YOSCC && !gequal(kma, kmb))
-      {
-        U = cgetg(3, t_VEC);
-        gel(U,1) = inittanhsinh(m, l);
-        gel(U,2) = homtab(tmp, kmb);
-        gel(T,2) = U;
-      }
-      else gel(T,2) = homtab(tmp, kmb);
+        gel(T,2) = mkvec2(inittanhsinh(m,l), homtab(tmp,kmb));
+      else
+        gel(T,2) = homtab(tmp,kmb);
       return T;
   }
   return gen_0; /* not reached */
 }
-
 GEN
+intnuminit(GEN a, GEN b, long m, long prec)
+{
+  pari_sp av = avma;
+  return gerepilecopy(av, intnuminit_i(a,b,m,prec));
+}
+
+static GEN
 intnuminit0(GEN a, GEN b, GEN tab, long prec)
 {
   long m;
@@ -1030,7 +1023,7 @@ intnuminit0(GEN a, GEN b, GEN tab, long prec)
     m = itos(tab);
   return intnuminit(a, b, m, prec);
 }
-GEN
+static GEN
 sumnuminit0(GEN a, GEN tab, long sgn, long prec)
 {
   long m;
@@ -1240,14 +1233,13 @@ intfuncinit(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long m, long flag, l
 static GEN
 intnum_i(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab, long prec)
 {
-  GEN tmp, S = gen_0, res1, res2, tm, pi2, pi2p, pis2, pis2p, kma, kmb;
-  GEN SP, SN;
-  long tmpi, sgns = 1, codea = transcode(a, "a"), codeb = transcode(b, "b");
+  GEN S = gen_0, res1, res2, kma, kmb;
+  long sb, sgns = 1, codea = transcode(a, "a"), codeb = transcode(b, "b");
 
   if (codea == f_REG && typ(a) == t_VEC) a = gel(a,1);
   if (codeb == f_REG && typ(b) == t_VEC) b = gel(b,1);
   if (codea == f_REG && codeb == f_REG) return intn(E, eval, a, b, tab);
-  if (labs(codea) > labs(codeb)) { swap(a, b); lswap(codea, codeb); sgns = -1; }
+  if (labs(codea) > labs(codeb)) { swap(a,b); lswap(codea,codeb); sgns = -1; }
   /* now labs(codea) <= labs(codeb) */
   if (codeb == f_SING)
   {
@@ -1255,75 +1247,83 @@ intnum_i(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab, long prec)
       S = intnsing(E, eval, b, a, tab, prec), sgns = -sgns;
     else
     {
-      tmp = gmul2n(gadd(gel(a,1), gel(b,1)), -1);
-      res1 = intnsing(E, eval, a, tmp, tab, prec);
-      res2 = intnsing(E, eval, b, tmp, tab, prec);
+      GEN c = gmul2n(gadd(gel(a,1), gel(b,1)), -1);
+      res1 = intnsing(E, eval, a, c, tab, prec);
+      res2 = intnsing(E, eval, b, c, tab, prec);
       S = gsub(res1, res2);
     }
     return (sgns < 0) ? gneg(S) : S;
   }
   /* now b is infinite */
-  tmpi = codeb > 0 ? 1 : -1;
+  sb = codeb > 0 ? 1 : -1;
   if (codea == f_REG && labs(codeb) != f_YOSCC
       && (labs(codeb) != f_YOSCS || gequal0(a)))
   {
-    S = intninfpm(E, eval, a, tmpi, tab);
-    return sgns*tmpi < 0 ? gneg(S) : S;
+    S = intninfpm(E, eval, a, sb, tab);
+    return sgns*sb < 0 ? gneg(S) : S;
   }
-  pi2 = Pi2n(1, prec); pis2 = Pi2n(-1, prec);
   if (is_fin_f(codea))
   { /* either codea == f_SING  or codea == f_REG and codeb = f_YOSCC
      * or (codeb == f_YOSCS and !gequal0(a)) */
-    pi2p = gmul(pi2, f_getycplx(b, prec));
-    pis2p = gmul2n(pi2p, -2);
-    tm = real_i(codea == f_SING ? gel(a,1) : a);
-    if (labs(codeb) == f_YOSCC) tm = gadd(tm, pis2p);
-    tm = gdiv(tm, pi2p);
-    if (tmpi > 0)
-      tm = addsi(1, gceil(tm));
-    else
-      tm = subis(gfloor(tm), 1);
-    tm = gmul(pi2p, tm);
-    if (labs(codeb) == f_YOSCC) tm = gsub(tm, pis2p);
-    res1 = codea==f_SING? intnsing(E, eval, a,  tm,  gel(tab,1), prec)
-                        : intn    (E, eval, a,  tm,  gel(tab,1));
-    res2 = intninfpm(E, eval, tm, tmpi,gel(tab,2));
-    if (tmpi < 0) res2 = gneg(res2);
+    GEN c;
+    GEN pi2p = gmul(Pi2n(1,prec), f_getycplx(b, prec));
+    GEN pis2p = gmul2n(pi2p, -2);
+    c = real_i(codea == f_SING ? gel(a,1) : a);
+    codeb = labs(codeb);
+    switch(codeb)
+    {
+      case f_YOSCC: case f_YOSCS:
+        if (codeb == f_YOSCC) c = gadd(c, pis2p);
+        c = gdiv(c, pi2p);
+        if (sb > 0)
+          c = addsi(1, gceil(c));
+        else
+          c = subis(gfloor(c), 1);
+        c = gmul(pi2p, c);
+        if (codeb == f_YOSCC) c = gsub(c, pis2p);
+        break;
+      default: c = addsi(1, gceil(c));
+        break;
+    }
+    res1 = codea==f_SING? intnsing(E, eval, a, c, gel(tab,1), prec)
+                        : intn    (E, eval, a, c, gel(tab,1));
+    res2 = intninfpm(E, eval, c, sb,gel(tab,2));
+    if (sb < 0) res2 = gneg(res2);
     res1 = gadd(res1, res2);
     return sgns < 0 ? gneg(res1) : res1;
   }
   /* now a and b are infinite */
   if (codea * codeb > 0)
   {
-    pari_warn(warner, "integral from infty to infty or from -infty to -infty");
+    if (codea > 0) pari_warn(warner, "integral from oo to oo");
+    if (codea < 0) pari_warn(warner, "integral from -oo to -oo");
     return gen_0;
   }
-  if (codea > 0) { lswap(codea, codeb); swap(a, b); sgns = -sgns; }
-  /* now codea < 0 < codeb */
-  codea = -codea;
-  kma = f_getycplx(a, prec);
-  kmb = f_getycplx(b, prec);
+  if (sb < 0) sgns = -sgns;
+  kma = f_getycplx(a, prec); codea = labs(codea);
+  kmb = f_getycplx(b, prec); codeb = labs(codeb);
   if ((codea == f_YSLOW && codeb == f_YSLOW)
    || (codea == f_YFAST && codeb == f_YFAST && gequal(kma, kmb)))
     S = intninfinf(E, eval, tab);
   else
   {
-    GEN coupea = (codea == f_YOSCC)? gmul(pis2, kma): gen_0;
-    GEN coupeb = (codeb == f_YOSCC)? gmul(pis2, kmb): gen_0;
-    GEN coupe = codea == f_YOSCC ? coupea : coupeb;
-    SN = intninfpm(E, eval, coupe, -1, gel(tab,1));
+    GEN pis2 = Pi2n(-1, prec);
+    GEN ca = (codea == f_YOSCC)? gmul(pis2, kma): gen_0;
+    GEN cb = (codeb == f_YOSCC)? gmul(pis2, kmb): gen_0;
+    GEN c = codea == f_YOSCC ? ca : cb;
+    GEN SP, SN = intninfpm(E, eval, c, -sb, gel(tab,1)); /* signe(a) = -sb */
     if (codea != f_YOSCC)
-      SP = intninfpm(E, eval, coupeb, 1, gel(tab,2));
+      SP = intninfpm(E, eval, cb, sb, gel(tab,2));
     else
     {
       if (codeb != f_YOSCC) pari_err_BUG("code error in intnum");
       if (gequal(kma, kmb))
-        SP = intninfpm(E, eval, coupeb, 1, gel(tab,2));
+        SP = intninfpm(E, eval, cb, sb, gel(tab,2));
       else
       {
         tab = gel(tab,2);
-        SP = intninfpm(E, eval, coupeb, 1, gel(tab,2));
-        SP = gadd(SP, intn(E, eval, coupea, coupeb, gel(tab,1)));
+        SP = intninfpm(E, eval, cb, sb, gel(tab,2));
+        SP = gadd(SP, intn(E, eval, ca, cb, gel(tab,1)));
       }
     }
     S = gadd(SN, SP);
@@ -1376,11 +1376,12 @@ intcirc(void *E, GEN (*eval)(void*, GEN), GEN a, GEN R, GEN tab, long prec)
   return gmul2n(gmul(R, z), -1);
 }
 
-static GEN
-gettmpP(GEN x) { return mkvec2(mkvec(gen_1), x); }
-
-static GEN
-gettmpN(GEN tmpP) { return mkvec2(gneg(gel(tmpP,1)), gel(tmpP,2)); }
+static void
+getinf(GEN x, GEN *P, GEN *N)
+{
+  *P = mkvec2(mkoo(), x);
+  *N = mkvec2(mkmoo(),x);
+}
 
 /* w(Rt) f(a+it) */
 static GEN
@@ -1394,7 +1395,7 @@ static GEN
 intinvintern(void *E, GEN (*eval)(void*, GEN), GEN sig, GEN x, GEN tab, long prec)
 {
   auxint_t D;
-  GEN z, zR, zI, tmpP, tmpN;
+  GEN z, zR, zI, P, N;
 
   if (lg(sig) != 3 || !isinR(gel(sig,1)) || !isinR(gel(sig,2)))
     pari_err_TYPE("integral transform",sig);
@@ -1406,23 +1407,24 @@ intinvintern(void *E, GEN (*eval)(void*, GEN), GEN sig, GEN x, GEN tab, long pre
   D.E = E;
   if (gequal0(gel(sig,2)))
   {
+    GEN c = mulcxI(gabs(x, prec));
     D.R = x;
-    tmpP = gettmpP(mulcxI(gabs(x, prec)));
-    tmpN = gettmpN(tmpP);
-    tab = intnuminit0(tmpN, tmpP, tab, prec);
+    getinf(c, &P, &N);
+    tab = intnuminit0(N, P, tab, prec);
     D.w = gcos;
-    zR = intnum_i(&D, &auxinv, tmpN, tmpP, tab, prec);
-    gel(tmpP,2) = gneg(gel(tmpP,2));
+    zR = intnum_i(&D, &auxinv, N, P, tab, prec);
+
+    getinf(gneg(c), &P, &N);
     D.w = gsin;
-    zI = intnum_i(&D, &auxinv, gettmpN(tmpP), tmpP, tab, prec);
+    zI = intnum_i(&D, &auxinv, N, P, tab, prec);
     z = gadd(zR, mulcxI(zI));
   }
   else
   {
     D.R = mulcxI(x);
-    tmpP = gettmpP(gel(sig,2));
+    getinf(gel(sig,2), &P, &N);
     D.w = gexp;
-    z = intnum(&D, &auxinv, gettmpN(tmpP), tmpP, tab, prec);
+    z = intnum(&D, &auxinv, N, P, tab, prec);
   }
   return gdiv(gmul(gexp(gmul(gel(sig,1), x), prec), z), Pi2n(1, prec));
 }
@@ -1462,7 +1464,7 @@ GEN
 intmellininvshort(GEN sig, GEN x, GEN tab, long prec)
 {
   auxmel_t D;
-  GEN z, tmpP, LX = gneg(glog(x, prec));
+  GEN z, P,N, LX = gneg(glog(x, prec));
 
   if (typ(sig) != t_VEC) sig = mkvec2(sig, gen_1);
   if (lg(sig) != 3 || !isinR(gel(sig,1)) || !isinR(gel(sig,2)))
@@ -1471,8 +1473,8 @@ intmellininvshort(GEN sig, GEN x, GEN tab, long prec)
     pari_err_OVERFLOW("intinvmellinshort [need exponential decrease]");
   D.L = mulcxI(LX);
   D.prec = prec;
-  tmpP = gettmpP(gel(sig,2));
-  z = intnum_i(&D, &auxmelshort, gettmpN(tmpP), tmpP, tab, prec);
+  getinf(gel(sig,2), &P,&N);
+  z = intnum_i(&D, &auxmelshort, N, P, tab, prec);
   return gdiv(gmul(gexp(gmul(gel(sig,1), LX), prec), z), Pi2n(1, prec));
 }
 
@@ -1491,8 +1493,8 @@ mytra(GEN a, GEN x, long flag, const char *name)
       if (!s) pari_err_DOMAIN("Fourier transform","Re(x)","=",gen_0,x);
       if (s < 0) xa = gneg(xa);
       b = cgetg(3, t_VEC);
-      gel(b,1) = mkvec( codea > 0 ? gen_1 : gen_m1 );
-      gel(b,2) = (flag? mulcxI(xa): mulcxmI(xa));
+      gel(b,1) = codea > 0? mkoo(): mkmoo();
+      gel(b,2) = flag? mulcxI(xa): mulcxmI(xa);
       return b;
     case f_YOSCS: case f_YOSCC:
       pari_err_IMPL("Fourier transform of oscillating functions");
diff --git a/src/language/members.c b/src/language/members.c
index 96b612c..2342d84 100644
--- a/src/language/members.c
+++ b/src/language/members.c
@@ -105,6 +105,7 @@ member_nf(GEN x)
   long t; GEN y = get_nf(x,&t);
   if (!y) {
     if (t == typ_RNF) return gel(x,10);
+    if (t == typ_ELL && ell_get_type(x) == t_ELL_NF) return ellnf_get_nf(x);
     member_err("nf",x);
   }
   return y;
diff --git a/src/language/opcode.h b/src/language/opcode.h
index daa2f66..84d00ff 100644
--- a/src/language/opcode.h
+++ b/src/language/opcode.h
@@ -13,7 +13,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 
 BEGINEXTERN
 
-typedef enum {Gvoid, Gsmall, Gvec, Gvar, Ggen, Gclosure} Gtype;
+typedef enum {Gvoid, Gsmall, Gvec, Gvar, Ggen, Gclosure, Gusmall} Gtype;
 
 typedef enum {OCpushlong='A',OCpushgnil,OCpushgen,OCpushreal,OCpushstoi,OCpushvar,
               OCpop,
@@ -32,6 +32,7 @@ typedef enum {OCpushlong='A',OCpushgnil,OCpushgen,OCpushreal,OCpushstoi,OCpushva
               OCcheckargs,OCcheckargs0,OCdefaultgen,OCdefaultlong,
               OCavma,OCgerepile,
               OCcowvardyn,OCcowvarlex,
-              OCdup,OCstoreptr,OCcheckuserargs} op_code;
+              OCdup,OCstoreptr,OCcheckuserargs,
+              OCitou,OCutoi,OCdefaultulong} op_code;
 
 ENDEXTERN
diff --git a/src/language/parse.c b/src/language/parse.c
index a25def3..2015792 100644
--- a/src/language/parse.c
+++ b/src/language/parse.c
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 2.5.  */
+/* A Bison parser, made by GNU Bison 2.4.3.  */
 
-/* Bison implementation for Yacc-like parsers in C
+/* Skeleton implementation for Bison's Yacc-like parsers in C
    
-      Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2009, 2010 Free Software Foundation, Inc.
    
    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
@@ -44,7 +45,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.5"
+#define YYBISON_VERSION "2.4.3"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -73,7 +74,7 @@
 
 /* Copy the first part of user declarations.  */
 
-/* Line 268 of yacc.c  */
+/* Line 189 of yacc.c  */
 #line 1 "../src/language/parse.y"
 
 /* Copyright (C) 2006  The PARI group.
@@ -99,8 +100,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 #define NOARG(x) newnode(Fnoarg,-1,-1,&(x))
 
 
-/* Line 268 of yacc.c  */
-#line 104 "../src/language/parse.c"
+/* Line 189 of yacc.c  */
+#line 105 "../src/language/parse.c"
 
 /* Enabling traces.  */
 #ifndef YYDEBUG
@@ -188,8 +189,8 @@ typedef struct YYLTYPE
 /* Copy the second part of user declarations.  */
 
 
-/* Line 343 of yacc.c  */
-#line 193 "../src/language/parse.c"
+/* Line 264 of yacc.c  */
+#line 194 "../src/language/parse.c"
 
 #ifdef short
 # undef short
@@ -292,11 +293,11 @@ YYID (yyi)
 #    define alloca _alloca
 #   else
 #    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 #     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#     ifndef EXIT_SUCCESS
-#      define EXIT_SUCCESS 0
+#     ifndef _STDLIB_H
+#      define _STDLIB_H 1
 #     endif
 #    endif
 #   endif
@@ -319,24 +320,24 @@ YYID (yyi)
 #  ifndef YYSTACK_ALLOC_MAXIMUM
 #   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
 #  endif
-#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
+#  if (defined __cplusplus && ! defined _STDLIB_H \
        && ! ((defined YYMALLOC || defined malloc) \
 	     && (defined YYFREE || defined free)))
 #   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   ifndef EXIT_SUCCESS
-#    define EXIT_SUCCESS 0
+#   ifndef _STDLIB_H
+#    define _STDLIB_H 1
 #   endif
 #  endif
 #  ifndef YYMALLOC
 #   define YYMALLOC malloc
-#   if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
 #   endif
 #  endif
 #  ifndef YYFREE
 #   define YYFREE free
-#   if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 void free (void *); /* INFRINGES ON USER NAME SPACE */
 #   endif
@@ -367,7 +368,23 @@ union yyalloc
      ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
       + 2 * YYSTACK_GAP_MAXIMUM)
 
-# define YYCOPY_NEEDED 1
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)		\
+      do					\
+	{					\
+	  YYSIZE_T yyi;				\
+	  for (yyi = 0; yyi < (Count); yyi++)	\
+	    (To)[yyi] = (From)[yyi];		\
+	}					\
+      while (YYID (0))
+#  endif
+# endif
 
 /* Relocate STACK from its old location to the new one.  The
    local variables YYSIZE and YYSTACKSIZE give the old and new number of
@@ -387,30 +404,10 @@ union yyalloc
 
 #endif
 
-#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
-/* Copy COUNT objects from FROM to TO.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined __GNUC__ && 1 < __GNUC__
-#   define YYCOPY(To, From, Count) \
-      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-#  else
-#   define YYCOPY(To, From, Count)		\
-      do					\
-	{					\
-	  YYSIZE_T yyi;				\
-	  for (yyi = 0; yyi < (Count); yyi++)	\
-	    (To)[yyi] = (From)[yyi];		\
-	}					\
-      while (YYID (0))
-#  endif
-# endif
-#endif /* !YYCOPY_NEEDED */
-
 /* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  46
+#define YYFINAL  47
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   638
+#define YYLAST   671
 
 /* YYNTOKENS -- Number of terminals.  */
 #define YYNTOKENS  61
@@ -419,7 +416,7 @@ union yyalloc
 /* YYNRULES -- Number of rules.  */
 #define YYNRULES  109
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  189
+#define YYNSTATES  192
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
@@ -468,76 +465,76 @@ static const yytype_uint8 yytranslate[] =
    YYRHS.  */
 static const yytype_uint16 yyprhs[] =
 {
-       0,     0,     3,     5,     8,     9,    11,    14,    18,    19,
-      21,    25,    28,    34,    38,    40,    43,    45,    48,    51,
-      54,    58,    62,    64,    66,    68,    72,    74,    77,    79,
-      84,    86,    88,    90,    92,    94,    98,   102,   105,   108,
-     112,   116,   120,   124,   128,   132,   136,   140,   144,   147,
-     150,   154,   158,   162,   166,   170,   174,   178,   182,   186,
-     190,   194,   198,   202,   206,   210,   214,   218,   222,   226,
-     229,   232,   236,   239,   242,   245,   248,   250,   254,   258,
-     260,   263,   267,   269,   273,   277,   281,   284,   290,   294,
-     298,   302,   306,   311,   313,   317,   321,   327,   333,   335,
-     338,   339,   344,   346,   350,   355,   359,   366,   372,   376
+       0,     0,     3,     5,     6,     8,    11,    15,    16,    18,
+      22,    25,    31,    35,    37,    40,    42,    45,    48,    51,
+      55,    59,    61,    63,    65,    69,    71,    74,    76,    81,
+      83,    85,    87,    89,    91,    95,    99,   102,   105,   109,
+     113,   117,   121,   125,   129,   133,   137,   141,   144,   147,
+     151,   155,   159,   163,   167,   171,   175,   179,   183,   187,
+     191,   195,   199,   203,   207,   211,   215,   219,   223,   226,
+     229,   233,   236,   239,   242,   245,   247,   251,   255,   257,
+     260,   264,   266,   270,   274,   278,   281,   287,   291,   295,
+     299,   303,   308,   310,   314,   318,   324,   330,   332,   337,
+     340,   341,   346,   348,   352,   357,   361,   368,   374,   378
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      62,     0,    -1,    63,    -1,    63,     1,    -1,    -1,    68,
-      -1,    63,    35,    -1,    63,    35,    68,    -1,    -1,    68,
-      -1,    68,     5,    68,    -1,    48,    68,    -1,    52,    64,
-      36,    64,    57,    -1,    52,    64,    57,    -1,    58,    -1,
-      66,    58,    -1,    43,    -1,    43,    27,    -1,    43,    66,
-      -1,    43,    49,    -1,    43,    49,    27,    -1,    43,    49,
-      66,    -1,    27,    -1,    28,    -1,    54,    -1,    27,    54,
-      29,    -1,    30,    -1,    53,    29,    -1,    67,    -1,    68,
-      55,    78,    59,    -1,    79,    -1,    69,    -1,    72,    -1,
-      75,    -1,    81,    -1,    72,    37,    68,    -1,    69,    37,
-      68,    -1,    69,    25,    -1,    69,    26,    -1,    69,     8,
-      68,    -1,    69,     9,    68,    -1,    69,    10,    68,    -1,
-      69,    11,    68,    -1,    69,    12,    68,    -1,    69,    21,
-      68,    -1,    69,    20,    68,    -1,    69,     6,    68,    -1,
-      69,     7,    68,    -1,    50,    68,    -1,    49,    68,    -1,
-      68,    14,    68,    -1,    68,    13,    68,    -1,    68,    38,
-      68,    -1,    68,    15,    68,    -1,    68,    16,    68,    -1,
-      68,    17,    68,    -1,    68,    18,    68,    -1,    68,    39,
-      68,    -1,    68,    19,    68,    -1,    68,    40,    68,    -1,
-      68,    42,    68,    -1,    68,    41,    68,    -1,    68,    23,
-      68,    -1,    68,    22,    68,    -1,    68,    43,    68,    -1,
-      68,    24,    68,    -1,    68,    44,    68,    -1,    68,    45,
-      68,    -1,    68,    46,    68,    -1,    41,    68,    -1,    42,
-      68,    -1,    68,    48,    68,    -1,    68,    51,    -1,    68,
-      53,    -1,    68,    50,    -1,    68,    65,    -1,    80,    -1,
-      68,    56,    29,    -1,    55,    68,    59,    -1,    29,    -1,
-      69,    65,    -1,    69,    56,    29,    -1,    68,    -1,    70,
-      36,    68,    -1,    70,    35,    70,    -1,    71,    35,    70,
-      -1,    52,    57,    -1,    52,    68,     5,    68,    57,    -1,
-      52,    35,    57,    -1,    52,    70,    57,    -1,    52,    71,
-      57,    -1,    52,     1,    57,    -1,    69,    40,    42,    68,
-      -1,    73,    -1,    73,    36,    68,    -1,    73,    35,    74,
-      -1,    73,    36,    68,    35,    74,    -1,    52,    68,    60,
-      74,    57,    -1,    63,    -1,    38,    69,    -1,    -1,    76,
-       1,    77,    68,    -1,    76,    -1,    78,    36,    76,    -1,
-      29,    55,    78,    59,    -1,    68,    54,    29,    -1,    29,
-      55,    78,    59,    37,    63,    -1,    68,    54,    29,    37,
-      63,    -1,    69,     4,    63,    -1,    55,    78,     3,    63,
-      -1
+      62,     0,    -1,    63,    -1,    -1,    68,    -1,    63,    35,
+      -1,    63,    35,    68,    -1,    -1,    68,    -1,    68,     5,
+      68,    -1,    48,    68,    -1,    52,    64,    36,    64,    57,
+      -1,    52,    64,    57,    -1,    58,    -1,    66,    58,    -1,
+      43,    -1,    43,    27,    -1,    43,    66,    -1,    43,    49,
+      -1,    43,    49,    27,    -1,    43,    49,    66,    -1,    27,
+      -1,    28,    -1,    54,    -1,    27,    54,    29,    -1,    30,
+      -1,    53,    29,    -1,    67,    -1,    68,    55,    78,    59,
+      -1,    79,    -1,    69,    -1,    72,    -1,    75,    -1,    81,
+      -1,    72,    37,    68,    -1,    69,    37,    68,    -1,    69,
+      25,    -1,    69,    26,    -1,    69,     8,    68,    -1,    69,
+       9,    68,    -1,    69,    10,    68,    -1,    69,    11,    68,
+      -1,    69,    12,    68,    -1,    69,    21,    68,    -1,    69,
+      20,    68,    -1,    69,     6,    68,    -1,    69,     7,    68,
+      -1,    50,    68,    -1,    49,    68,    -1,    68,    14,    68,
+      -1,    68,    13,    68,    -1,    68,    38,    68,    -1,    68,
+      15,    68,    -1,    68,    16,    68,    -1,    68,    17,    68,
+      -1,    68,    18,    68,    -1,    68,    39,    68,    -1,    68,
+      19,    68,    -1,    68,    40,    68,    -1,    68,    42,    68,
+      -1,    68,    41,    68,    -1,    68,    23,    68,    -1,    68,
+      22,    68,    -1,    68,    43,    68,    -1,    68,    24,    68,
+      -1,    68,    44,    68,    -1,    68,    45,    68,    -1,    68,
+      46,    68,    -1,    41,    68,    -1,    42,    68,    -1,    68,
+      48,    68,    -1,    68,    51,    -1,    68,    53,    -1,    68,
+      50,    -1,    68,    65,    -1,    80,    -1,    68,    56,    29,
+      -1,    55,    68,    59,    -1,    29,    -1,    69,    65,    -1,
+      69,    56,    29,    -1,    68,    -1,    70,    36,    68,    -1,
+      70,    35,    70,    -1,    71,    35,    70,    -1,    52,    57,
+      -1,    52,    68,     5,    68,    57,    -1,    52,    35,    57,
+      -1,    52,    70,    57,    -1,    52,    71,    57,    -1,    52,
+       1,    57,    -1,    69,    40,    42,    68,    -1,    73,    -1,
+      73,    36,    68,    -1,    73,    35,    74,    -1,    73,    36,
+      68,    35,    74,    -1,    52,    68,    60,    74,    57,    -1,
+      63,    -1,    69,    52,     5,    57,    -1,    38,    69,    -1,
+      -1,    76,     1,    77,    68,    -1,    76,    -1,    78,    36,
+      76,    -1,    29,    55,    78,    59,    -1,    68,    54,    29,
+      -1,    29,    55,    78,    59,    37,    63,    -1,    68,    54,
+      29,    37,    63,    -1,    69,     4,    63,    -1,    55,    78,
+       3,    63,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint8 yyrline[] =
 {
-       0,    85,    85,    86,    89,    90,    91,    92,    95,    96,
-      97,    98,   101,   102,   105,   106,   109,   110,   111,   112,
-     113,   114,   117,   118,   119,   120,   122,   123,   124,   125,
+       0,    85,    85,    88,    89,    90,    91,    94,    95,    96,
+      97,   100,   101,   104,   105,   108,   109,   110,   111,   112,
+     113,   116,   117,   118,   119,   121,   122,   123,   124,   125,
      126,   127,   128,   129,   130,   131,   132,   133,   134,   135,
      136,   137,   138,   139,   140,   141,   142,   143,   144,   145,
      146,   147,   148,   149,   150,   151,   152,   153,   154,   155,
      156,   157,   158,   159,   160,   161,   162,   163,   164,   165,
-     166,   167,   168,   169,   170,   171,   172,   173,   174,   177,
-     178,   179,   182,   183,   186,   187,   190,   191,   192,   193,
-     194,   195,   198,   201,   202,   203,   204,   207,   210,   211,
+     166,   167,   168,   169,   170,   171,   172,   173,   176,   177,
+     178,   181,   182,   185,   186,   189,   190,   191,   192,   193,
+     194,   197,   200,   201,   202,   203,   206,   209,   210,   211,
      212,   212,   216,   217,   220,   223,   226,   228,   230,   231
 };
 #endif
@@ -555,7 +552,7 @@ static const char *const yytname[] =
   "\"character string\"", "DEFFUNC", "SEQ", "LVAL", "INT", "';'", "','",
   "'='", "'&'", "'>'", "'<'", "'+'", "'-'", "'%'", "'\\\\'", "'/'", "'*'",
   "SIGN", "'^'", "'#'", "'!'", "'~'", "'['", "'\\''", "'.'", "'('", "':'",
-  "']'", "'`'", "')'", "'|'", "$accept", "sequnused", "seq", "range",
+  "']'", "'`'", "')'", "'|'", "$accept", "sequence", "seq", "range",
   "matrix_index", "backticks", "history", "expr", "lvalue", "matrixelts",
   "matrixlines", "matrix", "in", "inseq", "compr", "arg", "$@1", "listarg",
   "funcid", "memberid", "definition", 0
@@ -580,247 +577,252 @@ static const yytype_uint16 yytoknum[] =
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    61,    62,    62,    63,    63,    63,    63,    64,    64,
-      64,    64,    65,    65,    66,    66,    67,    67,    67,    67,
-      67,    67,    68,    68,    68,    68,    68,    68,    68,    68,
+       0,    61,    62,    63,    63,    63,    63,    64,    64,    64,
+      64,    65,    65,    66,    66,    67,    67,    67,    67,    67,
+      67,    68,    68,    68,    68,    68,    68,    68,    68,    68,
       68,    68,    68,    68,    68,    68,    68,    68,    68,    68,
       68,    68,    68,    68,    68,    68,    68,    68,    68,    68,
       68,    68,    68,    68,    68,    68,    68,    68,    68,    68,
       68,    68,    68,    68,    68,    68,    68,    68,    68,    68,
-      68,    68,    68,    68,    68,    68,    68,    68,    68,    69,
-      69,    69,    70,    70,    71,    71,    72,    72,    72,    72,
-      72,    72,    73,    74,    74,    74,    74,    75,    76,    76,
+      68,    68,    68,    68,    68,    68,    68,    68,    69,    69,
+      69,    70,    70,    71,    71,    72,    72,    72,    72,    72,
+      72,    73,    74,    74,    74,    74,    75,    76,    76,    76,
       77,    76,    78,    78,    79,    80,    81,    81,    81,    81
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 static const yytype_uint8 yyr2[] =
 {
-       0,     2,     1,     2,     0,     1,     2,     3,     0,     1,
-       3,     2,     5,     3,     1,     2,     1,     2,     2,     2,
-       3,     3,     1,     1,     1,     3,     1,     2,     1,     4,
-       1,     1,     1,     1,     1,     3,     3,     2,     2,     3,
-       3,     3,     3,     3,     3,     3,     3,     3,     2,     2,
+       0,     2,     1,     0,     1,     2,     3,     0,     1,     3,
+       2,     5,     3,     1,     2,     1,     2,     2,     2,     3,
+       3,     1,     1,     1,     3,     1,     2,     1,     4,     1,
+       1,     1,     1,     1,     3,     3,     2,     2,     3,     3,
+       3,     3,     3,     3,     3,     3,     3,     2,     2,     3,
        3,     3,     3,     3,     3,     3,     3,     3,     3,     3,
-       3,     3,     3,     3,     3,     3,     3,     3,     3,     2,
-       2,     3,     2,     2,     2,     2,     1,     3,     3,     1,
-       2,     3,     1,     3,     3,     3,     2,     5,     3,     3,
-       3,     3,     4,     1,     3,     3,     5,     5,     1,     2,
+       3,     3,     3,     3,     3,     3,     3,     3,     2,     2,
+       3,     2,     2,     2,     2,     1,     3,     3,     1,     2,
+       3,     1,     3,     3,     3,     2,     5,     3,     3,     3,
+       3,     4,     1,     3,     3,     5,     5,     1,     4,     2,
        0,     4,     1,     3,     4,     3,     6,     5,     3,     4
 };
 
-/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
-   Performed when YYTABLE doesn't specify something else to do.  Zero
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       4,    22,    23,    79,    26,     0,     0,    16,     0,     0,
-       0,     0,    24,     4,     0,     0,    28,     5,    31,    32,
-      33,    30,    76,    34,     0,     4,    69,    70,    17,    19,
-      14,    18,    49,    48,     0,     0,    86,    82,     0,     0,
-      27,     0,    98,     5,     0,     0,     1,     3,     6,     0,
+       3,    21,    22,    78,    25,     0,     0,    15,     0,     0,
+       0,     0,    23,     3,     0,     2,    27,     4,    30,    31,
+      32,    29,    75,    33,     0,     3,    68,    69,    16,    18,
+      13,    17,    48,    47,     0,     0,    85,    81,     0,     0,
+      26,     0,    97,     4,    30,     0,     0,     1,     5,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,    74,
-      72,     8,    73,     0,     4,     0,    75,     4,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    37,    38,     0,
-       0,    80,     0,    25,     0,    20,    21,    15,    91,    88,
-       0,     0,     0,     0,    89,     0,    90,    79,    99,    78,
-     100,     4,     4,     7,    51,    50,    53,    54,    55,    56,
-      58,    63,    62,    65,    52,    57,    59,    61,    60,    64,
-      66,    67,    68,    71,     0,     0,     9,   105,     0,    77,
-     108,    46,    47,    39,    40,    41,    42,    43,    45,    44,
-      36,    81,    35,   104,     0,     0,    93,     0,    82,    84,
-      83,    85,     0,   109,     0,    11,     8,    13,     0,     4,
-      29,     4,    87,     0,     0,     0,    97,   101,     0,    10,
-     107,   106,     0,    95,    94,    12,    92,     0,    96
+       0,     0,     0,     0,     0,     0,     0,     0,     0,    73,
+      71,     7,    72,     0,     3,     0,    74,     3,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    36,    37,     0,
+       0,    79,     0,    24,     0,    19,    20,    14,    90,    87,
+       0,     0,     0,     0,    88,     0,    89,    78,    99,    77,
+       7,   100,     3,     3,     6,    50,    49,    52,    53,    54,
+      55,    57,    62,    61,    64,    51,    56,    58,    60,    59,
+      63,    65,    66,    67,    70,     0,     0,     8,   105,     0,
+      76,   108,    45,    46,    38,    39,    40,    41,    42,    44,
+      43,    35,    80,    34,   104,     0,     0,    92,     0,    81,
+      83,    82,    84,     0,     0,   109,     0,    10,     7,    12,
+       0,     3,    28,     3,    86,     0,     0,     0,    96,    98,
+     101,     0,     9,   107,   106,     0,    94,    93,    11,    91,
+       0,    95
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
-      -1,    14,    42,   135,    76,    31,    16,    17,    18,    38,
-      39,    19,   156,   157,    20,    44,   162,    45,    21,    22,
+      -1,    14,    42,   136,    76,    31,    16,    17,    18,    38,
+      39,    19,   157,   158,    20,    45,   164,    46,    21,    22,
       23
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -162
+#define YYPACT_NINF -165
 static const yytype_int16 yypact[] =
 {
-     583,   -29,  -162,   -26,  -162,   583,   583,    45,   583,   583,
-      81,    -2,  -162,   549,    31,    36,  -162,   428,   223,     1,
-    -162,  -162,  -162,  -162,    41,   549,    93,    93,  -162,   -17,
-    -162,    27,   143,    58,    39,    42,  -162,   168,   -15,    48,
-    -162,    60,    66,   292,    29,     3,  -162,  -162,   583,   583,
-     583,   583,   583,   583,   583,   583,   583,   583,   583,   583,
-     583,   583,   583,   583,   583,   583,   583,   583,   583,  -162,
-    -162,   566,  -162,    64,   549,    73,  -162,   583,   583,   583,
-     583,   583,   583,   583,   583,   583,   583,  -162,  -162,   583,
-      75,  -162,   583,  -162,   -25,  -162,    27,  -162,  -162,  -162,
-     583,    60,   583,   583,  -162,   583,  -162,  -162,   -38,  -162,
-    -162,   583,   549,   428,   470,   470,   505,   505,   505,   505,
-     505,    93,    93,    93,   470,   505,   505,   519,   519,    93,
-      93,    93,    93,    93,   583,    33,   248,    69,   -19,  -162,
-      66,   428,   428,   428,   428,   428,   428,   428,   428,   428,
-     428,  -162,   428,    70,   339,   -28,   -13,    61,   428,    79,
-     428,    79,   583,    66,    32,   428,   566,  -162,   583,   583,
-    -162,   583,  -162,    77,    60,   583,  -162,   428,    68,   428,
-      66,    66,   583,  -162,   384,  -162,   428,    60,  -162
+     616,   -33,  -165,   -28,  -165,   616,   616,   -17,   616,   616,
+      84,     1,  -165,   582,    31,     3,  -165,   461,   141,    46,
+    -165,  -165,  -165,  -165,    60,   582,   150,   150,  -165,    12,
+    -165,    38,   190,    54,    42,    44,  -165,   172,    36,    47,
+    -165,    61,     3,   325,   227,     6,    33,  -165,   616,   616,
+     616,   616,   616,   616,   616,   616,   616,   616,   616,   616,
+     616,   616,   616,   616,   616,   616,   616,   616,   616,  -165,
+    -165,   599,  -165,    73,   582,    74,  -165,   616,   616,   616,
+     616,   616,   616,   616,   616,   616,   616,  -165,  -165,   616,
+      86,  -165,   616,  -165,   -22,  -165,    38,  -165,  -165,  -165,
+     616,    61,   616,   616,  -165,   616,  -165,  -165,   -36,  -165,
+     282,  -165,   616,   582,   461,   503,   503,   538,   538,   538,
+     538,   538,   150,   150,   150,   503,   538,   538,   552,   552,
+     150,   150,   150,   150,   150,   616,    50,   252,    79,   -19,
+    -165,     3,   461,   461,   461,   461,   461,   461,   461,   461,
+     461,   461,  -165,   461,    80,   372,   -27,   -12,    63,   461,
+      82,   461,    82,    64,   616,     3,    32,   461,   599,  -165,
+     616,   616,  -165,   616,  -165,    87,    61,   616,  -165,  -165,
+     461,    65,   461,     3,     3,   616,  -165,   417,  -165,   461,
+      61,  -165
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-    -162,  -162,     9,   -49,   -16,    92,  -162,    -5,   -34,   -86,
-    -162,  -162,  -162,  -161,  -162,    14,  -162,   -10,  -162,  -162,
-    -162
+    -165,  -165,    11,   -44,   -16,    99,  -165,    -5,    -7,   -83,
+    -165,  -165,  -165,  -164,  -165,    18,  -165,   -10,  -165,  -165,
+    -165
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If YYTABLE_NINF, syntax error.  */
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
 #define YYTABLE_NINF -104
 static const yytype_int16 yytable[] =
 {
-      26,    27,    91,    32,    33,    37,   111,   108,    43,    15,
-      95,   112,   173,   183,    71,    94,   159,   112,    90,   161,
-     102,   103,   174,   175,    71,    24,   188,    40,    90,    25,
-     110,    46,  -102,   110,   153,  -103,    -2,    47,    92,   112,
-     170,    30,   104,   113,   114,   115,   116,   117,   118,   119,
-     120,   121,   122,   123,   124,   125,   126,   127,   128,   129,
-     130,   131,   132,   133,   138,  -102,   136,   155,  -103,   166,
-      93,    48,    28,   141,   142,   143,   144,   145,   146,   147,
-     148,   149,    34,   105,   150,    97,   140,   152,  -102,   107,
-     167,  -103,    91,   137,    29,   154,    98,   158,   160,    99,
-     158,    48,   139,    30,   151,   106,   169,   171,     1,     2,
-       3,     4,    73,    74,    75,   103,    35,   178,   176,   182,
-     163,    96,     5,     6,     7,   185,   164,     0,     0,   165,
-       8,     9,     0,    10,    11,    12,    13,     0,    36,    91,
-     155,    68,     0,    69,    70,    71,    72,    73,    74,    75,
-       0,     0,     0,   155,     0,     0,     0,   177,     0,     0,
-       0,   136,     0,   179,     0,     0,     0,     0,     0,     0,
-     184,     0,     0,   100,     0,     0,     0,   186,   180,     0,
-     181,    49,    50,    51,    52,    53,    54,    55,     0,     0,
-      56,    57,    58,    69,    70,    71,    72,    73,    74,    75,
-       0,     0,     0,     0,     0,     0,    59,    60,    61,    62,
-      63,    64,    65,    66,    67,     0,    68,     0,    69,    70,
-      71,    72,    73,    74,    75,     0,     0,    77,   101,    78,
-      79,    80,    81,    82,    83,    84,     0,     0,     0,     0,
-       0,     0,     0,    85,    86,     0,     0,     0,    87,    88,
-       0,     0,     0,   168,     0,     0,     0,     0,     0,     0,
-      89,    49,    50,    51,    52,    53,    54,    55,     0,     0,
-      56,    57,    58,     0,     0,    71,     0,     0,     0,    90,
-       0,     0,     0,     0,     0,     0,    59,    60,    61,    62,
-      63,    64,    65,    66,    67,     0,    68,     0,    69,    70,
-      71,    72,    73,    74,    75,    49,    50,    51,    52,    53,
+      26,    27,    91,    32,    33,    37,    44,   111,    43,  -102,
+      28,    15,   186,   175,   113,    94,    71,   113,    44,   160,
+      90,    24,   162,   176,   177,    71,   191,    25,    91,    90,
+      40,    47,    29,   111,   108,  -103,   112,   154,    48,    95,
+     172,    30,  -102,   114,   115,   116,   117,   118,   119,   120,
+     121,   122,   123,   124,   125,   126,   127,   128,   129,   130,
+     131,   132,   133,   134,   139,  -102,   137,    44,  -103,   113,
+      30,   102,   103,   142,   143,   144,   145,   146,   147,   148,
+     149,   150,   105,    92,   151,    34,   168,   153,   141,    93,
+     107,  -103,    91,   104,   156,   155,    97,   159,   161,    98,
+     159,    99,   138,   140,   106,   137,    44,   169,    73,    74,
+      75,     1,     2,     3,     4,   152,   171,   173,   103,    35,
+     178,   179,   188,   165,   181,     5,     6,     7,    96,   185,
+     167,   166,     0,     8,     9,     0,    10,    11,    12,    13,
+      91,    36,     0,     0,     0,    77,     0,    78,    79,    80,
+      81,    82,    83,    84,     0,     0,     0,     0,     0,   180,
+       0,    85,    86,   137,     0,   182,    87,    88,     0,   156,
+       0,     0,   187,     0,     0,     0,     0,   100,    89,     0,
+     189,     0,   183,   156,   184,    49,    50,    51,    52,    53,
+      54,    55,     0,    71,    56,    57,    58,    90,    68,     0,
+      69,    70,    71,    72,    73,    74,    75,     0,     0,     0,
+      59,    60,    61,    62,    63,    64,    65,    66,    67,     0,
+      68,     0,    69,    70,    71,    72,    73,    74,    75,     0,
+       0,    77,   101,    78,    79,    80,    81,    82,    83,    84,
+      69,    70,    71,    72,    73,    74,    75,    85,    86,     0,
+       0,     0,    87,    88,     0,     0,     0,   170,     0,     0,
+       0,     0,     0,     0,    89,    49,    50,    51,    52,    53,
+      54,    55,     0,     0,    56,    57,    58,     0,     0,   110,
+       0,     0,     0,    90,     0,     0,     0,   163,     0,     0,
+      59,    60,    61,    62,    63,    64,    65,    66,    67,     0,
+      68,     0,    69,    70,    71,    72,    73,    74,    75,     1,
+       2,     3,     4,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     5,     6,     7,     0,     0,     0,     0,
+     135,     8,     9,     0,    10,    11,    12,    13,    49,    50,
+      51,    52,    53,    54,    55,     0,     0,    56,    57,    58,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,    59,    60,    61,    62,    63,    64,    65,
+      66,    67,     0,    68,     0,    69,    70,    71,    72,    73,
+      74,    75,     0,     0,   109,    49,    50,    51,    52,    53,
       54,    55,     0,     0,    56,    57,    58,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
       59,    60,    61,    62,    63,    64,    65,    66,    67,     0,
-      68,     0,    69,    70,    71,    72,    73,    74,    75,     0,
-       0,   109,    49,    50,    51,    52,    53,    54,    55,     0,
-       0,    56,    57,    58,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    59,    60,    61,
-      62,    63,    64,    65,    66,    67,     0,    68,     0,    69,
-      70,    71,    72,    73,    74,    75,   172,    49,    50,    51,
-      52,    53,    54,    55,     0,     0,    56,    57,    58,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   187,
-       0,     0,    59,    60,    61,    62,    63,    64,    65,    66,
-      67,     0,    68,     0,    69,    70,    71,    72,    73,    74,
-      75,    49,    50,    51,    52,    53,    54,    55,     0,     0,
+      68,     0,    69,    70,    71,    72,    73,    74,    75,   174,
+      49,    50,    51,    52,    53,    54,    55,     0,     0,    56,
+      57,    58,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,   190,     0,     0,    59,    60,    61,    62,    63,
+      64,    65,    66,    67,     0,    68,     0,    69,    70,    71,
+      72,    73,    74,    75,    49,    50,    51,    52,    53,    54,
+      55,     0,     0,    56,    57,    58,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,    59,
+      60,    61,    62,    63,    64,    65,    66,    67,     0,    68,
+       0,    69,    70,    71,    72,    73,    74,    75,    51,    52,
+      53,    54,    55,     0,     0,    56,    57,    58,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    60,    61,    62,    63,    64,    65,    66,    67,
+       0,    68,     0,    69,    70,    71,    72,    73,    74,    75,
       56,    57,    58,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,    59,    60,    61,    62,
+       0,     0,     0,     0,    56,    57,    58,     0,     0,    62,
       63,    64,    65,    66,    67,     0,    68,     0,    69,    70,
-      71,    72,    73,    74,    75,    51,    52,    53,    54,    55,
-       0,     0,    56,    57,    58,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,    60,
-      61,    62,    63,    64,    65,    66,    67,     0,    68,     0,
-      69,    70,    71,    72,    73,    74,    75,    56,    57,    58,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,    56,    57,    58,     0,     0,    62,    63,    64,    65,
-      66,    67,     0,    68,     0,    69,    70,    71,    72,    73,
-      74,    75,    64,    65,    66,    67,     0,    68,     0,    69,
-      70,    71,    72,    73,    74,    75,     1,     2,     3,     4,
-       0,     0,     0,     0,     0,     0,     0,    41,     0,     0,
-       5,     6,     7,     1,     2,     3,     4,     0,     8,     9,
+      71,    72,    73,    74,    75,    64,    65,    66,    67,     0,
+      68,     0,    69,    70,    71,    72,    73,    74,    75,     1,
+       2,     3,     4,     0,     0,     0,     0,     0,     0,     0,
+      41,     0,     0,     5,     6,     7,     1,     2,     3,     4,
+       0,     8,     9,     0,    10,    11,    12,    13,     0,     0,
+       5,     6,     7,     1,     2,     3,     4,   135,     8,     9,
        0,    10,    11,    12,    13,     0,     0,     5,     6,     7,
-       1,     2,     3,     4,   134,     8,     9,     0,    10,    11,
-      12,    13,     0,     0,     5,     6,     7,     0,     0,     0,
-       0,     0,     8,     9,     0,    10,    11,    12,    13
+       0,     0,     0,     0,     0,     8,     9,     0,    10,    11,
+      12,    13
 };
 
-#define yypact_value_is_default(yystate) \
-  ((yystate) == (-162))
-
-#define yytable_value_is_error(yytable_value) \
-  YYID (0)
-
 static const yytype_int16 yycheck[] =
 {
-       5,     6,    18,     8,     9,    10,     3,    41,    13,     0,
-      27,    36,    40,   174,    52,    25,   102,    36,    56,   105,
-      35,    36,    35,    36,    52,    54,   187,    29,    56,    55,
-       1,     0,     3,     1,    59,     3,     0,     1,    37,    36,
-      59,    58,    57,    48,    49,    50,    51,    52,    53,    54,
+       5,     6,    18,     8,     9,    10,    13,     1,    13,     3,
+      27,     0,   176,    40,    36,    25,    52,    36,    25,   102,
+      56,    54,   105,    35,    36,    52,   190,    55,    44,    56,
+      29,     0,    49,     1,    41,     3,     3,    59,    35,    27,
+      59,    58,    36,    48,    49,    50,    51,    52,    53,    54,
       55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
-      65,    66,    67,    68,    74,    36,    71,   101,    36,    36,
-      29,    35,    27,    78,    79,    80,    81,    82,    83,    84,
-      85,    86,     1,    35,    89,    58,    77,    92,    59,    29,
-      57,    59,   108,    29,    49,   100,    57,   102,   103,    57,
-     105,    35,    29,    58,    29,    57,    37,    37,    27,    28,
-      29,    30,    54,    55,    56,    36,    35,   166,    57,    42,
-     111,    29,    41,    42,    43,    57,   112,    -1,    -1,   134,
-      49,    50,    -1,    52,    53,    54,    55,    -1,    57,   155,
-     174,    48,    -1,    50,    51,    52,    53,    54,    55,    56,
-      -1,    -1,    -1,   187,    -1,    -1,    -1,   162,    -1,    -1,
-      -1,   166,    -1,   168,    -1,    -1,    -1,    -1,    -1,    -1,
-     175,    -1,    -1,     5,    -1,    -1,    -1,   182,   169,    -1,
-     171,    13,    14,    15,    16,    17,    18,    19,    -1,    -1,
-      22,    23,    24,    50,    51,    52,    53,    54,    55,    56,
-      -1,    -1,    -1,    -1,    -1,    -1,    38,    39,    40,    41,
-      42,    43,    44,    45,    46,    -1,    48,    -1,    50,    51,
-      52,    53,    54,    55,    56,    -1,    -1,     4,    60,     6,
-       7,     8,     9,    10,    11,    12,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    20,    21,    -1,    -1,    -1,    25,    26,
-      -1,    -1,    -1,     5,    -1,    -1,    -1,    -1,    -1,    -1,
-      37,    13,    14,    15,    16,    17,    18,    19,    -1,    -1,
-      22,    23,    24,    -1,    -1,    52,    -1,    -1,    -1,    56,
-      -1,    -1,    -1,    -1,    -1,    -1,    38,    39,    40,    41,
-      42,    43,    44,    45,    46,    -1,    48,    -1,    50,    51,
-      52,    53,    54,    55,    56,    13,    14,    15,    16,    17,
+      65,    66,    67,    68,    74,    59,    71,    74,    36,    36,
+      58,    35,    36,    78,    79,    80,    81,    82,    83,    84,
+      85,    86,    35,    37,    89,     1,    36,    92,    77,    29,
+      29,    59,   108,    57,   101,   100,    58,   102,   103,    57,
+     105,    57,    29,    29,    57,   110,   113,    57,    54,    55,
+      56,    27,    28,    29,    30,    29,    37,    37,    36,    35,
+      57,    57,    57,   112,   168,    41,    42,    43,    29,    42,
+     135,   113,    -1,    49,    50,    -1,    52,    53,    54,    55,
+     156,    57,    -1,    -1,    -1,     4,    -1,     6,     7,     8,
+       9,    10,    11,    12,    -1,    -1,    -1,    -1,    -1,   164,
+      -1,    20,    21,   168,    -1,   170,    25,    26,    -1,   176,
+      -1,    -1,   177,    -1,    -1,    -1,    -1,     5,    37,    -1,
+     185,    -1,   171,   190,   173,    13,    14,    15,    16,    17,
+      18,    19,    -1,    52,    22,    23,    24,    56,    48,    -1,
+      50,    51,    52,    53,    54,    55,    56,    -1,    -1,    -1,
+      38,    39,    40,    41,    42,    43,    44,    45,    46,    -1,
+      48,    -1,    50,    51,    52,    53,    54,    55,    56,    -1,
+      -1,     4,    60,     6,     7,     8,     9,    10,    11,    12,
+      50,    51,    52,    53,    54,    55,    56,    20,    21,    -1,
+      -1,    -1,    25,    26,    -1,    -1,    -1,     5,    -1,    -1,
+      -1,    -1,    -1,    -1,    37,    13,    14,    15,    16,    17,
+      18,    19,    -1,    -1,    22,    23,    24,    -1,    -1,    52,
+      -1,    -1,    -1,    56,    -1,    -1,    -1,     5,    -1,    -1,
+      38,    39,    40,    41,    42,    43,    44,    45,    46,    -1,
+      48,    -1,    50,    51,    52,    53,    54,    55,    56,    27,
+      28,    29,    30,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    41,    42,    43,    -1,    -1,    -1,    -1,
+      48,    49,    50,    -1,    52,    53,    54,    55,    13,    14,
+      15,    16,    17,    18,    19,    -1,    -1,    22,    23,    24,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    -1,    48,    -1,    50,    51,    52,    53,    54,
+      55,    56,    -1,    -1,    59,    13,    14,    15,    16,    17,
       18,    19,    -1,    -1,    22,    23,    24,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       38,    39,    40,    41,    42,    43,    44,    45,    46,    -1,
-      48,    -1,    50,    51,    52,    53,    54,    55,    56,    -1,
-      -1,    59,    13,    14,    15,    16,    17,    18,    19,    -1,
-      -1,    22,    23,    24,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    38,    39,    40,
-      41,    42,    43,    44,    45,    46,    -1,    48,    -1,    50,
-      51,    52,    53,    54,    55,    56,    57,    13,    14,    15,
-      16,    17,    18,    19,    -1,    -1,    22,    23,    24,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    35,
-      -1,    -1,    38,    39,    40,    41,    42,    43,    44,    45,
-      46,    -1,    48,    -1,    50,    51,    52,    53,    54,    55,
-      56,    13,    14,    15,    16,    17,    18,    19,    -1,    -1,
+      48,    -1,    50,    51,    52,    53,    54,    55,    56,    57,
+      13,    14,    15,    16,    17,    18,    19,    -1,    -1,    22,
+      23,    24,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    35,    -1,    -1,    38,    39,    40,    41,    42,
+      43,    44,    45,    46,    -1,    48,    -1,    50,    51,    52,
+      53,    54,    55,    56,    13,    14,    15,    16,    17,    18,
+      19,    -1,    -1,    22,    23,    24,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    38,
+      39,    40,    41,    42,    43,    44,    45,    46,    -1,    48,
+      -1,    50,    51,    52,    53,    54,    55,    56,    15,    16,
+      17,    18,    19,    -1,    -1,    22,    23,    24,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    39,    40,    41,    42,    43,    44,    45,    46,
+      -1,    48,    -1,    50,    51,    52,    53,    54,    55,    56,
       22,    23,    24,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    38,    39,    40,    41,
+      -1,    -1,    -1,    -1,    22,    23,    24,    -1,    -1,    41,
       42,    43,    44,    45,    46,    -1,    48,    -1,    50,    51,
-      52,    53,    54,    55,    56,    15,    16,    17,    18,    19,
-      -1,    -1,    22,    23,    24,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    39,
-      40,    41,    42,    43,    44,    45,    46,    -1,    48,    -1,
-      50,    51,    52,    53,    54,    55,    56,    22,    23,    24,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    22,    23,    24,    -1,    -1,    41,    42,    43,    44,
-      45,    46,    -1,    48,    -1,    50,    51,    52,    53,    54,
-      55,    56,    43,    44,    45,    46,    -1,    48,    -1,    50,
-      51,    52,    53,    54,    55,    56,    27,    28,    29,    30,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    38,    -1,    -1,
-      41,    42,    43,    27,    28,    29,    30,    -1,    49,    50,
+      52,    53,    54,    55,    56,    43,    44,    45,    46,    -1,
+      48,    -1,    50,    51,    52,    53,    54,    55,    56,    27,
+      28,    29,    30,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      38,    -1,    -1,    41,    42,    43,    27,    28,    29,    30,
+      -1,    49,    50,    -1,    52,    53,    54,    55,    -1,    -1,
+      41,    42,    43,    27,    28,    29,    30,    48,    49,    50,
       -1,    52,    53,    54,    55,    -1,    -1,    41,    42,    43,
-      27,    28,    29,    30,    48,    49,    50,    -1,    52,    53,
-      54,    55,    -1,    -1,    41,    42,    43,    -1,    -1,    -1,
-      -1,    -1,    49,    50,    -1,    52,    53,    54,    55
+      -1,    -1,    -1,    -1,    -1,    49,    50,    -1,    52,    53,
+      54,    55
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -831,21 +833,22 @@ static const yytype_uint8 yystos[] =
       52,    53,    54,    55,    62,    63,    67,    68,    69,    72,
       75,    79,    80,    81,    54,    55,    68,    68,    27,    49,
       58,    66,    68,    68,     1,    35,    57,    68,    70,    71,
-      29,    38,    63,    68,    76,    78,     0,     1,    35,    13,
+      29,    38,    63,    68,    69,    76,    78,     0,    35,    13,
       14,    15,    16,    17,    18,    19,    22,    23,    24,    38,
       39,    40,    41,    42,    43,    44,    45,    46,    48,    50,
       51,    52,    53,    54,    55,    56,    65,     4,     6,     7,
        8,     9,    10,    11,    12,    20,    21,    25,    26,    37,
       56,    65,    37,    29,    78,    27,    66,    58,    57,    57,
        5,    60,    35,    36,    57,    35,    57,    29,    69,    59,
-       1,     3,    36,    68,    68,    68,    68,    68,    68,    68,
+      52,     1,     3,    36,    68,    68,    68,    68,    68,    68,
       68,    68,    68,    68,    68,    68,    68,    68,    68,    68,
-      68,    68,    68,    68,    48,    64,    68,    29,    78,    29,
-      63,    68,    68,    68,    68,    68,    68,    68,    68,    68,
-      68,    29,    68,    59,    68,    69,    73,    74,    68,    70,
-      68,    70,    77,    63,    76,    68,    36,    57,     5,    37,
-      59,    37,    57,    40,    35,    36,    57,    68,    64,    68,
-      63,    63,    42,    74,    68,    57,    68,    35,    74
+      68,    68,    68,    68,    68,    48,    64,    68,    29,    78,
+      29,    63,    68,    68,    68,    68,    68,    68,    68,    68,
+      68,    68,    29,    68,    59,    68,    69,    73,    74,    68,
+      70,    68,    70,     5,    77,    63,    76,    68,    36,    57,
+       5,    37,    59,    37,    57,    40,    35,    36,    57,    57,
+      68,    64,    68,    63,    63,    42,    74,    68,    57,    68,
+      35,    74
 };
 
 #define yyerrok		(yyerrstatus = 0)
@@ -881,6 +884,7 @@ do								\
     {								\
       yychar = (Token);						\
       yylval = (Value);						\
+      yytoken = YYTRANSLATE (yychar);				\
       YYPOPSTACK (1);						\
       goto yybackup;						\
     }								\
@@ -1136,6 +1140,7 @@ int yydebug;
 # define YYMAXDEPTH 10000
 #endif
 
+

 
 #if YYERROR_VERBOSE
 
@@ -1238,142 +1243,115 @@ yytnamerr (char *yyres, const char *yystr)
 }
 # endif
 
-/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
-   about the unexpected token YYTOKEN for the state stack whose top is
-   YYSSP.
-
-   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
-   not large enough to hold the message.  In that case, also set
-   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
-   required number of bytes is too large to store.  */
-static int
-yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
-                yytype_int16 *yyssp, int yytoken)
+/* Copy into YYRESULT an error message about the unexpected token
+   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
+   including the terminating null byte.  If YYRESULT is null, do not
+   copy anything; just return the number of bytes that would be
+   copied.  As a special case, return 0 if an ordinary "syntax error"
+   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
+   size calculation.  */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
 {
-  YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]);
-  YYSIZE_T yysize = yysize0;
-  YYSIZE_T yysize1;
-  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
-  /* Internationalized format string. */
-  const char *yyformat = 0;
-  /* Arguments of yyformat. */
-  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
-  /* Number of reported tokens (one for the "unexpected", one per
-     "expected"). */
-  int yycount = 0;
-
-  /* There are many possibilities here to consider:
-     - Assume YYFAIL is not used.  It's too flawed to consider.  See
-       <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
-       for details.  YYERROR is fine as it does not invoke this
-       function.
-     - If this state is a consistent state with a default action, then
-       the only way this function was invoked is if the default action
-       is an error action.  In that case, don't check for expected
-       tokens because there are none.
-     - The only way there can be no lookahead present (in yychar) is if
-       this state is a consistent state with a default action.  Thus,
-       detecting the absence of a lookahead is sufficient to determine
-       that there is no unexpected or expected token to report.  In that
-       case, just report a simple "syntax error".
-     - Don't assume there isn't a lookahead just because this state is a
-       consistent state with a default action.  There might have been a
-       previous inconsistent state, consistent state with a non-default
-       action, or user semantic action that manipulated yychar.
-     - Of course, the expected token list depends on states to have
-       correct lookahead information, and it depends on the parser not
-       to perform extra reductions after fetching a lookahead from the
-       scanner and before detecting a syntax error.  Thus, state merging
-       (from LALR or IELR) and default reductions corrupt the expected
-       token list.  However, the list is correct for canonical LR with
-       one exception: it will still contain any token that will not be
-       accepted due to an error action in a later state.
-  */
-  if (yytoken != YYEMPTY)
-    {
-      int yyn = yypact[*yyssp];
-      yyarg[yycount++] = yytname[yytoken];
-      if (!yypact_value_is_default (yyn))
-        {
-          /* Start YYX at -YYN if negative to avoid negative indexes in
-             YYCHECK.  In other words, skip the first -YYN actions for
-             this state because they are default actions.  */
-          int yyxbegin = yyn < 0 ? -yyn : 0;
-          /* Stay within bounds of both yycheck and yytname.  */
-          int yychecklim = YYLAST - yyn + 1;
-          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-          int yyx;
-
-          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
-                && !yytable_value_is_error (yytable[yyx + yyn]))
-              {
-                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
-                  {
-                    yycount = 1;
-                    yysize = yysize0;
-                    break;
-                  }
-                yyarg[yycount++] = yytname[yyx];
-                yysize1 = yysize + yytnamerr (0, yytname[yyx]);
-                if (! (yysize <= yysize1
-                       && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-                  return 2;
-                yysize = yysize1;
-              }
-        }
-    }
+  int yyn = yypact[yystate];
 
-  switch (yycount)
+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+    return 0;
+  else
     {
-# define YYCASE_(N, S)                      \
-      case N:                               \
-        yyformat = S;                       \
-      break
-      YYCASE_(0, YY_("syntax error"));
-      YYCASE_(1, YY_("syntax error, unexpected %s"));
-      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
-      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
-      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
-      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-# undef YYCASE_
-    }
+      int yytype = YYTRANSLATE (yychar);
+      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+      YYSIZE_T yysize = yysize0;
+      YYSIZE_T yysize1;
+      int yysize_overflow = 0;
+      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+      int yyx;
+
+# if 0
+      /* This is so xgettext sees the translatable formats that are
+	 constructed on the fly.  */
+      YY_("syntax error, unexpected %s");
+      YY_("syntax error, unexpected %s, expecting %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+      char *yyfmt;
+      char const *yyf;
+      static char const yyunexpected[] = "syntax error, unexpected %s";
+      static char const yyexpecting[] = ", expecting %s";
+      static char const yyor[] = " or %s";
+      char yyformat[sizeof yyunexpected
+		    + sizeof yyexpecting - 1
+		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+		       * (sizeof yyor - 1))];
+      char const *yyprefix = yyexpecting;
+
+      /* Start YYX at -YYN if negative to avoid negative indexes in
+	 YYCHECK.  */
+      int yyxbegin = yyn < 0 ? -yyn : 0;
+
+      /* Stay within bounds of both yycheck and yytname.  */
+      int yychecklim = YYLAST - yyn + 1;
+      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+      int yycount = 1;
+
+      yyarg[0] = yytname[yytype];
+      yyfmt = yystpcpy (yyformat, yyunexpected);
+
+      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+	  {
+	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+	      {
+		yycount = 1;
+		yysize = yysize0;
+		yyformat[sizeof yyunexpected - 1] = '\0';
+		break;
+	      }
+	    yyarg[yycount++] = yytname[yyx];
+	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+	    yysize_overflow |= (yysize1 < yysize);
+	    yysize = yysize1;
+	    yyfmt = yystpcpy (yyfmt, yyprefix);
+	    yyprefix = yyor;
+	  }
 
-  yysize1 = yysize + yystrlen (yyformat);
-  if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-    return 2;
-  yysize = yysize1;
+      yyf = YY_(yyformat);
+      yysize1 = yysize + yystrlen (yyf);
+      yysize_overflow |= (yysize1 < yysize);
+      yysize = yysize1;
 
-  if (*yymsg_alloc < yysize)
-    {
-      *yymsg_alloc = 2 * yysize;
-      if (! (yysize <= *yymsg_alloc
-             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
-        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
-      return 1;
-    }
+      if (yysize_overflow)
+	return YYSIZE_MAXIMUM;
 
-  /* Avoid sprintf, as that infringes on the user's name space.
-     Don't have undefined behavior even if the translation
-     produced a string with the wrong number of "%s"s.  */
-  {
-    char *yyp = *yymsg;
-    int yyi = 0;
-    while ((*yyp = *yyformat) != '\0')
-      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
-        {
-          yyp += yytnamerr (yyp, yyarg[yyi++]);
-          yyformat += 2;
-        }
-      else
-        {
-          yyp++;
-          yyformat++;
-        }
-  }
-  return 0;
+      if (yyresult)
+	{
+	  /* Avoid sprintf, as that infringes on the user's name space.
+	     Don't have undefined behavior even if the translation
+	     produced a string with the wrong number of "%s"s.  */
+	  char *yyp = yyresult;
+	  int yyi = 0;
+	  while ((*yyp = *yyf) != '\0')
+	    {
+	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+		{
+		  yyp += yytnamerr (yyp, yyarg[yyi++]);
+		  yyf += 2;
+		}
+	      else
+		{
+		  yyp++;
+		  yyf++;
+		}
+	    }
+	}
+      return yysize;
+    }
 }
 #endif /* YYERROR_VERBOSE */
+

 
 /*-----------------------------------------------.
 | Release the memory associated to this symbol.  |
@@ -1406,165 +1384,165 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp, lex)
     {
       case 63: /* "seq" */
 
-/* Line 1391 of yacc.c  */
+/* Line 1009 of yacc.c  */
 #line 82 "../src/language/parse.y"
 	{ pari_discarded++; };
 
-/* Line 1391 of yacc.c  */
-#line 1415 "../src/language/parse.c"
+/* Line 1009 of yacc.c  */
+#line 1393 "../src/language/parse.c"
 	break;
       case 64: /* "range" */
 
-/* Line 1391 of yacc.c  */
+/* Line 1009 of yacc.c  */
 #line 82 "../src/language/parse.y"
 	{ pari_discarded++; };
 
-/* Line 1391 of yacc.c  */
-#line 1424 "../src/language/parse.c"
+/* Line 1009 of yacc.c  */
+#line 1402 "../src/language/parse.c"
 	break;
       case 65: /* "matrix_index" */
 
-/* Line 1391 of yacc.c  */
+/* Line 1009 of yacc.c  */
 #line 82 "../src/language/parse.y"
 	{ pari_discarded++; };
 
-/* Line 1391 of yacc.c  */
-#line 1433 "../src/language/parse.c"
+/* Line 1009 of yacc.c  */
+#line 1411 "../src/language/parse.c"
 	break;
       case 66: /* "backticks" */
 
-/* Line 1391 of yacc.c  */
+/* Line 1009 of yacc.c  */
 #line 82 "../src/language/parse.y"
 	{ pari_discarded++; };
 
-/* Line 1391 of yacc.c  */
-#line 1442 "../src/language/parse.c"
+/* Line 1009 of yacc.c  */
+#line 1420 "../src/language/parse.c"
 	break;
       case 67: /* "history" */
 
-/* Line 1391 of yacc.c  */
+/* Line 1009 of yacc.c  */
 #line 82 "../src/language/parse.y"
 	{ pari_discarded++; };
 
-/* Line 1391 of yacc.c  */
-#line 1451 "../src/language/parse.c"
+/* Line 1009 of yacc.c  */
+#line 1429 "../src/language/parse.c"
 	break;
       case 68: /* "expr" */
 
-/* Line 1391 of yacc.c  */
+/* Line 1009 of yacc.c  */
 #line 82 "../src/language/parse.y"
 	{ pari_discarded++; };
 
-/* Line 1391 of yacc.c  */
-#line 1460 "../src/language/parse.c"
+/* Line 1009 of yacc.c  */
+#line 1438 "../src/language/parse.c"
 	break;
       case 69: /* "lvalue" */
 
-/* Line 1391 of yacc.c  */
+/* Line 1009 of yacc.c  */
 #line 82 "../src/language/parse.y"
 	{ pari_discarded++; };
 
-/* Line 1391 of yacc.c  */
-#line 1469 "../src/language/parse.c"
+/* Line 1009 of yacc.c  */
+#line 1447 "../src/language/parse.c"
 	break;
       case 70: /* "matrixelts" */
 
-/* Line 1391 of yacc.c  */
+/* Line 1009 of yacc.c  */
 #line 82 "../src/language/parse.y"
 	{ pari_discarded++; };
 
-/* Line 1391 of yacc.c  */
-#line 1478 "../src/language/parse.c"
+/* Line 1009 of yacc.c  */
+#line 1456 "../src/language/parse.c"
 	break;
       case 71: /* "matrixlines" */
 
-/* Line 1391 of yacc.c  */
+/* Line 1009 of yacc.c  */
 #line 82 "../src/language/parse.y"
 	{ pari_discarded++; };
 
-/* Line 1391 of yacc.c  */
-#line 1487 "../src/language/parse.c"
+/* Line 1009 of yacc.c  */
+#line 1465 "../src/language/parse.c"
 	break;
       case 72: /* "matrix" */
 
-/* Line 1391 of yacc.c  */
+/* Line 1009 of yacc.c  */
 #line 82 "../src/language/parse.y"
 	{ pari_discarded++; };
 
-/* Line 1391 of yacc.c  */
-#line 1496 "../src/language/parse.c"
+/* Line 1009 of yacc.c  */
+#line 1474 "../src/language/parse.c"
 	break;
       case 73: /* "in" */
 
-/* Line 1391 of yacc.c  */
+/* Line 1009 of yacc.c  */
 #line 82 "../src/language/parse.y"
 	{ pari_discarded++; };
 
-/* Line 1391 of yacc.c  */
-#line 1505 "../src/language/parse.c"
+/* Line 1009 of yacc.c  */
+#line 1483 "../src/language/parse.c"
 	break;
       case 74: /* "inseq" */
 
-/* Line 1391 of yacc.c  */
+/* Line 1009 of yacc.c  */
 #line 82 "../src/language/parse.y"
 	{ pari_discarded++; };
 
-/* Line 1391 of yacc.c  */
-#line 1514 "../src/language/parse.c"
+/* Line 1009 of yacc.c  */
+#line 1492 "../src/language/parse.c"
 	break;
       case 75: /* "compr" */
 
-/* Line 1391 of yacc.c  */
+/* Line 1009 of yacc.c  */
 #line 82 "../src/language/parse.y"
 	{ pari_discarded++; };
 
-/* Line 1391 of yacc.c  */
-#line 1523 "../src/language/parse.c"
+/* Line 1009 of yacc.c  */
+#line 1501 "../src/language/parse.c"
 	break;
       case 76: /* "arg" */
 
-/* Line 1391 of yacc.c  */
+/* Line 1009 of yacc.c  */
 #line 82 "../src/language/parse.y"
 	{ pari_discarded++; };
 
-/* Line 1391 of yacc.c  */
-#line 1532 "../src/language/parse.c"
+/* Line 1009 of yacc.c  */
+#line 1510 "../src/language/parse.c"
 	break;
       case 78: /* "listarg" */
 
-/* Line 1391 of yacc.c  */
+/* Line 1009 of yacc.c  */
 #line 82 "../src/language/parse.y"
 	{ pari_discarded++; };
 
-/* Line 1391 of yacc.c  */
-#line 1541 "../src/language/parse.c"
+/* Line 1009 of yacc.c  */
+#line 1519 "../src/language/parse.c"
 	break;
       case 79: /* "funcid" */
 
-/* Line 1391 of yacc.c  */
+/* Line 1009 of yacc.c  */
 #line 82 "../src/language/parse.y"
 	{ pari_discarded++; };
 
-/* Line 1391 of yacc.c  */
-#line 1550 "../src/language/parse.c"
+/* Line 1009 of yacc.c  */
+#line 1528 "../src/language/parse.c"
 	break;
       case 80: /* "memberid" */
 
-/* Line 1391 of yacc.c  */
+/* Line 1009 of yacc.c  */
 #line 82 "../src/language/parse.y"
 	{ pari_discarded++; };
 
-/* Line 1391 of yacc.c  */
-#line 1559 "../src/language/parse.c"
+/* Line 1009 of yacc.c  */
+#line 1537 "../src/language/parse.c"
 	break;
       case 81: /* "definition" */
 
-/* Line 1391 of yacc.c  */
+/* Line 1009 of yacc.c  */
 #line 82 "../src/language/parse.y"
 	{ pari_discarded++; };
 
-/* Line 1391 of yacc.c  */
-#line 1568 "../src/language/parse.c"
+/* Line 1009 of yacc.c  */
+#line 1546 "../src/language/parse.c"
 	break;
 
       default:
@@ -1572,7 +1550,6 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp, lex)
     }
 }
 
-
 /* Prevent warnings from -Wmissing-prototypes.  */
 #ifdef YYPARSE_PARAM
 #if defined __STDC__ || defined __cplusplus
@@ -1589,9 +1566,12 @@ int yyparse ();
 #endif /* ! YYPARSE_PARAM */
 
 
-/*----------.
-| yyparse.  |
-`----------*/
+
+
+
+/*-------------------------.
+| yyparse or yypush_parse.  |
+`-------------------------*/
 
 #ifdef YYPARSE_PARAM
 #if (defined __STDC__ || defined __C99__FUNC__ \
@@ -1710,12 +1690,12 @@ YYLTYPE yylloc;
 
 /* User initialization code.  */
 
-/* Line 1590 of yacc.c  */
+/* Line 1251 of yacc.c  */
 #line 29 "../src/language/parse.y"
 { yylloc.start=yylloc.end=*lex; }
 
-/* Line 1590 of yacc.c  */
-#line 1719 "../src/language/parse.c"
+/* Line 1251 of yacc.c  */
+#line 1699 "../src/language/parse.c"
   yylsp[0] = yylloc;
 
   goto yysetstate;
@@ -1814,7 +1794,7 @@ yybackup:
 
   /* First try to decide what to do without reference to lookahead token.  */
   yyn = yypact[yystate];
-  if (yypact_value_is_default (yyn))
+  if (yyn == YYPACT_NINF)
     goto yydefault;
 
   /* Not known => get a lookahead token if don't already have one.  */
@@ -1845,8 +1825,8 @@ yybackup:
   yyn = yytable[yyn];
   if (yyn <= 0)
     {
-      if (yytable_value_is_error (yyn))
-        goto yyerrlab;
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+	goto yyerrlab;
       yyn = -yyn;
       goto yyreduce;
     }
@@ -1902,778 +1882,767 @@ yyreduce:
     {
         case 2:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 85 "../src/language/parse.y"
-    {(yyval.val)=(yyvsp[(1) - (1)].val);}
+    {(yyval.val)=(yyvsp[(1) - (1)].val);;}
     break;
 
   case 3:
 
-/* Line 1806 of yacc.c  */
-#line 86 "../src/language/parse.y"
-    {(yyval.val)=(yyvsp[(1) - (2)].val); pari_unused_chars=(yylsp[(1) - (2)]).end;YYABORT;}
+/* Line 1464 of yacc.c  */
+#line 88 "../src/language/parse.y"
+    {(yyval.val)=NOARG((yyloc));;}
     break;
 
   case 4:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 89 "../src/language/parse.y"
-    {(yyval.val)=NOARG((yyloc));}
+    {(yyval.val)=(yyvsp[(1) - (1)].val);;}
     break;
 
   case 5:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 90 "../src/language/parse.y"
-    {(yyval.val)=(yyvsp[(1) - (1)].val);}
+    {(yyval.val)=(yyvsp[(1) - (2)].val); (yyloc)=(yylsp[(1) - (2)]);;}
     break;
 
   case 6:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 91 "../src/language/parse.y"
-    {(yyval.val)=(yyvsp[(1) - (2)].val); (yyloc)=(yylsp[(1) - (2)]);}
+    {(yyval.val)=newnode(Fseq,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 7:
 
-/* Line 1806 of yacc.c  */
-#line 92 "../src/language/parse.y"
-    {(yyval.val)=newnode(Fseq,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+/* Line 1464 of yacc.c  */
+#line 94 "../src/language/parse.y"
+    { (yyval.val)=newnode(Frange,NOARG((yyloc)),NOARG((yyloc)),&(yyloc)); ;}
     break;
 
   case 8:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 95 "../src/language/parse.y"
-    { (yyval.val)=newnode(Frange,NOARG((yyloc)),NOARG((yyloc)),&(yyloc)); }
+    { (yyval.val)=newnode(Frange,(yyvsp[(1) - (1)].val),NOARG((yyloc)),&(yyloc)); ;}
     break;
 
   case 9:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 96 "../src/language/parse.y"
-    { (yyval.val)=newnode(Frange,(yyvsp[(1) - (1)].val),NOARG((yyloc)),&(yyloc)); }
+    { (yyval.val)=newnode(Frange,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc)); ;}
     break;
 
   case 10:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 97 "../src/language/parse.y"
-    { (yyval.val)=newnode(Frange,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc)); }
+    { (yyval.val)=newnode(Frange,NOARG((yyloc)),(yyvsp[(2) - (2)].val),&(yyloc)); ;}
     break;
 
   case 11:
 
-/* Line 1806 of yacc.c  */
-#line 98 "../src/language/parse.y"
-    { (yyval.val)=newnode(Frange,NOARG((yyloc)),(yyvsp[(2) - (2)].val),&(yyloc)); }
+/* Line 1464 of yacc.c  */
+#line 100 "../src/language/parse.y"
+    {(yyval.val)=newnode(Fmatrix,(yyvsp[(2) - (5)].val),(yyvsp[(4) - (5)].val),&(yyloc));;}
     break;
 
   case 12:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 101 "../src/language/parse.y"
-    {(yyval.val)=newnode(Fmatrix,(yyvsp[(2) - (5)].val),(yyvsp[(4) - (5)].val),&(yyloc));}
+    {(yyval.val)=newnode(Fmatrix,(yyvsp[(2) - (3)].val),-1,&(yyloc));;}
     break;
 
   case 13:
 
-/* Line 1806 of yacc.c  */
-#line 102 "../src/language/parse.y"
-    {(yyval.val)=newnode(Fmatrix,(yyvsp[(2) - (3)].val),-1,&(yyloc));}
+/* Line 1464 of yacc.c  */
+#line 104 "../src/language/parse.y"
+    {(yyval.val)=1;;}
     break;
 
   case 14:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 105 "../src/language/parse.y"
-    {(yyval.val)=1;}
+    {(yyval.val)=(yyvsp[(1) - (2)].val)+1;;}
     break;
 
   case 15:
 
-/* Line 1806 of yacc.c  */
-#line 106 "../src/language/parse.y"
-    {(yyval.val)=(yyvsp[(1) - (2)].val)+1;}
+/* Line 1464 of yacc.c  */
+#line 108 "../src/language/parse.y"
+    {(yyval.val)=newopcall(OPhist,-1,-1,&(yyloc));;}
     break;
 
   case 16:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 109 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPhist,-1,-1,&(yyloc));}
+    {(yyval.val)=newopcall(OPhist,newintnode(&(yylsp[(2) - (2)])),-1,&(yyloc));;}
     break;
 
   case 17:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 110 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPhist,newintnode(&(yylsp[(2) - (2)])),-1,&(yyloc));}
+    {(yyval.val)=newopcall(OPhist,newnode(Fsmall,-(yyvsp[(2) - (2)].val),-1,&(yyloc)),-1,&(yyloc));;}
     break;
 
   case 18:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 111 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPhist,newnode(Fsmall,-(yyvsp[(2) - (2)].val),-1,&(yyloc)),-1,&(yyloc));}
+    {(yyval.val)=newopcall(OPhisttime,-1,-1,&(yyloc));;}
     break;
 
   case 19:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 112 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPhisttime,-1,-1,&(yyloc));}
+    {(yyval.val)=newopcall(OPhisttime,newintnode(&(yylsp[(3) - (3)])),-1,&(yyloc));;}
     break;
 
   case 20:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 113 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPhisttime,newintnode(&(yylsp[(3) - (3)])),-1,&(yyloc));}
+    {(yyval.val)=newopcall(OPhisttime,newnode(Fsmall,-(yyvsp[(3) - (3)].val),-1,&(yyloc)),-1,&(yyloc));;}
     break;
 
   case 21:
 
-/* Line 1806 of yacc.c  */
-#line 114 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPhisttime,newnode(Fsmall,-(yyvsp[(3) - (3)].val),-1,&(yyloc)),-1,&(yyloc));}
+/* Line 1464 of yacc.c  */
+#line 116 "../src/language/parse.y"
+    {(yyval.val)=newintnode(&(yylsp[(1) - (1)]));;}
     break;
 
   case 22:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 117 "../src/language/parse.y"
-    {(yyval.val)=newintnode(&(yylsp[(1) - (1)]));}
+    {(yyval.val)=newconst(CSTreal,&(yyloc));;}
     break;
 
   case 23:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 118 "../src/language/parse.y"
-    {(yyval.val)=newconst(CSTreal,&(yyloc));}
+    {(yyval.val)=newconst(CSTreal,&(yyloc));;}
     break;
 
   case 24:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 119 "../src/language/parse.y"
-    {(yyval.val)=newconst(CSTreal,&(yyloc));}
+    {(yyval.val)=newnode(Ffunction,newconst(CSTmember,&(yylsp[(3) - (3)])),
+                                                newintnode(&(yylsp[(1) - (3)])),&(yyloc));;}
     break;
 
   case 25:
 
-/* Line 1806 of yacc.c  */
-#line 120 "../src/language/parse.y"
-    {(yyval.val)=newnode(Ffunction,newconst(CSTmember,&(yylsp[(3) - (3)])),
-                                                newintnode(&(yylsp[(1) - (3)])),&(yyloc));}
+/* Line 1464 of yacc.c  */
+#line 121 "../src/language/parse.y"
+    {(yyval.val)=newconst(CSTstr,&(yyloc));;}
     break;
 
   case 26:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 122 "../src/language/parse.y"
-    {(yyval.val)=newconst(CSTstr,&(yyloc));}
+    {(yyval.val)=newconst(CSTquote,&(yyloc));;}
     break;
 
   case 27:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 123 "../src/language/parse.y"
-    {(yyval.val)=newconst(CSTquote,&(yyloc));}
+    {(yyval.val)=(yyvsp[(1) - (1)].val);;}
     break;
 
   case 28:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 124 "../src/language/parse.y"
-    {(yyval.val)=(yyvsp[(1) - (1)].val);}
+    {(yyval.val)=newnode(Fcall,(yyvsp[(1) - (4)].val),(yyvsp[(3) - (4)].val),&(yyloc));;}
     break;
 
   case 29:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 125 "../src/language/parse.y"
-    {(yyval.val)=newnode(Fcall,(yyvsp[(1) - (4)].val),(yyvsp[(3) - (4)].val),&(yyloc));}
+    {(yyval.val)=(yyvsp[(1) - (1)].val);;}
     break;
 
   case 30:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 126 "../src/language/parse.y"
-    {(yyval.val)=(yyvsp[(1) - (1)].val);}
+    {(yyval.val)=(yyvsp[(1) - (1)].val);;}
     break;
 
   case 31:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 127 "../src/language/parse.y"
-    {(yyval.val)=(yyvsp[(1) - (1)].val);}
+    {(yyval.val)=(yyvsp[(1) - (1)].val);;}
     break;
 
   case 32:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 128 "../src/language/parse.y"
-    {(yyval.val)=(yyvsp[(1) - (1)].val);}
+    {(yyval.val)=(yyvsp[(1) - (1)].val);;}
     break;
 
   case 33:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 129 "../src/language/parse.y"
-    {(yyval.val)=(yyvsp[(1) - (1)].val);}
+    {(yyval.val)=(yyvsp[(1) - (1)].val);;}
     break;
 
   case 34:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 130 "../src/language/parse.y"
-    {(yyval.val)=(yyvsp[(1) - (1)].val);}
+    {(yyval.val)=newnode(Fassign,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 35:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 131 "../src/language/parse.y"
-    {(yyval.val)=newnode(Fassign,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newnode(Fassign,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 36:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 132 "../src/language/parse.y"
-    {(yyval.val)=newnode(Fassign,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPpp,(yyvsp[(1) - (2)].val),-1,&(yyloc));;}
     break;
 
   case 37:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 133 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPpp,(yyvsp[(1) - (2)].val),-1,&(yyloc));}
+    {(yyval.val)=newopcall(OPss,(yyvsp[(1) - (2)].val),-1,&(yyloc));;}
     break;
 
   case 38:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 134 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPss,(yyvsp[(1) - (2)].val),-1,&(yyloc));}
+    {(yyval.val)=newopcall(OPme,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 39:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 135 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPme,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPde,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 40:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 136 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPde,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPdre,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 41:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 137 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPdre,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPeuce,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 42:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 138 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPeuce,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPmode,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 43:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 139 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPmode,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPsle,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 44:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 140 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPsle,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPsre,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 45:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 141 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPsre,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPpe,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 46:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 142 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPpe,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPse,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 47:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 143 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPse,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPnb,(yyvsp[(2) - (2)].val),-1,&(yyloc));;}
     break;
 
   case 48:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 144 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPnb,(yyvsp[(2) - (2)].val),-1,&(yyloc));}
+    {(yyval.val)=newopcall(OPlength,(yyvsp[(2) - (2)].val),-1,&(yyloc));;}
     break;
 
   case 49:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 145 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPlength,(yyvsp[(2) - (2)].val),-1,&(yyloc));}
+    {(yyval.val)=newopcall(OPor,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 50:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 146 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPor,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPand,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 51:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 147 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPand,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPand,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 52:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 148 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPand,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPid,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 53:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 149 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPid,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPeq,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 54:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 150 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPeq,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPne,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 55:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 151 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPne,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPge,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 56:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 152 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPge,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPg,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 57:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 153 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPg,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPle,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 58:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 154 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPle,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPl,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 59:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 155 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPl,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPs,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 60:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 156 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPs,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPp,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 61:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 157 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPp,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPsl,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 62:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 158 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPsl,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPsr,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 63:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 159 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPsr,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPmod,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 64:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 160 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPmod,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPdr,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 65:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 161 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPdr,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPeuc,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 66:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 162 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPeuc,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPd,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 67:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 163 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPd,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPm,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 68:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 164 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPm,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=(yyvsp[(2) - (2)].val);;}
     break;
 
   case 69:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 165 "../src/language/parse.y"
-    {(yyval.val)=(yyvsp[(2) - (2)].val);}
+    {(yyval.val)=newopcall(OPn,(yyvsp[(2) - (2)].val),-1,&(yyloc));;}
     break;
 
   case 70:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 166 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPn,(yyvsp[(2) - (2)].val),-1,&(yyloc));}
+    {(yyval.val)=newopcall(OPpow,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 71:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 167 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPpow,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPtrans,(yyvsp[(1) - (2)].val),-1,&(yyloc));;}
     break;
 
   case 72:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 168 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPtrans,(yyvsp[(1) - (2)].val),-1,&(yyloc));}
+    {(yyval.val)=newopcall(OPderiv,(yyvsp[(1) - (2)].val),-1,&(yyloc));;}
     break;
 
   case 73:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 169 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPderiv,(yyvsp[(1) - (2)].val),-1,&(yyloc));}
+    {(yyval.val)=newopcall(OPfact,(yyvsp[(1) - (2)].val),-1,&(yyloc));;}
     break;
 
   case 74:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 170 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPfact,(yyvsp[(1) - (2)].val),-1,&(yyloc));}
+    {(yyval.val)=newnode(Fmatcoeff,(yyvsp[(1) - (2)].val),(yyvsp[(2) - (2)].val),&(yyloc));;}
     break;
 
   case 75:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 171 "../src/language/parse.y"
-    {(yyval.val)=newnode(Fmatcoeff,(yyvsp[(1) - (2)].val),(yyvsp[(2) - (2)].val),&(yyloc));}
+    {(yyval.val)=(yyvsp[(1) - (1)].val);;}
     break;
 
   case 76:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 172 "../src/language/parse.y"
-    {(yyval.val)=(yyvsp[(1) - (1)].val);}
+    {(yyval.val)=newnode(Ftag,(yyvsp[(1) - (3)].val),0,&(yyloc));;}
     break;
 
   case 77:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 173 "../src/language/parse.y"
-    {(yyval.val)=newnode(Ftag,(yyvsp[(1) - (3)].val),0,&(yyloc));}
+    {(yyval.val)=(yyvsp[(2) - (3)].val);;}
     break;
 
   case 78:
 
-/* Line 1806 of yacc.c  */
-#line 174 "../src/language/parse.y"
-    {(yyval.val)=(yyvsp[(2) - (3)].val);}
+/* Line 1464 of yacc.c  */
+#line 176 "../src/language/parse.y"
+    {(yyval.val)=newnode(Fentry,newconst(CSTentry,&(yylsp[(1) - (1)])),-1,&(yyloc));;}
     break;
 
   case 79:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 177 "../src/language/parse.y"
-    {(yyval.val)=newnode(Fentry,newconst(CSTentry,&(yylsp[(1) - (1)])),-1,&(yyloc));}
+    {(yyval.val)=newnode(Fmatcoeff,(yyvsp[(1) - (2)].val),(yyvsp[(2) - (2)].val),&(yyloc));;}
     break;
 
   case 80:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 178 "../src/language/parse.y"
-    {(yyval.val)=newnode(Fmatcoeff,(yyvsp[(1) - (2)].val),(yyvsp[(2) - (2)].val),&(yyloc));}
+    {(yyval.val)=newnode(Ftag,(yyvsp[(1) - (3)].val),newconst(CSTentry,&(yylsp[(2) - (3)])),&(yyloc));;}
     break;
 
   case 81:
 
-/* Line 1806 of yacc.c  */
-#line 179 "../src/language/parse.y"
-    {(yyval.val)=newnode(Ftag,(yyvsp[(1) - (3)].val),newconst(CSTentry,&(yylsp[(2) - (3)])),&(yyloc));}
+/* Line 1464 of yacc.c  */
+#line 181 "../src/language/parse.y"
+    {(yyval.val)=(yyvsp[(1) - (1)].val);;}
     break;
 
   case 82:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 182 "../src/language/parse.y"
-    {(yyval.val)=(yyvsp[(1) - (1)].val);}
+    {(yyval.val)=newnode(Fmatrixelts,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 83:
 
-/* Line 1806 of yacc.c  */
-#line 183 "../src/language/parse.y"
-    {(yyval.val)=newnode(Fmatrixelts,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+/* Line 1464 of yacc.c  */
+#line 185 "../src/language/parse.y"
+    {(yyval.val)=newnode(Fmatrixlines,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 84:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 186 "../src/language/parse.y"
-    {(yyval.val)=newnode(Fmatrixlines,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newnode(Fmatrixlines,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 85:
 
-/* Line 1806 of yacc.c  */
-#line 187 "../src/language/parse.y"
-    {(yyval.val)=newnode(Fmatrixlines,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+/* Line 1464 of yacc.c  */
+#line 189 "../src/language/parse.y"
+    {(yyval.val)=newnode(Fvec,-1,-1,&(yyloc));;}
     break;
 
   case 86:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 190 "../src/language/parse.y"
-    {(yyval.val)=newnode(Fvec,-1,-1,&(yyloc));}
+    {(yyval.val)=newopcall(OPrange,(yyvsp[(2) - (5)].val),(yyvsp[(4) - (5)].val),&(yyloc));;}
     break;
 
   case 87:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 191 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPrange,(yyvsp[(2) - (5)].val),(yyvsp[(4) - (5)].val),&(yyloc));}
+    {(yyval.val)=newnode(Fmat,-1,-1,&(yyloc));;}
     break;
 
   case 88:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 192 "../src/language/parse.y"
-    {(yyval.val)=newnode(Fmat,-1,-1,&(yyloc));}
+    {(yyval.val)=newnode(Fvec,(yyvsp[(2) - (3)].val),-1,&(yyloc));;}
     break;
 
   case 89:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 193 "../src/language/parse.y"
-    {(yyval.val)=newnode(Fvec,(yyvsp[(2) - (3)].val),-1,&(yyloc));}
+    {(yyval.val)=newnode(Fmat,(yyvsp[(2) - (3)].val),-1,&(yyloc));;}
     break;
 
   case 90:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 194 "../src/language/parse.y"
-    {(yyval.val)=newnode(Fmat,(yyvsp[(2) - (3)].val),-1,&(yyloc));}
+    {(yyval.val)=-1; YYABORT;;}
     break;
 
   case 91:
 
-/* Line 1806 of yacc.c  */
-#line 195 "../src/language/parse.y"
-    {(yyval.val)=-1; YYABORT;}
+/* Line 1464 of yacc.c  */
+#line 197 "../src/language/parse.y"
+    {(yyval.val)=newnode(Flistarg,(yyvsp[(4) - (4)].val),(yyvsp[(1) - (4)].val),&(yyloc));;}
     break;
 
   case 92:
 
-/* Line 1806 of yacc.c  */
-#line 198 "../src/language/parse.y"
-    {(yyval.val)=newnode(Flistarg,(yyvsp[(4) - (4)].val),(yyvsp[(1) - (4)].val),&(yyloc));}
+/* Line 1464 of yacc.c  */
+#line 200 "../src/language/parse.y"
+    {(yyval.val)=newopcall(OPcompr,(yyvsp[(1) - (1)].val),-2,&(yyloc));;}
     break;
 
   case 93:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 201 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPcompr,(yyvsp[(1) - (1)].val),-2,&(yyloc));}
+    {(yyval.val)=newopcall3(OPcompr,(yyvsp[(1) - (3)].val),-2,(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 94:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 202 "../src/language/parse.y"
-    {(yyval.val)=newopcall3(OPcompr,(yyvsp[(1) - (3)].val),-2,(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall(OPcomprc,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 95:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 203 "../src/language/parse.y"
-    {(yyval.val)=newopcall(OPcomprc,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newopcall3(OPcomprc,(yyvsp[(1) - (5)].val),(yyvsp[(5) - (5)].val),(yyvsp[(3) - (5)].val),&(yyloc));;}
     break;
 
   case 96:
 
-/* Line 1806 of yacc.c  */
-#line 204 "../src/language/parse.y"
-    {(yyval.val)=newopcall3(OPcomprc,(yyvsp[(1) - (5)].val),(yyvsp[(5) - (5)].val),(yyvsp[(3) - (5)].val),&(yyloc));}
+/* Line 1464 of yacc.c  */
+#line 206 "../src/language/parse.y"
+    {(yyval.val)=addcurrexpr((yyvsp[(4) - (5)].val),(yyvsp[(2) - (5)].val),&(yyloc));;}
     break;
 
   case 97:
 
-/* Line 1806 of yacc.c  */
-#line 207 "../src/language/parse.y"
-    {(yyval.val)=addcurrexpr((yyvsp[(4) - (5)].val),(yyvsp[(2) - (5)].val),&(yyloc));}
+/* Line 1464 of yacc.c  */
+#line 209 "../src/language/parse.y"
+    {(yyval.val)=(yyvsp[(1) - (1)].val);;}
     break;
 
   case 98:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 210 "../src/language/parse.y"
-    {(yyval.val)=(yyvsp[(1) - (1)].val);}
+    {(yyval.val)=newnode(Fvararg,(yyvsp[(1) - (4)].val),-1,&(yyloc));;}
     break;
 
   case 99:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 211 "../src/language/parse.y"
-    {(yyval.val)=newnode(Frefarg,(yyvsp[(2) - (2)].val),-1,&(yyloc));}
+    {(yyval.val)=newnode(Frefarg,(yyvsp[(2) - (2)].val),-1,&(yyloc));;}
     break;
 
   case 100:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 212 "../src/language/parse.y"
-    {if (!pari_once) { yyerrok; } pari_once=1;}
+    {if (!pari_once) { yyerrok; } pari_once=1;;}
     break;
 
   case 101:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 213 "../src/language/parse.y"
-    {pari_once=0; (yyval.val)=newopcall(OPcat,(yyvsp[(1) - (4)].val),(yyvsp[(4) - (4)].val),&(yyloc));}
+    {pari_once=0; (yyval.val)=newopcall(OPcat,(yyvsp[(1) - (4)].val),(yyvsp[(4) - (4)].val),&(yyloc));;}
     break;
 
   case 102:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 216 "../src/language/parse.y"
-    {(yyval.val)=(yyvsp[(1) - (1)].val);}
+    {(yyval.val)=(yyvsp[(1) - (1)].val);;}
     break;
 
   case 103:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 217 "../src/language/parse.y"
-    {(yyval.val)=newnode(Flistarg,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newnode(Flistarg,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 104:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 220 "../src/language/parse.y"
-    {(yyval.val)=newnode(Ffunction,newconst(CSTentry,&(yylsp[(1) - (4)])),(yyvsp[(3) - (4)].val),&(yyloc));}
+    {(yyval.val)=newnode(Ffunction,newconst(CSTentry,&(yylsp[(1) - (4)])),(yyvsp[(3) - (4)].val),&(yyloc));;}
     break;
 
   case 105:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 223 "../src/language/parse.y"
-    {(yyval.val)=newnode(Ffunction,newconst(CSTmember,&(yylsp[(3) - (3)])),(yyvsp[(1) - (3)].val),&(yyloc));}
+    {(yyval.val)=newnode(Ffunction,newconst(CSTmember,&(yylsp[(3) - (3)])),(yyvsp[(1) - (3)].val),&(yyloc));;}
     break;
 
   case 106:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 227 "../src/language/parse.y"
-    {(yyval.val)=newfunc(CSTentry,&(yylsp[(1) - (6)]),(yyvsp[(3) - (6)].val),(yyvsp[(6) - (6)].val),&(yyloc));}
+    {(yyval.val)=newfunc(CSTentry,&(yylsp[(1) - (6)]),(yyvsp[(3) - (6)].val),(yyvsp[(6) - (6)].val),&(yyloc));;}
     break;
 
   case 107:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 229 "../src/language/parse.y"
-    {(yyval.val)=newfunc(CSTmember,&(yylsp[(3) - (5)]),(yyvsp[(1) - (5)].val),(yyvsp[(5) - (5)].val),&(yyloc));}
+    {(yyval.val)=newfunc(CSTmember,&(yylsp[(3) - (5)]),(yyvsp[(1) - (5)].val),(yyvsp[(5) - (5)].val),&(yyloc));;}
     break;
 
   case 108:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 230 "../src/language/parse.y"
-    {(yyval.val)=newnode(Flambda, (yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));}
+    {(yyval.val)=newnode(Flambda, (yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;}
     break;
 
   case 109:
 
-/* Line 1806 of yacc.c  */
+/* Line 1464 of yacc.c  */
 #line 231 "../src/language/parse.y"
-    {(yyval.val)=newnode(Flambda, (yyvsp[(2) - (4)].val),(yyvsp[(4) - (4)].val),&(yyloc));}
+    {(yyval.val)=newnode(Flambda, (yyvsp[(2) - (4)].val),(yyvsp[(4) - (4)].val),&(yyloc));;}
     break;
 
 
 
-/* Line 1806 of yacc.c  */
-#line 2664 "../src/language/parse.c"
+/* Line 1464 of yacc.c  */
+#line 2644 "../src/language/parse.c"
       default: break;
     }
-  /* User semantic actions sometimes alter yychar, and that requires
-     that yytoken be updated with the new translation.  We take the
-     approach of translating immediately before every use of yytoken.
-     One alternative is translating here after every semantic action,
-     but that translation would be missed if the semantic action invokes
-     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
-     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
-     incorrect destructor might then be invoked immediately.  In the
-     case of YYERROR or YYBACKUP, subsequent parser actions might lead
-     to an incorrect destructor call or verbose syntax error message
-     before the lookahead is translated.  */
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
 
   YYPOPSTACK (yylen);
@@ -2702,10 +2671,6 @@ yyreduce:
 | yyerrlab -- here on detecting error |
 `------------------------------------*/
 yyerrlab:
-  /* Make sure we have latest lookahead translation.  See comments at
-     user semantic actions for why this is necessary.  */
-  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
-
   /* If not already recovering from an error, report this error.  */
   if (!yyerrstatus)
     {
@@ -2713,36 +2678,37 @@ yyerrlab:
 #if ! YYERROR_VERBOSE
       yyerror (&yylloc, lex, YY_("syntax error"));
 #else
-# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
-                                        yyssp, yytoken)
       {
-        char const *yymsgp = YY_("syntax error");
-        int yysyntax_error_status;
-        yysyntax_error_status = YYSYNTAX_ERROR;
-        if (yysyntax_error_status == 0)
-          yymsgp = yymsg;
-        else if (yysyntax_error_status == 1)
-          {
-            if (yymsg != yymsgbuf)
-              YYSTACK_FREE (yymsg);
-            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
-            if (!yymsg)
-              {
-                yymsg = yymsgbuf;
-                yymsg_alloc = sizeof yymsgbuf;
-                yysyntax_error_status = 2;
-              }
-            else
-              {
-                yysyntax_error_status = YYSYNTAX_ERROR;
-                yymsgp = yymsg;
-              }
-          }
-        yyerror (&yylloc, lex, yymsgp);
-        if (yysyntax_error_status == 2)
-          goto yyexhaustedlab;
+	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+	  {
+	    YYSIZE_T yyalloc = 2 * yysize;
+	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+	      yyalloc = YYSTACK_ALLOC_MAXIMUM;
+	    if (yymsg != yymsgbuf)
+	      YYSTACK_FREE (yymsg);
+	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+	    if (yymsg)
+	      yymsg_alloc = yyalloc;
+	    else
+	      {
+		yymsg = yymsgbuf;
+		yymsg_alloc = sizeof yymsgbuf;
+	      }
+	  }
+
+	if (0 < yysize && yysize <= yymsg_alloc)
+	  {
+	    (void) yysyntax_error (yymsg, yystate, yychar);
+	    yyerror (&yylloc, lex, yymsg);
+	  }
+	else
+	  {
+	    yyerror (&yylloc, lex, YY_("syntax error"));
+	    if (yysize != 0)
+	      goto yyexhaustedlab;
+	  }
       }
-# undef YYSYNTAX_ERROR
 #endif
     }
 
@@ -2802,7 +2768,7 @@ yyerrlab1:
   for (;;)
     {
       yyn = yypact[yystate];
-      if (!yypact_value_is_default (yyn))
+      if (yyn != YYPACT_NINF)
 	{
 	  yyn += YYTERROR;
 	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
@@ -2866,13 +2832,8 @@ yyexhaustedlab:
 
 yyreturn:
   if (yychar != YYEMPTY)
-    {
-      /* Make sure we have latest lookahead translation.  See comments at
-         user semantic actions for why this is necessary.  */
-      yytoken = YYTRANSLATE (yychar);
-      yydestruct ("Cleanup: discarding lookahead",
-                  yytoken, &yylval, &yylloc, lex);
-    }
+     yydestruct ("Cleanup: discarding lookahead",
+		 yytoken, &yylval, &yylloc, lex);
   /* Do not reclaim the symbols of the rule which action triggered
      this YYABORT or YYACCEPT.  */
   YYPOPSTACK (yylen);
@@ -2897,7 +2858,7 @@ yyreturn:
 
 
 
-/* Line 2067 of yacc.c  */
+/* Line 1684 of yacc.c  */
 #line 234 "../src/language/parse.y"
 
 
diff --git a/src/language/parse.h b/src/language/parse.h
index 5ca9868..94b38d2 100644
--- a/src/language/parse.h
+++ b/src/language/parse.h
@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 2.5.  */
+/* A Bison parser, made by GNU Bison 2.4.3.  */
 
-/* Bison interface for Yacc-like parsers in C
+/* Skeleton interface for Bison's Yacc-like parsers in C
    
-      Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2009, 2010 Free Software Foundation, Inc.
    
    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
diff --git a/src/language/parse.y b/src/language/parse.y
index cd77f20..cbd3748 100644
--- a/src/language/parse.y
+++ b/src/language/parse.y
@@ -72,7 +72,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 %left "++" "--"
 %left '('
 %left ':'
-%type <val> seq sequnused
+%type <val> seq sequence
 %type <val> range matrix matrix_index expr
 %type <val> lvalue
 %type <val> matrixelts matrixlines arg listarg definition
@@ -82,8 +82,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 %destructor { pari_discarded++; } seq matrix range matrix_index expr lvalue matrixelts matrixlines arg listarg definition funcid memberid backticks history compr in inseq
 %%
 
-sequnused: seq       {$$=$1;}
-         | seq error {$$=$1; pari_unused_chars=@1.end;YYABORT;}
+sequence: seq        {$$=$1;} /* skip the destructor */
 ;
 
 seq: /**/ %prec SEQ  {$$=NOARG(@$);}
@@ -208,6 +207,7 @@ compr: '[' expr '|' inseq ']' {$$=addcurrexpr($4,$2,&@$);}
 ;
 
 arg: seq        {$$=$1;}
+   | lvalue '[' ".." ']' {$$=newnode(Fvararg,$1,-1,&@$);}
    | '&' lvalue {$$=newnode(Frefarg,$2,-1,&@$);}
    | arg error  {if (!pari_once) { yyerrok; } pari_once=1;}  expr
                      {pari_once=0; $$=newopcall(OPcat,$1,$4,&@$);}
diff --git a/src/language/parsec.h b/src/language/parsec.h
index d21dcdc..7a19e2c 100644
--- a/src/language/parsec.h
+++ b/src/language/parsec.h
@@ -21,7 +21,7 @@ ENDEXTERN
 
 static THREAD int pari_once;
 static THREAD long pari_discarded;
-static THREAD const char *pari_lex_start, *pari_unused_chars;
+static THREAD const char *pari_lex_start;
 static THREAD GEN pari_lasterror;
 
 static void pari_error(YYLTYPE *yylloc, char **lex, const char *s)
@@ -56,17 +56,6 @@ pari_init_parser(void)
 void
 pari_close_parser(void) { pari_stack_delete(&s_node); }
 
-static void
-unused_chars(const char *lex, int strict)
-{
-  long n = 2 * term_width() - (17+19+1); /* Warning + unused... + . */
-  if (strict) compile_err("unused characters", lex);
-  if ((long)strlen(lex) > n) /* at most 2 lines */
-    pari_warn(warner, "unused characters: %.*s[+++]", n-5, lex);
-  else
-    pari_warn(warner, "unused characters: %s", lex);
-}
-
 void
 compile_err(const char *msg, const char *str)
 {
@@ -84,7 +73,6 @@ parsestate_reset(void)
 {
   s_node.n = OPnboperator;
   pari_lex_start = NULL;
-  pari_unused_chars=NULL;
   pari_once=1;
   pari_discarded=0;
   pari_lasterror=NULL;
@@ -94,7 +82,6 @@ parsestate_save(struct pari_parsestate *state)
 {
   state->node = s_node.n;
   state->lex_start = pari_lex_start;
-  state->unused_chars = pari_unused_chars;
   state->once = pari_once;
   state->discarded = pari_discarded;
   state->lasterror = pari_lasterror;
@@ -104,29 +91,25 @@ parsestate_restore(struct pari_parsestate *state)
 {
   s_node.n = state->node;
   pari_lex_start = state->lex_start;
-  pari_unused_chars = state->unused_chars;
   pari_once = state->once;
   pari_discarded = state->discarded;
   pari_lasterror = state->lasterror;
 }
 
 GEN
-pari_compile_str(char *lex, int strict)
+pari_compile_str(const char *lex)
 {
   pari_sp ltop=avma;
   GEN code;
   struct pari_parsestate state;
   parsestate_save(&state);
   pari_lex_start = lex;
-  pari_unused_chars=NULL;
   pari_once=1;
   pari_discarded=0;
   pari_lasterror=NULL;
-  if (pari_parse(&lex) || pari_discarded)
+  if (pari_parse((char**)&lex) || pari_discarded)
   {
-    if (pari_unused_chars && !pari_discarded)
-      unused_chars(pari_unused_chars,strict);
-    else if (pari_lasterror)
+    if (pari_lasterror)
       compile_err(GSTR(pari_lasterror),lex-1);
     else /* should not happen */
       compile_err("syntax error",lex-1);
diff --git a/src/language/sumiter.c b/src/language/sumiter.c
index c03134f..0b39f9d 100644
--- a/src/language/sumiter.c
+++ b/src/language/sumiter.c
@@ -54,12 +54,12 @@ iferrpari(GEN a, GEN b, GEN c)
 static void
 forparii(GEN a, GEN b, GEN code)
 {
-  pari_sp av, av0 = avma, lim;
+  pari_sp av, av0 = avma;
   GEN aa;
   if (gcmp(b,a) < 0) return;
   b = gfloor(b);
   aa = a = setloop(a);
-  av=avma; lim = stack_lim(av,1);
+  av=avma;
   push_lex(a,code);
   while (gcmp(a,b) <= 0)
   {
@@ -73,7 +73,7 @@ forparii(GEN a, GEN b, GEN code)
     else
     { /* 'code' modified a ! Be careful (and slow) from now on */
       a = gaddgs(a,1);
-      if (low_stack(lim, stack_lim(av,1)))
+      if (gc_needed(av,1))
       {
         if (DEBUGMEM>1) pari_warn(warnmem,"forparii");
         a = gerepileupto(av,a);
@@ -87,16 +87,16 @@ forparii(GEN a, GEN b, GEN code)
 void
 forpari(GEN a, GEN b, GEN code)
 {
-  pari_sp ltop=avma, av, lim;
+  pari_sp ltop=avma, av;
   if (typ(a) == t_INT) { forparii(a,b,code); return; }
   b = gcopy(b); /* Kludge to work-around the a+(a=2) bug */
-  av=avma; lim = stack_lim(av,1);
+  av=avma;
   push_lex(a,code);
   while (gcmp(a,b) <= 0)
   {
     closure_evalvoid(code); if (loop_break()) break;
     a = get_lex(-1); a = gaddgs(a,1);
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"forpari");
       a = gerepileupto(av,a);
@@ -141,11 +141,11 @@ void
 forstep(GEN a, GEN b, GEN s, GEN code)
 {
   long ss, i;
-  pari_sp av, av0 = avma, lim;
+  pari_sp av, av0 = avma;
   GEN v = NULL;
   int (*cmp)(GEN,GEN);
 
-  b = gcopy(b); av=avma; lim = stack_lim(av,1);
+  b = gcopy(b); av=avma;
   push_lex(a,code);
   if (is_vec_t(typ(s)))
   {
@@ -166,7 +166,7 @@ forstep(GEN a, GEN b, GEN s, GEN code)
     }
     a = get_lex(-1); a = gadd(a,s);
 
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"forstep");
       a = gerepileupto(av,a);
@@ -332,7 +332,7 @@ forprime_init(forprime_t *T, GEN a, GEN b)
   T->pp = cgeti(lb);
   /* a, b are positive integers, a <= b */
   if (lgefint(a) == 3) /* lb == 3 implies b != NULL */
-    return u_forprime_init(T, a[2], lb == 3? (ulong)b[2]: ULONG_MAX);
+    return u_forprime_init(T, uel(a,2), lb == 3? uel(b,2): ULONG_MAX);
   T->strategy = 4;
   affii(subiu(a,1), T->pp);
   return 1;
@@ -653,13 +653,13 @@ _next_le_i(forvec_t *d)
     if (cmpii(d->a[i], d->M[i]) < 0)
     {
       d->a[i] = incloop(d->a[i]);
-      /* m[i] < a[i] <= M[i] < M[i+1] */
+      /* m[i] < a[i] <= M[i] <= M[i+1] */
       while (i < d->n)
       {
         GEN t;
         i++;
         if (cmpii(d->a[i-1], d->a[i]) <= 0) continue;
-        /* a[i-1] <= M[i-1] <= M[i] */
+        /* a[i] < a[i-1] <= M[i-1] <= M[i] */
         t = d->a[i-1]; if (cmpii(t, d->m[i]) < 0) t = d->m[i];
         d->a[i] = resetloop(d->a[i], t);/*a[i]:=max(a[i-1],m[i])*/
       }
@@ -673,7 +673,7 @@ _next_le_i(forvec_t *d)
 static GEN
 _next_le(forvec_t *d)
 {
-  long i = d->n, imin = d->n;
+  long i = d->n;
   if (d->first) { d->first = 0; return (GEN)d->a; }
   for (;;) {
     d->a[i] = gaddgs(d->a[i], 1);
@@ -681,25 +681,18 @@ _next_le(forvec_t *d)
     {
       while (i < d->n)
       {
+        GEN c;
         i++;
         if (gcmp(d->a[i-1], d->a[i]) <= 0) continue;
-        while (gcmp(d->a[i-1], d->M[i]) > 0)
-        {
-          i = imin - 1; if (!i) return NULL;
-          imin = i;
-          d->a[i] = gaddgs(d->a[i], 1);
-          if (gcmp(d->a[i], d->M[i]) <= 0) break;
-        }
-        if (i > 1) { /* a >= a[i-1] - a[i] */
-          GEN a = gceil(gsub(d->a[i-1], d->a[i]));
-          d->a[i] = gadd(d->a[i], a);
-        }
+        /* M[i] >= M[i-1] >= a[i-1] > a[i] */
+        c = gceil(gsub(d->a[i-1], d->a[i]));
+        d->a[i] = gadd(d->a[i], c);
+        /* a[i-1] <= a[i] < M[i-1] + 1 => a[i] < M[i]+1 => a[i] <= M[i] */
       }
       return (GEN)d->a;
     }
     d->a[i] = d->m[i];
     if (--i <= 0) return NULL;
-    if (i < imin) imin = i;
   }
 }
 /* strictly increasing order [over integers] */
@@ -720,7 +713,7 @@ _next_lt_i(forvec_t *d)
         i++;
         if (cmpii(d->a[i-1], d->a[i]) < 0) continue;
         av = avma;
-        /* a[i-1] <= M[i-1] < M[i] */
+        /* M[i] > M[i-1] >= a[i-1] */
         t = addis(d->a[i-1],1); if (cmpii(t, d->m[i]) < 0) t = d->m[i];
         d->a[i] = resetloop(d->a[i], t);/*a[i]:=max(a[i-1]+1,m[i]) <= M[i]*/
         avma = av;
@@ -735,7 +728,7 @@ _next_lt_i(forvec_t *d)
 static GEN
 _next_lt(forvec_t *d)
 {
-  long i = d->n, imin = d->n;
+  long i = d->n;
   if (d->first) { d->first = 0; return (GEN)d->a; }
   for (;;) {
     d->a[i] = gaddgs(d->a[i], 1);
@@ -743,28 +736,18 @@ _next_lt(forvec_t *d)
     {
       while (i < d->n)
       {
+        GEN c;
         i++;
         if (gcmp(d->a[i-1], d->a[i]) < 0) continue;
-        for(;;)
-        {
-          GEN a, b;
-          a = addis(gfloor(gsub(d->a[i-1], d->a[i])), 1); /* a> v[i-1]-v[i] */
-          b = gadd(d->a[i], a);
-          /* v[i-1] < b <= v[i-1] + 1 */
-          if (gcmp(b, d->M[i]) <= 0) { d->a[i] = b; break; }
-
-          for (; i >= imin; i--) d->a[i] = d->m[i];
-          if (!i) return NULL;
-          imin = i;
-          d->a[i] = gaddgs(d->a[i], 1);
-          if (gcmp(d->a[i], d->M[i]) <= 0) break;
-        }
+        /* M[i] > M[i-1] >= a[i-1] >= a[i] */
+        c = addis(gfloor(gsub(d->a[i-1], d->a[i])), 1); /* > a[i-1] - a[i] */
+        d->a[i] = gadd(d->a[i], c);
+        /* a[i-1] < a[i] <= M[i-1] + 1 => a[i] < M[i]+1 => a[i] <= M[i] */
       }
       return (GEN)d->a;
     }
     d->a[i] = d->m[i];
     if (--i <= 0) return NULL;
-    if (i < imin) imin = i;
   }
 }
 /* for forvec(v=[],) */
@@ -775,9 +758,10 @@ _next_void(forvec_t *d)
   return NULL;
 }
 
-/* Initialize minima (m) and maxima (M); guarantee
+/* Initialize minima (m) and maxima (M); guarantee M[i] - m[i] integer and
  *   if flag = 1: m[i-1] <= m[i] <= M[i] <= M[i+1]
- *   if flag = 2: m[i-1] <  m[i] <= M[i] <  M[i+1] */
+ *   if flag = 2: m[i-1] <  m[i] <= M[i] <  M[i+1],
+ * for all i */
 int
 forvec_init(forvec_t *d, GEN x, long flag)
 {
@@ -812,32 +796,25 @@ forvec_init(forvec_t *d, GEN x, long flag)
       default: m = gcopy(m);
         break;
     }
+    M = gadd(m, gfloor(gsub(M,m))); /* ensure M-m is an integer */
     if (gcmp(m,M) > 0) { d->a = NULL; d->next = &_next; return 0; }
     d->m[i] = m;
     d->M[i] = M;
   }
-  for (i = l-2; i >= 1; i--)
+  if (flag == 1) for (i = l-2; i >= 1; i--)
   {
-    GEN a, M = d->M[i];
-    switch(flag) {
-      case 1:/* a >= M - M[i] */
-        a = gfloor(gsub(d->M[i+1], M));
-        if (typ(a) != t_INT) pari_err_TYPE("forvec",a);
-        if (signe(a) < 0) M = gadd(M, a); else M = gcopy(M);
-        /* M <= M[i+1] */
-        break;
-      case 2:
-        a = gceil(gsub(d->M[i+1], M));
-        if (typ(a) != t_INT) pari_err_TYPE("forvec",a);
-        a = subis(a, 1);
-        if (signe(a) < 0) M = gadd(M, a); else M = gcopy(M);
-        /* M < M[i+1] */
-        break;
-      default:
-        M = gcopy(M);
-        break;
-    }
-    d->M[i] = M;
+    GEN M = d->M[i], a = gfloor(gsub(d->M[i+1], M));
+    if (typ(a) != t_INT) pari_err_TYPE("forvec",a);
+    /* M[i]+a <= M[i+1] */
+    if (signe(a) < 0) d->M[i] = gadd(M, a);
+  }
+  else if (flag == 2) for (i = l-2; i >= 1; i--)
+  {
+    GEN M = d->M[i], a = gceil(gsub(d->M[i+1], M));
+    if (typ(a) != t_INT) pari_err_TYPE("forvec",a);
+    a = subiu(a, 1);
+    /* M[i]+a < M[i+1] */
+    if (signe(a) < 0) d->M[i] = gadd(M, a);
   }
   if (t == t_INT) {
     for (i = 1; i < l; i++) {
@@ -884,7 +861,7 @@ forvec(GEN x, GEN code, long flag)
 GEN
 somme(GEN a, GEN b, GEN code, GEN x)
 {
-  pari_sp av, av0 = avma, lim;
+  pari_sp av, av0 = avma;
   GEN p1;
 
   if (typ(a) != t_INT) pari_err_TYPE("sum",a);
@@ -893,14 +870,14 @@ somme(GEN a, GEN b, GEN code, GEN x)
 
   b = gfloor(b);
   a = setloop(a);
-  av=avma; lim = stack_lim(av,1);
+  av=avma;
   push_lex(a,code);
   for(;;)
   {
     p1 = closure_evalnobrk(code);
     x=gadd(x,p1); if (cmpii(a,b) >= 0) break;
     a = incloop(a);
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"sum");
       x = gerepileupto(av,x);
@@ -914,12 +891,12 @@ GEN
 suminf(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)
 {
   long fl, G;
-  pari_sp av0 = avma, av, lim;
+  pari_sp av0 = avma, av;
   GEN p1,x = real_1(prec);
 
   if (typ(a) != t_INT) pari_err_TYPE("suminf",a);
   a = setloop(a);
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
   fl=0; G = prec2nbits(prec) + 5;
   for(;;)
   {
@@ -928,7 +905,7 @@ suminf(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)
       { if (++fl==3) break; }
     else
       fl=0;
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"suminf");
       x = gerepileupto(av,x);
@@ -989,7 +966,7 @@ sumdivmultexpr(GEN num, GEN code)
 GEN
 produit(GEN a, GEN b, GEN code, GEN x)
 {
-  pari_sp av, av0 = avma, lim;
+  pari_sp av, av0 = avma;
   GEN p1;
 
   if (typ(a) != t_INT) pari_err_TYPE("prod",a);
@@ -998,14 +975,14 @@ produit(GEN a, GEN b, GEN code, GEN x)
 
   b = gfloor(b);
   a = setloop(a);
-  av=avma; lim = stack_lim(av,1);
+  av=avma;
   push_lex(a,code);
   for(;;)
   {
     p1 = closure_evalnobrk(code);
     x = gmul(x,p1); if (cmpii(a,b) >= 0) break;
     a = incloop(a);
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"prod");
       x = gerepileupto(av,x);
@@ -1018,13 +995,13 @@ produit(GEN a, GEN b, GEN code, GEN x)
 GEN
 prodinf(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)
 {
-  pari_sp av0 = avma, av, lim;
+  pari_sp av0 = avma, av;
   long fl,G;
   GEN p1,x = real_1(prec);
 
   if (typ(a) != t_INT) pari_err_TYPE("prodinf",a);
   a = setloop(a);
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
   fl=0; G = -prec2nbits(prec)-5;
   for(;;)
   {
@@ -1032,7 +1009,7 @@ prodinf(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)
     x = gmul(x,p1); a = incloop(a);
     p1 = gsubgs(p1, 1);
     if (gequal0(p1) || gexpo(p1) <= G) { if (++fl==3) break; } else fl=0;
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"prodinf");
       x = gerepileupto(av,x);
@@ -1043,13 +1020,13 @@ prodinf(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)
 GEN
 prodinf1(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)
 {
-  pari_sp av0 = avma, av, lim;
+  pari_sp av0 = avma, av;
   long fl,G;
   GEN p1,p2,x = real_1(prec);
 
   if (typ(a) != t_INT) pari_err_TYPE("prodinf1",a);
   a = setloop(a);
-  av = avma; lim = stack_lim(av,1);
+  av = avma;
   fl=0; G = -prec2nbits(prec)-5;
   for(;;)
   {
@@ -1057,7 +1034,7 @@ prodinf1(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)
     if (gequal0(p1)) { x = p1; break; }
     x = gmul(x,p1); a = incloop(a);
     if (gequal0(p2) || gexpo(p2) <= G) { if (++fl==3) break; } else fl=0;
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"prodinf1");
       x = gerepileupto(av,x);
@@ -1080,7 +1057,7 @@ prodinf0(GEN a, GEN code, long flag, long prec)
 GEN
 prodeuler(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long prec)
 {
-  pari_sp av, av0 = avma, lim;
+  pari_sp av, av0 = avma;
   GEN x = real_1(prec), prime;
   forprime_t T;
 
@@ -1088,11 +1065,10 @@ prodeuler(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long prec)
   if (!forprime_init(&T, a,b)) { avma = av; return x; }
 
   av = avma;
-  lim = stack_lim(avma,1);
   while ( (prime = forprime_next(&T)) )
   {
     x = gmul(x, eval(E, prime));
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"prodeuler");
       x = gerepilecopy(av, x);
@@ -1112,11 +1088,21 @@ GEN
 direuler(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, GEN c)
 {
   ulong i, k, n;
-  pari_sp av0 = avma, av, lim = stack_lim(av0, 1);
+  pari_sp av0 = avma, av;
   long j, tx, lx;
   GEN x, y, s, polnum, polden, prime;
   forprime_t T;
 
+  if (typ(b) != t_INT)
+  {
+    b = gfloor(b);
+    if (typ(b) != t_INT) pari_err_TYPE("direuler",b);
+  }
+  if (typ(a) != t_INT)
+  {
+    a = gceil(a);
+    if (typ(a) != t_INT) pari_err_TYPE("direuler",a);
+  }
   if (c)
   {
     if (typ(c) != t_INT)
@@ -1124,23 +1110,12 @@ direuler(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, GEN c)
       c = gfloor(c);
       if (typ(c) != t_INT) pari_err_TYPE("direuler", c);
     }
-    if (signe(c) <= 0) { avma = av0; return mkvec(gen_1); }
-    n = itou(c);
-    if (cmpui(n, b) < 0) b = c;
+    if (signe(c) <= 0) { avma = av0; return cgetg(1,t_VEC); }
+    if (cmpii(c, b) < 0) b = c;
   }
+  if (lgefint(b) > 3) pari_err_OVERFLOW("direuler");
   if (!forprime_init(&T, a,b)) { avma = av0; return mkvec(gen_1); }
-
-  if (c)
-  {
-    n = itou(c);
-    if (cmpui(n, b) < 0) b = c;
-  }
-  else
-  {
-    if (lgefint(b) > 3) pari_err_OVERFLOW("direuler");
-    n = itou(b);
-  }
-
+  n = itou(b);
   y = cgetg(n+1,t_VEC); av = avma;
   x = zerovec(n); gel(x,1) = gen_1;
   while ( (prime = forprime_next(&T)) )
@@ -1207,7 +1182,7 @@ direuler(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, GEN c)
         gel(x,i) = gsub(gel(x,i),s);
       }
     }
-    if (low_stack(lim, stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"direuler");
       x = gerepilecopy(av, x);
@@ -1228,7 +1203,7 @@ direuler0(GEN a, GEN b, GEN code, GEN c)
 INLINE GEN
 copyupto(GEN z, GEN t)
 {
-  if (is_universal_constant(z) || (z>(GEN)bot && z<=t))
+  if (is_universal_constant(z) || (z>(GEN)pari_mainstack->bot && z<=t))
     return z;
   else
     return gcopy(z);
@@ -1344,97 +1319,103 @@ matrice(GEN nlig, GEN ncol, GEN code)
 /**                         SUMMING SERIES                         **/
 /**                                                                **/
 /********************************************************************/
-GEN
-polzag(long n, long m)
+/* h = (2+2x)g'- g; g has t_INT coeffs */
+static GEN
+delt(GEN g, long n)
 {
-  pari_sp av = avma;
-  long k, d = n - m;
-  GEN A, Bx, g, s;
-
-  if (d <= 0 || m < 0) return gen_0;
-  A  = mkpoln(2, stoi(-2), gen_1); /* 1 - 2x */
-  Bx = mkpoln(3, stoi(-2), gen_2, gen_0); /* 2x - 2x^2 */
-  g = gmul(poleval(ZX_deriv(polchebyshev1(d,0)), A), gpowgs(Bx, (m+1)>>1));
-  for (k = m; k >= 0; k--)
-    g = (k&1)? ZX_deriv(g): gadd(gmul(A,g), gmul(Bx,ZX_deriv(g)));
-  s = mulii(sqru(d), mpfact(m+1));
-  return gerepileupto(av, gdiv(g,s));
+  GEN h = cgetg(n+3,t_POL);
+  long k;
+  h[1] = g[1];
+  gel(h,2) = gel(g,2);
+  for (k=1; k<n; k++)
+    gel(h,k+2) = addii(mului(k+k+1,gel(g,k+2)), mului(k<<1,gel(g,k+1)));
+  gel(h,n+2) = mului(n<<1, gel(g,n+1)); return h;
 }
 
 #ifdef _MSC_VER /* Bill Daly: work around a MSVC bug */
 #pragma optimize("g",off)
 #endif
+/* P = polzagier(n,m)(-X), unnormalized (P(0) != 1) */
 static GEN
-polzagreel(long n, long m, long prec)
+polzag1(long n, long m)
 {
-  const long d = n - m, d2 = d<<1, r = (m+1)>>1;
-  long j, k, k2;
+  const long d = n - m, d2 = d<<1, r = (m+1)>>1, D = (d+1)>>1;
+  long i, k;
   pari_sp av = avma;
-  GEN Bx, g, h, v, b, s;
-
-  if (d <= 0 || m < 0) return gen_0;
-  Bx = mkpoln(3, gen_1, gen_1, gen_0); /* x + x^2 */
-  v = cgetg(d+1,t_VEC);
-  g = cgetg(d+1,t_VEC);
-  gel(v,d) = gen_1; b = stor(d2, prec);
-  gel(g,d) = b;
-  for (k = 1; k < d; k++)
+  GEN g, T;
+
+  if (d <= 0 || m < 0) return pol_0(0);
+  g = cgetg(d+2, t_POL);
+  g[1] = evalsigne(1)|evalvarn(0);
+  T = cgetg(d+1,t_VEC);
+  /* T[k+1] = binomial(2d,2k+1), 0 <= k < d */
+  gel(T,1) = utoipos(d2);
+  for (k = 1; k < D; k++)
+  {
+    long k2 = k<<1;
+    gel(T,k+1) = diviiexact(mulii(gel(T,k), muluu(d2-k2+1, d2-k2)),
+                            muluu(k2,k2+1));
+  }
+  for (; k < d; k++) gel(T,k+1) = gel(T,d-k);
+  gel(g,2) = gel(T,d); /* binomial(2d, 2(d-1)+1) */
+  for (i = 1; i < d; i++)
   {
-    gel(v,d-k) = gen_1;
-    for (j=1; j<k; j++)
-      gel(v,d-k+j) = addii(gel(v,d-k+j), gel(v,d-k+j+1));
-    /* v[d-k+j] = binom(k, j), j = 0..k */
-    k2 = k+k; b = divri(mulri(b,mulss(d2-k2+1,d2-k2)), mulss(k2,k2+1));
-    for (j=1; j<=k; j++)
-      gel(g,d-k+j) = mpadd(gel(g,d-k+j), mulri(b,gel(v,d-k+j)));
-    gel(g,d-k) = b;
-  }
-  g = gmul(RgV_to_RgX(g,0), gpowgs(Bx,r));
-  for (j=0; j<=r; j++)
+    pari_sp av2 = avma;
+    GEN s, t = gel(T,d-i); /* binomial(2d, 2(d-1-i)+1) */
+    s = t;
+    for (k = d-i; k < d; k++)
+    {
+      long k2 = k<<1;
+      t = diviiexact(mulii(t, muluu(d2-k2+1, d-k)), muluu(k2+1,k-(d-i)+1));
+      s = addii(s, t);
+    }
+    /* g_i = sum_{d-1-i <= k < d}, binomial(2*d, 2*k+1)*binomial(k,d-1-i) */
+    gel(g,i+2) = gerepileuptoint(av2, s);
+  }
+  /* sum_{0 <= i < d} g_i x^i * (x+x^2)^r */
+  g = RgX_mulXn(gmul(g, gpowgs(deg1pol(gen_1,gen_1,0),r)), r);
+  if (!odd(m)) g = delt(g, n);
+  for (i=1; i<=r; i++)
   {
-    if (j) g = RgX_deriv(g);
-    if (j || !(m&1))
+    g = delt(ZX_deriv(g), n);
+    if (gc_needed(av,4))
     {
-      h = cgetg(n+3,t_POL);
-      h[1] = evalsigne(1);
-      gel(h,2) = gel(g,2);
-      for (k=1; k<n; k++)
-        gel(h,k+2) = gadd(gmulsg(k+k+1,gel(g,k+2)), gmulsg(k<<1,gel(g,k+1)));
-      gel(h,n+2) = gmulsg(n<<1, gel(g,n+1));
-      g = h;
+      if (DEBUGMEM>1) pari_warn(warnmem,"polzag, i = %ld/%ld", i,r);
+      g = gerepilecopy(av, g);
     }
   }
-  g = gmul2n(g, r-1);
-  s = mului(d, mpfact(m+1));
-  return gerepileupto(av, gdiv(g,s));
+  return g;
+}
+GEN
+polzag(long n, long m)
+{
+  pari_sp av = avma;
+  GEN g = ZX_unscale(polzag1(n,m), gen_m1);
+  return gerepileupto(av, RgX_Rg_div(g,gel(g,2)));
 }
 
-#ifdef _MSC_VER
-#pragma optimize("g",on)
-#endif
 GEN
 sumalt(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)
 {
   ulong k, N;
-  pari_sp av = avma, av2, lim;
-  GEN s, az, c, e1, d;
+  pari_sp av = avma, av2;
+  GEN s, az, c, d;
 
   if (typ(a) != t_INT) pari_err_TYPE("sumalt",a);
-  e1 = addsr(3, sqrtr(stor(8,prec)));
-  N = (ulong)(0.4*(prec2nbits(prec)+ 7));
-  d = powru(e1,N);
+  N = (ulong)(0.39322*(prec2nbits(prec) + 7)); /*0.39322 > 1/log_2(3+sqrt(8))*/
+  d = powru(addsr(3, sqrtr(stor(8,prec))), N);
   d = shiftr(addrr(d, invr(d)),-1);
   a = setloop(a);
   az = gen_m1; c = d;
   s = gen_0;
-  av2 = avma; lim = stack_lim(av,4);
+  av2 = avma;
   for (k=0; ; k++) /* k < N */
   {
     c = addir(az,c); s = gadd(s, gmul(c, eval(E, a)));
     if (k==N-1) break;
     az = diviuuexact(muluui((N-k)<<1,N+k,az), k+1, (k<<1)+1);
     a = incloop(a); /* in place! */
-    if (low_stack(lim, stack_lim(av,4)))
+    if (gc_needed(av,4))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"sumalt, k = %ld/%ld", k,N-1);
       gerepileall(av2, 3, &az,&c,&s);
@@ -1447,23 +1428,23 @@ GEN
 sumalt2(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)
 {
   long k, N;
-  pari_sp av = avma, av2, lim;
+  pari_sp av = avma, av2;
   GEN s, dn, pol;
 
   if (typ(a) != t_INT) pari_err_TYPE("sumalt",a);
-  N = (long)(0.31*(prec2nbits(prec) + 5));
-  pol = polzagreel(N,N>>1,prec+EXTRAPRECWORD);
-  pol = RgX_div_by_X_x(pol, gen_1, &dn);
+  N = (long)(0.307073*(prec2nbits(prec) + 5)); /*0.307073 > 1/log_2(\beta_B)*/
+  pol = ZX_div_by_X_1(polzag1(N,N>>1), &dn);
   a = setloop(a);
   N = degpol(pol);
   s = gen_0;
-  av2 = avma; lim = stack_lim(av,4);
+  av2 = avma;
   for (k=0; k<=N; k++)
   {
-    s = gadd(s, gmul(gel(pol,k+2), eval(E, a)));
+    GEN t = itor(gel(pol,k+2), prec+EXTRAPRECWORD);
+    s = gadd(s, gmul(t, eval(E, a)));
     if (k == N) break;
     a = incloop(a); /* in place! */
-    if (low_stack(lim, stack_lim(av,4)))
+    if (gc_needed(av,4))
     {
       if (DEBUGMEM>1) pari_warn(warnmem,"sumalt2, k = %ld/%ld", k,N-1);
       s = gerepileupto(av2, s);
@@ -1484,49 +1465,80 @@ sumalt0(GEN a, GEN code, long flag, long prec)
   return NULL; /* not reached */
 }
 
+/* For k > 0, set S[k*2^i] <- g(k*2^i), k*2^i <= N = #S.
+ * Only needed with k odd (but also works for g even). */
+static void
+binsum(GEN S, ulong k, void *E, GEN (*f)(void *, GEN), GEN a,
+        long G, long prec)
+{
+  long e, i, N = lg(S)-1, l = expu(N / k); /* k 2^l <= N < k 2^(l+1) */
+  pari_sp av;
+  GEN r, t = gen_0;
+
+  gel(S, k << l) = cgetr(prec); av = avma;
+  G -= l;
+  r = utoipos(k<<l);
+  for(e=0;;e++) /* compute g(k 2^l) with absolute error ~ 2^(G-l) */
+  {
+    GEN u = gtofp(f(E, addii(a,r)), prec);
+    if (typ(u) != t_REAL) pari_err_TYPE("sumpos",u);
+    if (!signe(u)) break;
+    if (!e)
+      t = u;
+    else {
+      shiftr_inplace(u, e);
+      t = addrr(t,u);
+      if (expo(u) < G) break;
+    }
+    r = shifti(r,1);
+  }
+  gel(S, k << l) = t = gerepileuptoleaf(av, t);
+  /* g(j) = 2g(2j) + f(a+j) for all j > 0 */
+  for(i = l-1; i >= 0; i--)
+  { /* t ~ g(2 * k*2^i) with error ~ 2^(G-i-1) */
+    GEN u;
+    av = avma; u = gtofp(f(E, addiu(a, k << i)), prec);
+    if (typ(u) != t_REAL) pari_err_TYPE("sumpos",u);
+    t = addrr(gtofp(u,prec), shiftr(t,1)); /* ~ g(k*2^i) */
+    gel(S, k << i) = t = gerepileuptoleaf(av, t);
+  }
+}
+/* For k > 0, let g(k) := \sum_{e >= 0} 2^e f(a + k*2^e).
+ * Return [g(k), 1 <= k <= N] */
+static GEN
+sumpos_init(void *E, GEN (*f)(void *, GEN), GEN a, long N, long prec)
+{
+  GEN S = cgetg(N+1,t_VEC);
+  long k, G = -prec2nbits(prec) - 5;
+  for (k=1; k<=N; k+=2) binsum(S,k, E,f, a,G,prec);
+  return S;
+}
+
 GEN
 sumpos(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)
 {
-  long k, kk, N, G;
+  ulong k, N;
   pari_sp av = avma;
-  GEN r, reel, s, az, c, x, e1, d, *stock;
+  GEN s, az, c, d, S;
 
   if (typ(a) != t_INT) pari_err_TYPE("sumpos",a);
-  a = subis(a,1); reel = cgetr(prec);
-  e1 = addsr(3, sqrtr(stor(8,prec)));
-  N = (long)(0.4*(prec2nbits(prec) + 7));
-  d = powru(e1,N);
+  a = subiu(a,1);
+  N = (ulong)(0.4*(prec2nbits(prec) + 7));
+  d = powru(addsr(3, sqrtr(stor(8,prec))), N);
   d = shiftr(addrr(d, invr(d)),-1);
   az = gen_m1; c = d;
-  s = gen_0;
 
-  G = -prec2nbits(prec) - 5;
-  stock = (GEN*)new_chunk(N+1); for (k=1; k<=N; k++) stock[k] = NULL;
+  if (odd(N)) N++; /* extra precision for free */
+  S = sumpos_init(E, eval, a, N, prec);
+  s = gen_0;
   for (k=0; k<N; k++)
   {
-    if (odd(k) && stock[k]) x = stock[k];
-    else
-    {
-      pari_sp av2 = avma;
-      x = gen_0; r = utoipos(2*k+2);
-      for(kk=0;;kk++)
-      {
-
-        long ex;
-        affgr(eval(E, addii(r,a)), reel);
-        if (!signe(reel)) break;
-        ex = expo(reel) + kk; shiftr_inplace(reel, kk);
-        x = mpadd(x,reel); if (kk && ex < G) break;
-        r = shifti(r,1);
-      }
-      x = gerepileupto(av2, x);
-      if (2*k < N) stock[2*k+1] = x;
-      affgr(eval(E, addsi(k+1,a)), reel);
-      x = addrr(reel, gmul2n(x,1));
-    }
+    GEN t;
     c = addir(az,c);
-    s = mpadd(s, mulrr(x, k&1? negr(c): c));
-    az = diviiexact(mulii(mulss(N-k,N+k),shifti(az,1)),mulss(k+1,k+k+1));
+    t = mulrr(gel(S,k+1), c);
+    s = odd(k)? mpsub(s, t): mpadd(s, t);
+    if (k == N-1) break;
+    az = diviuuexact(muluui((N-k)<<1,N+k,az), k+1, (k<<1)+1);
   }
   return gerepileupto(av, gdiv(s,d));
 }
@@ -1534,42 +1546,22 @@ sumpos(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)
 GEN
 sumpos2(void *E, GEN (*eval)(void *, GEN), GEN a, long prec)
 {
-  long k, kk, N, G;
+  ulong k, N;
   pari_sp av = avma;
-  GEN r, reel, s, pol, dn, x, *stock;
+  GEN s, pol, dn, S;
 
   if (typ(a) != t_INT) pari_err_TYPE("sumpos2",a);
-  a = subis(a,1); reel = cgetr(prec);
-  N = (long)(0.31*(prec2nbits(prec) + 5));
+  a = subiu(a,1);
+  N = (ulong)(0.31*(prec2nbits(prec) + 5));
 
-  G = -prec2nbits(prec) - 5;
-  stock = (GEN*)new_chunk(N+1); for (k=1; k<=N; k++) stock[k] = NULL;
-  for (k=1; k<=N; k++)
-    if (odd(k) || !stock[k])
-    {
-      pari_sp av2 = avma;
-      x = gen_0; r = utoipos(2*k);
-      for(kk=0;;kk++)
-      {
-        long ex;
-        affgr(eval(E, addii(r,a)), reel);
-        ex = expo(reel) + kk; shiftr_inplace(reel, kk);
-        x = mpadd(x,reel); if (kk && ex < G) break;
-        r = shifti(r,1);
-      }
-      x = gerepileupto(av2, x);
-      if (2*k-1 < N) stock[2*k] = x;
-      affgr(eval(E, addsi(k,a)), reel);
-      stock[k] = addrr(reel, gmul2n(x,1));
-    }
+  if (odd(N)) N++; /* extra precision for free */
+  S = sumpos_init(E, eval, a, N, prec);
+  pol = ZX_div_by_X_1(polzag1(N,N>>1), &dn);
   s = gen_0;
-  pol = polzagreel(N,N>>1,prec+EXTRAPRECWORD);
-  pol = RgX_div_by_X_x(pol, gen_1, &dn);
-  for (k=1; k<=lg(pol)-2; k++)
+  for (k=0; k<N; k++)
   {
-    GEN p1 = gmul(gel(pol,k+1),stock[k]);
-    if (!odd(k)) p1 = gneg_i(p1);
-    s = gadd(s,p1);
+    GEN t = mulri(gel(S,k+1), gel(pol,k+2));
+    s = odd(k)? mpsub(s,t): mpadd(s,t);
   }
   return gerepileupto(av, gdiv(s,dn));
 }
@@ -1679,6 +1671,19 @@ zbrent0(GEN a, GEN b, GEN code, long prec)
 /**                                                                **/
 /********************************************************************/
 
+struct deriv_data
+{
+  GEN code;
+  GEN args;
+};
+
+static GEN deriv_eval(void *E, GEN x)
+{
+ struct deriv_data *data=(struct deriv_data *)E;
+ gel(data->args,1)=x;
+ return closure_callgenvec(data->code, data->args);
+}
+
 /* Rationale: (f(2^-e) - f(-2^-e) + O(2^-pr)) / (2 * 2^-e) = f'(0) + O(2^-2e)
  * since 2nd derivatives cancel.
  *   prec(LHS) = pr - e
@@ -1690,7 +1695,7 @@ GEN
 derivnum(void *E, GEN (*eval)(void *, GEN), GEN x, long prec)
 {
   GEN eps,a,b, y;
-  long pr, l, e, ex;
+  long pr, l, e, ex, newprec;
   pari_sp av = avma;
   long p = precision(x);
   long fpr = p ? prec2nbits(p): prec2nbits(prec);
@@ -1698,17 +1703,20 @@ derivnum(void *E, GEN (*eval)(void *, GEN), GEN x, long prec)
   if (ex < 0) ex = 0; /* near 0 */
   pr = (long)ceil(fpr * 1.5 + ex);
   l = nbits2prec(pr);
+  newprec = nbits2prec(pr + ex + BITS_IN_LONG);
   switch(typ(x))
   {
     case t_REAL:
     case t_COMPLEX:
-      x = gprec_w(x, l + nbits2extraprec(ex + BITS_IN_LONG));
+      x = gprec_w(x, newprec);
   }
 
   e = fpr/2; /* 1/2 required prec (in sig. bits) */
   eps = real2n(-e, l);
+  if (eval==gp_eval || eval==deriv_eval) push_localprec(newprec);
   a = eval(E, gsub(x, eps));
   b = eval(E, gadd(x, eps));
+  if (eval==gp_eval || eval==deriv_eval) pop_localprec();
   y = gmul2n(gsub(b,a), e-1);
   return gerepileupto(av, gprec_w(y, nbits2prec(fpr)));
 }
@@ -1738,19 +1746,6 @@ derivnum0(GEN a, GEN code, long prec)
   EXPR_WRAP(code, derivfun (EXPR_ARG,a,prec));
 }
 
-struct deriv_data
-{
-  GEN code;
-  GEN args;
-};
-
-static GEN deriv_eval(void *E, GEN x)
-{
- struct deriv_data *data=(struct deriv_data *)E;
- gel(data->args,1)=x;
- return closure_callgenvec(data->code, data->args);
-}
-
 GEN
 derivfun0(GEN code, GEN args, long prec)
 {
diff --git a/src/language/tree.h b/src/language/tree.h
index 77c1fc3..6b40936 100644
--- a/src/language/tree.h
+++ b/src/language/tree.h
@@ -20,7 +20,7 @@ typedef enum {Fseq,
               Fmatrixelts,Fmatrixlines,
               Fmat,Fvec,Fnoarg,
               Flistarg,
-              Frefarg,
+              Frefarg, Fvararg,
               Fconst,Fsmall,
               Ftag,
               Fentry,Fcall,Ffunction,Flambda
diff --git a/src/modules/algebras.c b/src/modules/algebras.c
new file mode 100644
index 0000000..135bb9d
--- /dev/null
+++ b/src/modules/algebras.c
@@ -0,0 +1,4482 @@
+/* Copyright (C) 2000  The PARI group.
+
+This file is part of the PARI/GP package.
+
+PARI/GP 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. It is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY WHATSOEVER.
+
+Check the License for details. You should have received a copy of it, along
+with the package; see the file 'COPYING'. If not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+#include "pari.h"
+#include "paripriv.h"
+
+/********************************************************************/
+/**                                                                **/
+/**           ASSOCIATIVE ALGEBRAS, CENTRAL SIMPLE ALGEBRAS        **/
+/**                 contributed by Aurel Page (2014)               **/
+/**                                                                **/
+/********************************************************************/
+static GEN alg_subalg(GEN al, GEN basis);
+static GEN alg_maximal_primes(GEN al, GEN P);
+static GEN algnatmultable(GEN al, long D);
+static GEN _tablemul_ej(GEN mt, GEN x, long j);
+static GEN _tablemul_ej_Fp(GEN mt, GEN x, long j, GEN p);
+static GEN _tablemul_ej_Fl(GEN mt, GEN x, long j, ulong p);
+static ulong algtracei(GEN mt, ulong p, ulong expo, ulong modu);
+static GEN alg_pmaximal(GEN al, GEN p);
+static GEN alg_maximal(GEN al);
+static GEN algtracematrix(GEN al);
+
+static int
+checkalg_i(GEN al)
+{
+  GEN mt;
+  if (typ(al) != t_VEC || lg(al) != 12) return 0;
+  mt = alg_get_multable(al);
+  if (typ(mt) != t_VEC || lg(mt) == 1 || typ(gel(mt,1)) != t_MAT) return 0;
+  if (!isintzero(alg_get_splitting(al)) && gequal0(alg_get_char(al))) {
+    if (typ(gel(al,2)) != t_VEC || lg(gel(al,2)) == 1) return 0;
+    checkrnf(alg_get_splitting(al));
+  }
+  return 1;
+}
+void
+checkalg(GEN al)
+{ if (!checkalg_i(al)) pari_err_TYPE("checkalg [please apply alginit()]",al); }
+
+/**  ACCESSORS  **/
+long
+alg_type(GEN al)
+{
+  if (isintzero(alg_get_splitting(al)) || !gequal0(alg_get_char(al))) return al_TABLE;
+  switch(typ(gmael(al,2,1))) {
+    case t_MAT: return al_CSA;
+    case t_INT:
+    case t_FRAC:
+    case t_POL:
+    case t_POLMOD: return al_CYCLIC;
+    default: return al_NULL;
+  }
+  return -1; /*not reached*/
+}
+long
+algtype(GEN al)
+{ return checkalg_i(al)? alg_type(al): al_NULL; }
+
+/* absdim == dim for al_TABLE. */
+long
+alg_get_dim(GEN al)
+{
+  long d;
+  switch(alg_type(al)) {
+    case al_TABLE: return lg(alg_get_multable(al))-1;
+    case al_CSA: return lg(alg_get_relmultable(al))-1;
+    case al_CYCLIC: d = alg_get_degree(al); return d*d;
+    default: pari_err_TYPE("alg_get_dim", al);
+  }
+  return -1; /*not reached*/
+}
+long
+algdim(GEN al)
+{ checkalg(al); return alg_get_dim(al); }
+
+long
+alg_get_absdim(GEN al)
+{
+  switch(alg_type(al)) {
+    case al_TABLE: return lg(alg_get_multable(al))-1;
+    case al_CSA: return alg_get_dim(al)*nf_get_degree(alg_get_center(al));
+    case al_CYCLIC:
+      return rnf_get_absdegree(alg_get_splitting(al))*alg_get_degree(al);
+    default: pari_err_TYPE("alg_get_absdim", al);
+  }
+  return -1;/*not reached*/
+}
+long
+algabsdim(GEN al)
+{ checkalg(al); return alg_get_absdim(al); }
+
+/* only cyclic */
+GEN
+alg_get_auts(GEN al)
+{
+  if (alg_type(al) != al_CYCLIC)
+    pari_err_TYPE("alg_get_auts [non-cyclic algebra]", al);
+  return gel(al,2);
+}
+GEN
+alg_get_aut(GEN al)
+{
+  if (alg_type(al) != al_CYCLIC)
+    pari_err_TYPE("alg_get_aut [non-cyclic algebra]", al);
+  return gel(alg_get_auts(al),1);
+}
+GEN
+algaut(GEN al) { checkalg(al); return alg_get_aut(al); }
+GEN
+alg_get_b(GEN al)
+{
+  if (alg_type(al) != al_CYCLIC)
+    pari_err_TYPE("alg_get_b [non-cyclic algebra]", al);
+  return gel(al,3);
+}
+GEN
+algb(GEN al) { checkalg(al); return alg_get_b(al); }
+
+/* only CSA */
+GEN
+alg_get_relmultable(GEN al)
+{
+  if (alg_type(al) != al_CSA)
+    pari_err_TYPE("alg_get_relmultable [algebra not given via mult. table]", al);
+  return gel(al,2);
+}
+GEN
+algrelmultable(GEN al) { checkalg(al); return alg_get_relmultable(al); }
+GEN
+alg_get_splittingdata(GEN al)
+{
+  if (alg_type(al) != al_CSA)
+    pari_err_TYPE("alg_get_splittingdata [algebra not given via mult. table]",al);
+  return gel(al,3);
+}
+GEN
+algsplittingdata(GEN al) { checkalg(al); return alg_get_splittingdata(al); }
+GEN
+alg_get_splittingbasis(GEN al)
+{
+  if (alg_type(al) != al_CSA)
+    pari_err_TYPE("alg_get_splittingbasis [algebra not given via mult. table]",al);
+  return gmael(al,3,2);
+}
+GEN
+alg_get_splittingbasisinv(GEN al)
+{
+  if (alg_type(al) != al_CSA)
+    pari_err_TYPE("alg_get_splittingbasisinv [algebra not given via mult. table]",al);
+  return gmael(al,3,3);
+}
+
+/* only cyclic and CSA */
+GEN
+alg_get_splitting(GEN al) { return gel(al,1); }
+GEN
+algsplittingfield(GEN al)
+{
+  long ta;
+  checkalg(al);
+  ta = alg_type(al);
+  if (ta != al_CYCLIC && ta != al_CSA)
+    pari_err_TYPE("alg_get_splittingfield [use alginit]",al);
+  return alg_get_splitting(al);
+}
+long
+alg_get_degree(GEN al)
+{
+  long ta;
+  ta = alg_type(al);
+  if (ta != al_CYCLIC && ta != al_CSA)
+    pari_err_TYPE("alg_get_degree [use alginit]",al);
+  return rnf_get_degree(alg_get_splitting(al));
+}
+long
+algdegree(GEN al)
+{
+  checkalg(al);
+  return alg_get_degree(al);
+}
+
+GEN
+alg_get_center(GEN al)
+{
+  long ta;
+  ta = alg_type(al);
+  if (ta != al_CSA && ta != al_CYCLIC)
+    pari_err_TYPE("alg_get_center [use alginit]",al);
+  return rnf_get_nf(alg_get_splitting(al));
+}
+GEN
+alggetcenter(GEN al)
+{
+  checkalg(al);
+  return alg_get_center(al);
+}
+GEN
+alg_get_splitpol(GEN al)
+{
+  long ta = alg_type(al);
+  if (ta != al_CYCLIC && ta != al_CSA)
+    pari_err_TYPE("alg_get_splitpol [use alginit]",al);
+  return rnf_get_pol(alg_get_splitting(al));
+}
+GEN
+alg_get_abssplitting(GEN al)
+{
+  long ta = alg_type(al), prec;
+  if (ta != al_CYCLIC && ta != al_CSA)
+    pari_err_TYPE("alg_get_abssplitting [use alginit]",al);
+  prec = nf_get_prec(alg_get_center(al));
+  return check_and_build_nfabs(alg_get_splitting(al), prec);
+}
+GEN
+alg_get_hasse_i(GEN al)
+{
+  long ta = alg_type(al);
+  if (ta != al_CYCLIC && ta != al_CSA)
+    pari_err_TYPE("alg_get_hasse_i [use alginit]",al);
+  if (ta == al_CSA) pari_err_IMPL("computation of Hasse invariants over table CSA");
+  return gel(al,4);
+}
+GEN
+alghassei(GEN al) { checkalg(al); return alg_get_hasse_i(al); }
+GEN
+alg_get_hasse_f(GEN al)
+{
+  long ta = alg_type(al);
+  if (ta != al_CYCLIC && ta != al_CSA)
+    pari_err_TYPE("alg_get_hasse_f [use alginit]",al);
+  if (ta == al_CSA) pari_err_IMPL("computation of Hasse invariants over table CSA");
+  return gel(al,5);
+}
+GEN
+alghassef(GEN al) { checkalg(al); return alg_get_hasse_f(al); }
+
+/* all types */
+GEN
+alg_get_ord(GEN al) { return gel(al,7); }
+GEN
+algbasis(GEN al) { checkalg(al); return alg_get_ord(al); }
+GEN
+alg_get_invord(GEN al) { return gel(al,8); }
+GEN
+alginvbasis(GEN al) { checkalg(al); return alg_get_invord(al); }
+GEN
+alg_get_multable(GEN al) { return gel(al,9); }
+GEN
+alggetmultable(GEN al) { checkalg(al); return alg_get_multable(al); }
+GEN
+alg_get_char(GEN al) { return gel(al,10); }
+GEN
+algchar(GEN al) { checkalg(al); return alg_get_char(al); }
+GEN
+alg_get_tracebasis(GEN al) { return gel(al,11); }
+
+/** ADDITIONAL **/
+
+/* FIXME: not rigorous */
+static long
+rnfrealdec(GEN rnf, long k)
+{
+  GEN nf = rnf_get_nf(rnf), pol = rnf_get_pol(rnf);
+  long i, l = lg(pol);
+  pol = shallowcopy(pol);
+  for (i=2; i<l; i++) gel(pol,i) = nfembed(nf, gel(pol,i), k);
+  return sturm(pol);
+}
+
+/* pl : requested signs for real embeddings, 0 = no sign constraint */
+/* FIXME: not rigorous */
+static long
+ispositive(GEN nf, GEN x, GEN pl)
+{
+  long l = lg(pl), i;
+  for (i = 1; i < l; i++)
+    if (pl[i] && pl[i] != gsigne(nfembed(nf,x,i))) return 0;
+  return 1;
+}
+
+/** IDEALCHINESE **/
+
+GEN
+extchinese(GEN nf, GEN x, GEN y, GEN pl, GEN* red)
+{
+  pari_sp av = avma;
+  long i, r, e;
+  GEN y0, G, I,x0, Mr, MI, lambda, mlambda, C, sol, nz;
+
+  y0 = idealchinese(nf, x, y);
+  I = factorbackprime(nf, gel(x,1), gel(x,2));
+  G = nf_get_roundG(nf);
+  *red = ZM_mul(I,ZM_lll(ZM_mul(G,I), 0.99, LLL_IM));
+  y0 = ZC_reducemodmatrix(y0,*red);
+
+  if (ispositive(nf, y0, pl)) {
+    gerepileall(av, 2, &y0, red);
+    return y0;
+  }
+
+  nz = vecsmall01_to_indices(pl);
+  Mr = rowpermute(nf_get_M(nf), nz);
+  MI = RgM_mul(Mr,*red);
+  lambda = gdivgs(matrixnorm(MI,DEFAULTPREC), 2);
+  mlambda = gneg(lambda);
+
+  r = lg(nz); C = cgetg(r, t_COL);
+  for (i = 1; i < r; i++) gel(C,i) = pl[nz[i]] < 0? mlambda: lambda;
+  C = RgC_sub(C, RgM_RgC_mul(Mr,y0));
+
+  sol = inverseimage(MI, C);
+  x0 = ZM_ZC_mul(*red, grndtoi(sol, &e));
+  y0 = ZC_add(y0,x0);
+
+  gerepileall(av, 2, &y0, red);
+  return y0;
+}
+
+/* no garbage collection */
+static GEN
+backtrackfacto(GEN y0, long n, GEN red, GEN pl, GEN nf, GEN data, int (*test)(GEN,GEN,GEN), GEN* fa, GEN N, GEN I)
+{
+  pari_sp av = avma;
+  long b, i;
+  GEN y1, y2, ny, fan;
+  long v[n+1];
+  for (b = 0;; b = b+(2*b)/(3*n)+1)
+  {
+    avma = av;
+    for (i=1; i<=n; i++) v[i] = -b;
+    v[n]--;
+    while (1) {
+      i=n;
+      while (i>0) {
+        if (v[i]==b) {
+          v[i] = -b;
+          i--;
+        }
+        else {
+          v[i]++;
+          break;
+        }
+      }
+      if (i==0) break;
+
+      y1 = y0;
+      for (i=1; i<=n; i++) y1 = nfadd(nf, y1, ZC_z_mul(gel(red,i), v[i]));
+
+      if (!ispositive(nf, y1, pl)) continue;
+
+      ny = absi(nfnorm(nf, y1));
+      if (!signe(ny)) continue;
+      ny = diviiexact(ny,gcdii(ny,N));
+      fan = Z_factor_limit(ny,1<<17);
+      if (lg(fan)>1 && nbrows(fan)>0 && !isprime(gcoeff(fan,nbrows(fan),1)))
+        continue;
+
+      y2 = idealdivexact(nf,y1,idealadd(nf,y1,I));
+      *fa = idealfactor(nf, y2);
+      if (data==gen_0 || test(data,y1,*fa)) return y1;
+    }
+  }
+}
+
+/* if data == gen_0, the test is skipped */
+/* in the test, the factorization does not contain the known factors */
+GEN
+factoredextchinesetest(GEN nf, GEN x, GEN y, GEN pl, GEN* fa, GEN data, int (*test)(GEN,GEN,GEN))
+{
+  pari_sp av = avma;
+  long n,i;
+  GEN y0, y1, red, N, I, vals;
+  n = nf_get_degree(nf);
+  y0 = extchinese(nf, x, y, pl, &red);
+
+  vals = shallowcopy(gel(x,2));
+  if (!gequal0(y0))
+    for (i=1; i<lg(vals); i++) {
+      gel(vals,i) = stoi(nfval(nf,y0,gcoeff(x,i,1)));
+      if (cmpii(gel(vals,i),gcoeff(x,i,2))>0) gel(vals,i) = gcoeff(x,i,2);
+    }
+  /* N and I : known factors */
+  I = factorbackprime(nf, gel(x,1), vals);
+  N = idealnorm(nf,I);
+
+  y1 = backtrackfacto(y0, n, red, pl, nf, data, test, fa, N, I);
+
+  /* restore known factors */
+  for (i=1; i<lg(vals); i++) gel(vals,i) = stoi(nfval(nf,y1,gcoeff(x,i,1)));
+  *fa = famat_reduce(famat_mul_shallow(*fa, mkmat2(gel(x,1), vals)));
+
+  gerepileall(av, 2, &y1, fa);
+  return y1;
+}
+
+GEN
+factoredextchinese(GEN nf, GEN x, GEN y, GEN pl, GEN* fa)
+{ return factoredextchinesetest(nf,x,y,pl,fa,gen_0,NULL); }
+
+/** OPERATIONS ON ASSOCIATIVE ALGEBRAS algebras.c **/
+
+/*
+Convention:
+(K/F,sigma,b) = sum_{i=0..n-1} u^i*K
+t*u = u*sigma(t)
+
+Natural basis:
+1<=i<=d*n^2
+b_i = u^((i-1)/(dn))*ZKabs.((i-1)%(dn)+1)
+
+Integral basis:
+Basis of some order.
+
+al:
+1- rnf of the cyclic splitting field of degree n over the center nf of degree d
+2- VEC of aut^i 1<=i<=n
+3- b in nf
+4- infinite hasse invariants (mod n) : VECSMALL of size r1, values only 0 or n/2 (if integral)
+5- finite hasse invariants (mod n) : VEC[VEC of primes, VECSMALL of hasse inv mod n]
+6- nf of the splitting field (absolute)
+7* dn^2*dn^2 matrix expressing the integral basis in terms of the natural basis
+8* dn^2*dn^2 matrix expressing the natural basis in terms of the integral basis
+9* VEC of dn^2 matrices giving the dn^2*dn^2 left multiplication tables of the integral basis
+10* characteristic of the base field (used only for algebras given by a multiplication table)
+
+If al is given by a multiplication table, only the * fields are present.
+*/
+
+/*
+TODO:
+- add a T2 norm : non canonical... just choose one !
+- LLL-reduce the integral basis
+- more general rnfkummer --> prime powers ?
+- alg_hasse : try to descent to Q in non-kummer case
+- alg_hasse : call polsubcyclo instead of rnfkummer when possible
+- alg_hasse : do a rnfpolredbest at every step
+- assisted factorization when possible : factorint(famat)
+- optimize b by reducing mod n-powers (when creating alg_hasse/can be called independently alred)
+- in all transformations (tensor, optimize...), also return the isomorphism (flag:maps)
+- allow more general elements in operations : integers, rationals, nf (F), nf
+(K), rnf (K).
+- effective GW : check whether condition descends to Q as well
+- opposite algebra and involution
+- optimize basismul using the property that the first element is the identity
+- use famat input for bnrinit etc : useful ? only small primes in the conductor, so factorization is fast anyways.
+- algdisc: reduced disc for al_CYCLIC and al_CSA
+- in algpow, use charpol when better.
+
+Karim :
+- test p-maximality before launching general algorithm
+- easy maximal order when pr unramified in L/K
+- precompute projectors and LLL-reduced basis in extchinese
+*/
+
+/* assumes same center and same variable */
+/* currently only works for coprime degrees */
+GEN
+algtensor(GEN al1, GEN al2, int maxord) {
+  pari_sp av = avma;
+  long v, k, d1, d2;
+  GEN nf, P1, P2, aut1, aut2, b1, b2, C, rnf, aut, b, x1, x2, al;
+
+  checkalg(al1);
+  checkalg(al2);
+  if (alg_type(al1) != al_CYCLIC  || alg_type(al2) != al_CYCLIC)
+    pari_err_IMPL("tensor of non-cyclic algebras"); /* TODO: do it. */
+
+  nf=alg_get_center(al1);
+  if (!gequal(alg_get_center(al2),nf))
+    pari_err_OP("tensor product [not the same center]", al1, al2);
+
+  P1=alg_get_splitpol(al1); aut1=alg_get_aut(al1); b1=alg_get_b(al1);
+  P2=alg_get_splitpol(al2); aut2=alg_get_aut(al2); b2=alg_get_b(al2);
+  v=varn(P1);
+
+  d1=alg_get_degree(al1);
+  d2=alg_get_degree(al2);
+  if (cgcd(d1,d2) != 1)
+    pari_err_IMPL("tensor of cylic algebras of non-coprime degrees"); /* TODO */
+
+  if (d1==1) return gcopy(al2);
+  if (d2==1) return gcopy(al1);
+
+  C = nfcompositum(nf, P1, P2, 3);
+  rnf = rnfinit(nf,gel(C,1));
+  x1 = gel(C,2);
+  x2 = gel(C,3);
+  k = itos(gel(C,4));
+  aut = gadd(gsubst(aut2,v,x2),gmulsg(k,gsubst(aut1,v,x1)));
+  b = nfmul(nf,nfpow_u(nf,b1,d2),nfpow_u(nf,b2,d1));
+  al = alg_cyclic(rnf,aut,b,maxord);
+  return gerepilecopy(av,al);
+}
+
+/* M an n x d Flm of rank d, n >= d. Initialize Mx = y solver */
+static GEN
+Flm_invimage_init(GEN M, ulong p)
+{
+  GEN v = Flm_indexrank(M, p), perm = gel(v,1);
+  GEN MM = rowpermute(M, perm); /* square invertible */
+  return mkvec2(Flm_inv(MM,p), perm);
+}
+/* assume Mx = y has a solution, v = Flm_invimage_init(M,p); return x */
+static GEN
+Flm_invimage_pre(GEN v, GEN y, ulong p)
+{
+  GEN inv = gel(v,1), perm = gel(v,2);
+  return Flm_Flc_mul(inv, vecsmallpermute(y, perm), p);
+}
+
+GEN
+algradical(GEN al)
+{
+  pari_sp av = avma;
+  GEN I, x, traces, K, MT, P, mt;
+  long l,i,ni, n;
+  ulong modu, expo, p;
+  checkalg(al);
+  P = alg_get_char(al);
+  mt = alg_get_multable(al);
+  n = alg_get_absdim(al);
+  traces = algtracematrix(al);
+  if (!signe(P))
+  {
+    K = ker(traces);
+    ni = lg(K)-1; if (!ni) { avma = av; return gen_0; }
+    return gerepileupto(av, K);
+  }
+  K = FpM_ker(traces, P);
+  ni = lg(K)-1; if (!ni) { avma = av; return gen_0; }
+  if (cmpiu(P,n)>0) return gerepileupto(av, K);
+
+  /* tough case, p <= n. Ronyai's algorithm */
+  p = P[2]; l = 1;
+  expo = p; modu = p*p;
+  while (modu<=(ulong)n) { l++; modu *= p; }
+  MT = ZMV_to_FlmV(mt, modu);
+  I = ZM_to_Flm(K,p); /* I_0 */
+  for (i=1; i<=l; i++) {/*compute I_i, expo = p^i, modu = p^(l+1) > n*/
+    long j, lig,col;
+    GEN v = cgetg(ni+1, t_VECSMALL);
+    GEN invI = Flm_invimage_init(I, p);
+    traces = cgetg(ni+1,t_MAT);
+    for (j = 1; j <= ni; j++)
+    {
+      GEN M = algbasismultable_Flm(MT, gel(I,j), modu);
+      uel(v,j) = algtracei(M, p,expo,modu);
+    }
+    for (col=1; col<=ni; col++)
+    {
+      GEN t = cgetg(n+1,t_VECSMALL); gel(traces,col) = t;
+      x = gel(I, col); /*col-th basis vector of I_{i-1}*/
+      for (lig=1; lig<=n; lig++)
+      {
+        GEN y = _tablemul_ej_Fl(MT,x,lig,p);
+        GEN z = Flm_invimage_pre(invI, y, p);
+        uel(t,lig) = Flv_dotproduct(v, z, p);
+      }
+    }
+    K = Flm_ker(traces, p);
+    ni = lg(K)-1; if (!ni) { avma = av; return gen_0; }
+    I = Flm_mul(I,K,p);
+    expo *= p;
+  }
+  return Flm_to_ZM(I);
+}
+
+static GEN
+alg_quotient0(GEN al, GEN S, GEN Si, long nq, GEN p, int maps)
+{
+  GEN mt = cgetg(nq+1,t_VEC);
+  long i;
+  for (i=1; i<=nq; i++)
+  {
+    GEN mti = algmultable(al,gel(S,i));
+    if (signe(p)) gel(mt,i) = FpM_mul(Si, FpM_mul(mti,S,p), p);
+    else          gel(mt,i) = RgM_mul(Si, RgM_mul(mti,S));
+  }
+  al = algtableinit(mt,p);
+  if (maps) al = mkvec3(al,Si,S); /*algebra, proj, lift*/
+  return al;
+}
+
+/*quotient of an algebra by a nontrivial two-sided ideal*/
+GEN
+alg_quotient(GEN al, GEN I, int maps)
+{
+  pari_sp av = avma;
+  GEN p, IS, ISi, S, Si;
+  long n, ni;
+
+  checkalg(al);
+  p = alg_get_char(al);
+  n = alg_get_absdim(al);
+  ni = lg(I)-1;
+
+  /*force first vector of complement to be the identity*/
+  IS = shallowconcat(I, gcoeff(alg_get_multable(al),1,1));
+  if (signe(p)) {
+    IS = FpM_suppl(IS,p);
+    ISi = FpM_inv(IS,p);
+  }
+  else {
+    IS = suppl(IS);
+    ISi = RgM_inv(IS);
+  }
+  S = vecslice(IS, ni+1, n);
+  Si = rowslice(ISi, ni+1, n);
+  return gerepilecopy(av, alg_quotient0(al, S, Si, n-ni, p, maps));
+}
+
+/* z[1],...z[nz] central elements such that z[1]A + z[2]A + ... + z[nz]A = A
+ * is a direct sum. idempotents ==> first basis element is identity */
+GEN
+alg_centralproj(GEN al, GEN z, int maps)
+{
+  pari_sp av = avma;
+  GEN S, U, Ui, alq, p;
+  long i, iu, lz = lg(z);
+
+  checkalg(al);
+  if (typ(z) != t_VEC) pari_err_TYPE("alcentralproj",z);
+  p = alg_get_char(al);
+  S = cgetg(lz,t_VEC); /*S[i] = Im(z_i)*/
+  for (i=1; i<lz; i++)
+  {
+    GEN mti = algmultable(al, gel(z,i));
+    if (signe(p)) gel(S,i) = FpM_image(mti,p);
+    else          gel(S,i) = image(mti);
+  }
+  U = shallowconcat1(S); /*U = [Im(z_1)|Im(z_2)|...|Im(z_nz)], n x n*/
+  if (lg(U)-1 < alg_get_absdim(al)) pari_err_TYPE("alcentralproj [z[i]'s not surjective]",z);
+  if (signe(p)) Ui = FpM_inv(U,p);
+  else          Ui = RgM_inv(U);
+  if (!Ui) pari_err_BUG("alcentralproj");
+
+  alq = cgetg(lz,t_VEC);
+  for (iu=0,i=1; i<lz; i++)
+  {
+    long nq = lg(gel(S,i))-1, ju = iu + nq;
+    GEN Si = rowslice(Ui, iu+1, ju);
+    gel(alq, i) = alg_quotient0(al,gel(S,i),Si,nq,p,maps);
+    iu = ju;
+  }
+  return gerepilecopy(av, alq);
+}
+
+GEN
+algcenter(GEN al)
+{
+  pari_sp av = avma;
+  long n, i, j, k, ic;
+  GEN C, cij, mt, p;
+  checkalg(al);
+  n = alg_get_absdim(al);
+  mt = alg_get_multable(al);
+  p = alg_get_char(al);
+  C = cgetg(n+1,t_MAT);
+  for (j=1; j<=n; j++)
+  {
+    gel(C,j) = cgetg(n*n-n+1,t_COL);
+    ic = 1;
+    for (i=2; i<=n; i++) {
+      if (signe(p)) cij = FpC_sub(gmael(mt,i,j),gmael(mt,j,i),p);
+      else          cij = RgC_sub(gmael(mt,i,j),gmael(mt,j,i));
+      for (k=1; k<=n; k++, ic++) gcoeff(C,ic,j) = gel(cij, k);
+    }
+  }
+  if (signe(p)) return gerepileupto(av, FpM_ker(C,p));
+  else          return gerepileupto(av, ker(C));
+}
+
+GEN gp_algcenter(GEN al)
+{
+  checkalg(al);
+  if(alg_type(al)==al_TABLE) return algcenter(al);
+  return alggetcenter(al);
+}
+
+/* Only in positive characteristic. Assumes that al is semisimple. */
+GEN
+algprimesubalg(GEN al)
+{
+  pari_sp av = avma;
+  GEN p, Z, F, K;
+  long nz, i;
+  checkalg(al);
+  p = alg_get_char(al);
+  if (!signe(p)) pari_err_DOMAIN("algprimesubalg","characteristic","=",gen_0,p);
+
+  Z = algcenter(al);
+  nz = lg(Z)-1;
+  if (nz==1) return Z;
+
+  F = cgetg(nz+1, t_MAT);
+  for (i=1; i<=nz; i++) {
+    GEN zi = gel(Z,i);
+    gel(F,i) = FpC_sub(algpow(al,zi,p),zi,p);
+  }
+  K = FpM_ker(F,p);
+  return gerepileupto(av, FpM_mul(Z,K,p));
+}
+
+
+static GEN
+_FpX_mul(void* D, GEN x, GEN y) { return FpX_mul(x,y,(GEN)D); }
+static GEN
+_FpX_pow(void* D, GEN x, GEN n) { return FpX_powu(x,itos(n),(GEN)D); }
+static GEN
+FpX_factorback(GEN fa, GEN p)
+{
+  return gen_factorback(gel(fa,1), zv_to_ZV(gel(fa,2)), &_FpX_mul, &_FpX_pow, (void*)p);
+}
+
+static GEN
+out_decompose(GEN t, GEN Z, GEN P, GEN p)
+{
+  GEN ali = gel(t,1), projm = gel(t,2), liftm = gel(t,3), pZ;
+  if (signe(p)) pZ = FpM_image(FpM_mul(projm,Z,p),p);
+  else          pZ = image(RgM_mul(projm,Z));
+  return mkvec5(ali, projm, liftm, pZ, P);
+}
+/* fa factorization of charpol(x) */
+static GEN
+alg_decompose0(GEN al, GEN x, GEN fa, GEN Z, int mini)
+{
+  long k = lgcols(fa)-1, k2 = mini? 1: k/2;
+  GEN v1 = rowslice(fa,1,k2);
+  GEN v2 = rowslice(fa,k2+1,k);
+  GEN alq, P,Q, mx, p = alg_get_char(al);
+  if (signe(p)) {
+    P = FpX_factorback(v1, p);
+    Q = FpX_factorback(v2, p);
+    P = FpX_mul(P, FpXQ_inv(P,Q,p), p);
+  }
+  else {
+    P = factorback(v1);
+    Q = factorback(v2);
+    P = RgX_mul(P, RgXQ_inv(P,Q));
+  }
+  mx = algmultable(al, x);
+  P = algpoleval(al, P, mx);
+  if (signe(p)) Q = FpC_sub(col_ei(lg(P)-1,1), P, p);
+  else          Q = gsub(gen_1, P);
+  if(gequal0(P) || gequal0(Q)) return NULL;
+  alq = alg_centralproj(al, mkvec2(P,Q), 1);
+
+  P = out_decompose(gel(alq,1), Z, P, p); if (mini) return P;
+  Q = out_decompose(gel(alq,2), Z, Q, p);
+  return mkvec2(P,Q);
+}
+
+static GEN
+random_pm1(long n)
+{
+  GEN z = cgetg(n+1,t_VECSMALL);
+  long i;
+  for (i = 1; i <= n; i++) z[i] = random_bits(5)%3 - 1;
+  return z;
+}
+
+static GEN alg_decompose(GEN al, GEN Z, int mini);
+/* Try to split al using x's charpoly. Return gen_0 if simple, NULL if failure.
+ * And a splitting otherwise */
+static GEN
+try_fact(GEN al, GEN x, GEN zx, GEN Z, GEN Zal, long mini)
+{
+  GEN z, dec0, dec1, cp = algcharpoly(Zal,zx,0), fa, p = alg_get_char(al);
+  long nfa, e;
+  if (signe(p)) fa = FpX_factor(cp,p);
+  else          fa = factor(cp);
+  nfa = nbrows(fa);
+  if (nfa == 1) {
+    if (signe(p)) e = gel(fa,2)[1];
+    else          e = itos(gcoeff(fa,1,2));
+    return e==1 ? gen_0 : NULL;
+  }
+  dec0 = alg_decompose0(al, x, fa, Z, mini);
+  if (!dec0) return NULL;
+  if (!mini) return dec0;
+  dec1 = alg_decompose(gel(dec0,1), gel(dec0,4), 1);
+  z = gel(dec0,5);
+  if (!isintzero(dec1)) {
+    if (signe(p)) z = FpM_FpC_mul(gel(dec0,3),dec1,p);
+    else          z = RgM_RgC_mul(gel(dec0,3),dec1);
+  }
+  return z;
+}
+static GEN
+randcol(long n, GEN b)
+{
+  GEN N = addiu(shifti(b,1), 1);
+  long i;
+  GEN res =  cgetg(n+1,t_COL);
+  for (i=1; i<=n; i++)
+  {
+    pari_sp av = avma;
+    gel(res,i) = gerepileuptoint(av, subii(randomi(N),b));
+  }
+  return res;
+}
+/* Return gen_0 if already simple. mini: only returns a central idempotent
+ * corresponding to one simple factor */
+static GEN
+alg_decompose(GEN al, GEN Z, int mini)
+{
+  pari_sp av;
+  GEN Zal, x, zx, rand, dec0, B, p;
+  long i, nz = lg(Z)-1;
+
+  if (nz==1) return gen_0;
+  Zal = alg_subalg(al,Z);
+  av = avma;
+  rand = random_pm1(nz);
+  zx = zc_to_ZC(rand);
+  p = alg_get_char(al);
+  if (signe(p)) {
+    zx = FpC_red(zx,p);
+    x = ZM_zc_mul(Z,rand);
+    x = FpC_red(x,p);
+  }
+  else x = RgM_zc_mul(Z,rand);
+  dec0 = try_fact(al,x,zx,Z,Zal,mini);
+  if (dec0) return dec0;
+  avma = av;
+  for (i=2; i<=nz; i++)
+  {
+    dec0 = try_fact(al,gel(Z,i),col_ei(nz,i),Z,Zal,mini);
+    if (dec0) return dec0;
+    avma = av;
+  }
+  B = int2n(10);
+  for(;;)
+  {
+    GEN x = randcol(nz,B), zx = ZM_ZC_mul(Z,x);
+    dec0 = try_fact(al,x,zx,Z,Zal,mini);
+    if (dec0) return dec0;
+    avma = av;
+  }
+}
+
+/*TODO guarantee that the images of the liftm form a direct sum*/
+static GEN
+alg_decompose_total(GEN al, GEN Z, int maps)
+{
+  GEN dec, sc, p;
+  long i;
+
+  dec = alg_decompose(al, Z, 0);
+  if (isintzero(dec))
+  {
+    if (maps) {
+      long n = alg_get_absdim(al);
+      al = mkvec3(al, matid(n), matid(n));
+    }
+    return mkvec(al);
+  }
+  p = alg_get_char(al); if (!signe(p)) p = NULL;
+  sc = cgetg(lg(dec), t_VEC);
+  for (i=1; i<lg(sc); i++) {
+    GEN D = gel(dec,i), a = gel(D,1), Za = gel(D,4);
+    GEN S = alg_decompose_total(a, Za, maps);
+    gel(sc,i) = S;
+    if (maps)
+    {
+      GEN projm = gel(D,2), liftm = gel(D,3);
+      long j, lS = lg(S);
+      for (j=1; j<lS; j++)
+      {
+        GEN Sj = gel(S,j), p2 = gel(Sj,2), l2 = gel(Sj,3);
+        if (p) p2 = FpM_mul(p2, projm, p);
+        else   p2 = RgM_mul(p2, projm);
+        if (p) l2 = FpM_mul(liftm, l2, p);
+        else   l2 = RgM_mul(liftm, l2);
+        gel(Sj,2) = p2;
+        gel(Sj,3) = l2;
+      }
+    }
+  }
+  return shallowconcat1(sc);
+}
+
+static GEN
+alg_subalg(GEN al, GEN basis)
+{
+  GEN invbasis, mt, p = alg_get_char(al);
+  long i, j, n = lg(basis)-1;
+  if (!signe(p)) p = NULL;
+  if (p) { /*TODO change after bugfix?*/
+    GEN complbasis = FpM_suppl(basis,p);
+    invbasis = rowslice(FpM_inv(complbasis,p),1,n);
+  }
+  else invbasis = RgM_inv(basis);
+  mt = cgetg(n+1,t_VEC);
+  gel(mt,1) = matid(n);
+  for(i=2; i<=n; i++) {
+    GEN mtx = cgetg(n+1,t_MAT), x = gel(basis,i);
+    gel(mtx,1) = col_ei(n,i);
+    for(j=2; j<=n; j++) {
+      GEN xy = algmul(al, x, gel(basis,j));
+      if (p) gel(mtx,j) = FpM_FpC_mul(invbasis, xy, p);
+      else   gel(mtx,j) = RgM_RgC_mul(invbasis, xy);
+    }
+    gel(mt,i) = mtx;
+  }
+  return algtableinit(mt,p);
+}
+GEN
+algsubalg(GEN al, GEN basis)
+{
+  pari_sp av = avma;
+  GEN p;
+  checkalg(al);
+  if (typ(basis) != t_MAT) pari_err_TYPE("algsubalg",basis);
+  p = alg_get_char(al);
+  if (signe(p)) basis = RgM_to_FpM(basis,p);
+  return gerepileupto(av, alg_subalg(al,basis));
+}
+
+GEN
+algsimpledec(GEN al, int maps)
+{
+  pari_sp av = avma;
+  GEN Z, p, res;
+  long n;
+  checkalg(al);
+  p = alg_get_char(al);
+  if (signe(p)) Z = algprimesubalg(al);
+  else          Z = algcenter(al);
+
+  if (lg(Z) == 2) {/*dim Z = 1*/
+    n = alg_get_absdim(al);
+    avma = av;
+    if (!maps) return mkveccopy(al);
+    retmkvec(mkvec3(gcopy(al), matid(n), matid(n)));
+  }
+  res = alg_decompose_total(al, Z, maps);
+  return gerepilecopy(av, res);
+}
+
+GEN
+alg_decomposition(GEN al)
+{
+  pari_sp av = avma;
+  /*GEN p = alg_get_char(al);*/
+  GEN rad, alq, dec, res;
+  rad = algradical(al);
+  alq = gequal0(rad) ? al : alg_quotient(al,rad,0);
+  dec = algsimpledec(alq,0);
+  res = mkvec2(rad, dec); /*TODO si char 0, reconnaitre les centres comme nf et descendre les tables de multiplication*/
+  return gerepilecopy(av,res);
+}
+
+/* multiplication table sanity checks */
+static GEN
+check_mt(GEN mt, GEN p)
+{
+  long i, l;
+  GEN MT = cgetg_copy(mt, &l);
+  if (typ(MT) != t_VEC || l == 1) return NULL;
+  for (i = 1; i < l; i++)
+  {
+    GEN M = gel(mt,i);
+    if (typ(M) != t_MAT || lg(M) != l || lgcols(M) != l) return NULL;
+    if (p) M = RgM_to_FpM(M,p);
+    if (i > 1 && ZC_is_ei(gel(M,1)) != i) return NULL; /* i = 1 checked at end*/
+    gel(MT,i) = M;
+  }
+  if (!ZM_isidentity(gel(MT,1))) return NULL;
+  return MT;
+}
+
+int
+algisassociative(GEN mt0, GEN p)
+{
+  pari_sp av = avma;
+  long i, j, k, n;
+  GEN M, mt;
+
+  if (checkalg_i(mt0)) { p = alg_get_char(mt0); mt0 = alg_get_multable(mt0); }
+  if (typ(p) != t_INT) pari_err_TYPE("algisassociative",p);
+  mt = check_mt(mt0, isintzero(p)? NULL: p);
+  if (!mt) pari_err_TYPE("algisassociative (mult. table)", mt0);
+  n = lg(mt)-1;
+  M = cgetg(n+1,t_MAT);
+  for (j=1; j<=n; j++) gel(M,j) = cgetg(n+1,t_COL);
+  for (i=1; i<=n; i++)
+  {
+    GEN mi = gel(mt,i);
+    for (j=1; j<=n; j++) gcoeff(M,i,j) = gel(mi,j); /* ei.ej */
+  }
+  for (i=2; i<=n; i++) {
+    GEN mi = gel(mt,i);
+    for (j=2; j<=n; j++) {
+      for (k=2; k<=n; k++) {
+        GEN x, y;
+        if (signe(p)) {
+          x = _tablemul_ej_Fp(mt,gcoeff(M,i,j),k,p);
+          y = FpM_FpC_mul(mi,gcoeff(M,j,k),p);
+        }
+        else {
+          x = _tablemul_ej(mt,gcoeff(M,i,j),k);
+          y = RgM_RgC_mul(mi,gcoeff(M,j,k));
+        }
+        /* not cmp_universal: mustn't fail on 0 == Mod(0,2) for instance */
+        if (!gequal(x,y)) { avma = av; return 0; }
+      }
+    }
+  }
+  avma = av; return 1;
+}
+
+int
+algiscommutative(GEN al) /* assumes e_1 = 1 */
+{
+  long i,j,k,N,sp;
+  GEN mt,a,b,p;
+  checkalg(al);
+  if(alg_type(al) != al_TABLE) return alg_get_degree(al)==1;
+  N = alg_get_absdim(al);
+  mt = alg_get_multable(al);
+  p = alg_get_char(al);
+  sp = signe(p);
+  for(i=2; i<=N; i++)
+    for(j=2; j<=N; j++)
+      for(k=1; k<=N; k++) {
+        a = gcoeff(gel(mt,i),k,j);
+        b = gcoeff(gel(mt,j),k,i);
+        if(sp) {
+          if(cmpii(Fp_red(a,p), Fp_red(b,p))) return 0;
+        }
+        else if(gcmp(a,b)) return 0;
+      }
+  return 1;
+}
+
+int
+algissemisimple(GEN al)
+{
+  pari_sp av = avma;
+  GEN rad;
+  checkalg(al);
+  if(alg_type(al) != al_TABLE) return 1;
+  rad = algradical(al);
+  avma = av;
+  return gequal0(rad);
+}
+
+/* ss : known to be semisimple */
+int
+algissimple(GEN al, long ss)
+{
+  pari_sp av = avma;
+  GEN Z, dec, p;
+  checkalg(al);
+  if(alg_type(al) != al_TABLE) return 1;
+  if(!ss && !algissemisimple(al)) return 0;
+
+  p = alg_get_char(al);
+  if (signe(p)) Z = algprimesubalg(al);
+  else          Z = algcenter(al);
+
+  if (lg(Z) == 2) {/*dim Z = 1*/
+    avma = av;
+    return 1;
+  }
+  dec = alg_decompose(al, Z, 1);
+  avma = av;
+  return gequal0(dec);
+}
+
+static int
+is_place_prid_i(GEN nf, GEN pl, GEN* pr, long* emb)
+{
+  long r1 = nf_get_r1(nf), r2 = nf_get_r2(nf);
+  *pr = get_prid(pl);
+  if (*pr) return 1;
+  if (typ(pl) != t_INT) return -1;
+  if (signe(pl)<=0) return -2;
+  if (cmpis(pl,r1+r2)>0) return -3;
+  *emb = itos(pl);
+  return 0;
+}
+
+/* if pl is a prime ideal, sets pr to this prime */
+/* if pl is an integer between 1 and r1+r2 sets emb to this integer */
+static int
+is_place_prid(GEN nf, GEN pl, GEN* pr, long* emb)
+{
+  int res = is_place_prid_i(nf, pl, pr, emb);
+  if (res == -1) pari_err_TYPE("is_place_prid", pl);
+  if (res == -2) pari_err_DOMAIN("is_place_prid", "pl", "<=", gen_0, pl);
+  if (res == -3) pari_err_DOMAIN("is_place_prid", "pl", ">", stoi(nf_get_r1(nf)+nf_get_r2(nf)), pl);
+  return res;
+}
+
+/* is there any reason for the primes of hassef not to be sorted ? */
+static long
+linear_prime_search(GEN L, GEN pr)
+{
+  long i;
+  for(i=1; i<lg(L); i++)
+    if(!cmp_prime_ideal(gel(L,i),pr)) return i;
+  return 0;
+}
+
+static long
+alghasse_emb(GEN al, long emb)
+{
+  GEN nf;
+  long r1;
+  nf = alg_get_center(al);
+  r1 = nf_get_r1(nf);
+  if (emb <= r1)    return alg_get_hasse_i(al)[emb];
+  else              return 0;
+}
+
+static long
+alghasse_pr(GEN al, GEN pr)
+{
+  long i;
+  GEN hf, L;
+  hf = alg_get_hasse_f(al);
+  L = gel(hf,1);
+  i = linear_prime_search(L,pr);
+  if (i) return gel(hf,2)[i];
+  else   return 0;
+}
+
+static long
+alghasse_0(GEN al, GEN pl)
+{
+  long ta, ispr, h, emb = 0;/*-Wall*/
+  GEN pr, nf;
+  checkalg(al);
+  ta = alg_type(al);
+  if (ta == al_CSA) pari_err_IMPL("computation of Hasse invariants over table CSA");
+  if (ta == al_TABLE) pari_err_TYPE("alghasse_0 [use alginit]",al);
+  nf = alg_get_center(al);
+  ispr = is_place_prid(nf, pl, &pr, &emb);
+  if (ispr) h = alghasse_pr(al, pr);
+  else      h = alghasse_emb(al, emb);
+  return h;
+}
+
+GEN
+alghasse(GEN al, GEN pl)
+{
+  pari_sp av = avma;
+  long h = alghasse_0(al,pl), d;
+  d = alg_get_degree(al);
+  return gerepilecopy(av, gdivgs(stoi(h),d));
+}
+
+static long
+indexfromhasse(long h, long d) { return d/cgcd(h,d); }
+
+long
+algindex(GEN al, GEN pl)
+{
+  pari_sp av = avma;
+  long h, d, res, i, r1;
+  GEN hi, hf, L;
+
+  checkalg(al);
+  if (alg_type(al) == al_TABLE) pari_err_TYPE("algindex [use alginit]",al);
+  d = alg_get_degree(al);
+
+  if (pl) {
+    h = alghasse_0(al,pl);
+    avma = av;
+    return indexfromhasse(h,d);
+  }
+
+  /* else : global index */
+  res = 1;
+  r1 = nf_get_r1(alg_get_center(al));
+  hi = alg_get_hasse_i(al);
+  for(i=1; i<=r1 && res!=d; i++)
+    res = clcm(res, indexfromhasse(hi[i],d));
+  hf = alg_get_hasse_f(al);
+  L = gel(hf,1);
+  hf = gel(hf,2);
+  for(i=1; i<lg(L) && res!=d; i++)
+    res = clcm(res, indexfromhasse(hf[i],d));
+  avma = av;
+  return res;
+}
+
+int
+algisdivision(GEN al, GEN pl)
+{
+  checkalg(al);
+  if (alg_type(al) == al_TABLE) {
+    if (!algissimple(al,0)) return 0;
+    if (algiscommutative(al)) return 1;
+    pari_err_IMPL("algisdivision for table algebras");
+  }
+  return algindex(al,pl) == alg_get_degree(al);
+}
+
+int
+algissplit(GEN al, GEN pl)
+{
+  checkalg(al);
+  if (alg_type(al) == al_TABLE) pari_err_TYPE("algissplit [use alginit]", al);
+  return algindex(al,pl) == 1;
+}
+
+int
+algisramified(GEN al, GEN pl)
+{
+  checkalg(al);
+  if (alg_type(al) == al_TABLE) pari_err_TYPE("algisramified [use alginit]", al);
+  return algindex(al,pl) != 1;
+}
+
+GEN
+algramifiedplaces(GEN al)
+{
+  pari_sp av = avma;
+  GEN ram, hf, hi, Lpr;
+  long r1, count, i;
+  checkalg(al);
+  if (alg_type(al) == al_TABLE) pari_err_TYPE("algramifiedplaces [use alginit]", al);
+  r1 = nf_get_r1(alg_get_center(al));
+  hi = alg_get_hasse_i(al);
+  hf = alg_get_hasse_f(al);
+  Lpr = gel(hf,1);
+  hf = gel(hf,2);
+  ram = cgetg(r1+lg(Lpr), t_VEC);
+  count = 0;
+  for(i=1; i<=r1; i++)
+    if (hi[i]) {
+      count++;
+      gel(ram,count) = stoi(i);
+    }
+  for(i=1; i<lg(Lpr); i++)
+    if (hf[i]) {
+      count++;
+      gel(ram,count) = gel(Lpr,i);
+    }
+  setlg(ram, count+1);
+  return gerepilecopy(av, ram);
+}
+
+/** OPERATIONS ON ELEMENTS operations.c **/
+
+static long
+alg_model0(GEN al, GEN x)
+{
+  long t, N = alg_get_absdim(al), lx = lg(x), d, n, D, i;
+  if (typ(x) == t_MAT) return al_MATRIX;
+  if (typ(x) != t_COL) return al_INVALID;
+  if (N == 1) {
+    if(lx != 2) return al_INVALID;
+    return al_TRIVIAL; /* cannot distinguish basis and alg from size */
+  }
+
+  switch(alg_type(al)) {
+    case al_TABLE:
+      if(lx != N+1) return al_INVALID;
+      return al_BASIS;
+    case al_CYCLIC:
+      d = alg_get_degree(al);
+      if (lx == N+1) return al_BASIS;
+      if (lx == d+1) return al_ALGEBRAIC;
+      return al_INVALID;
+    case al_CSA:
+      D = alg_get_dim(al);
+      n = nf_get_degree(alg_get_center(al));
+      if (n == 1) {
+        if(lx != D+1) return al_INVALID;
+        for(i=1; i<=D; i++) {
+          t = typ(gel(x,i));
+          if (t == t_POL || t == t_POLMOD)  return al_ALGEBRAIC; /* t_COL ? */
+        }
+        return al_BASIS;
+      }
+      else {
+        if (lx == N+1) return al_BASIS;
+        if (lx == D+1) return al_ALGEBRAIC;
+        return al_INVALID;
+      }
+  }
+  return al_INVALID; /* not reached */
+}
+
+static void
+checkalgx(GEN x, long model)
+{
+  long t, i;
+  switch(model) {
+    case al_BASIS:
+      for(i=1; i<lg(x); i++) {
+        t = typ(gel(x,i));
+        if (t != t_INT && t != t_FRAC)
+          pari_err_TYPE("checkalgx", gel(x,i));
+      }
+      return;
+    case al_TRIVIAL:
+    case al_ALGEBRAIC:
+      for(i=1; i<lg(x); i++) {
+        t = typ(gel(x,i));
+        if (t != t_INT && t != t_FRAC && t != t_POL && t != t_POLMOD)
+          /* t_COL ? */
+          pari_err_TYPE("checkalgx", gel(x,i));
+      }
+      return;
+  }
+}
+
+long alg_model(GEN al, GEN x)
+{
+  long res = alg_model0(al, x);
+  if(res == al_INVALID) pari_err_TYPE("alg_model", x);
+  checkalgx(x, res);
+  return res;
+}
+
+static GEN
+alC_add_i(GEN al, GEN x, GEN y, long lx)
+{
+  GEN A = cgetg(lx, t_COL);
+  long i;
+  for (i=1; i<lx; i++) gel(A,i) = algadd(al, gel(x,i), gel(y,i));
+  return A;
+}
+static GEN
+alM_add(GEN al, GEN x, GEN y)
+{
+  long lx = lg(x), l, j;
+  GEN z;
+  if (lg(y) != lx) pari_err_DIM("alM_add (rows)");
+  if (lx == 1) return cgetg(1, t_MAT);
+  z = cgetg(lx, t_MAT); l = lgcols(x);
+  if (lgcols(y) != l) pari_err_DIM("alM_add (columns)");
+  for (j = 1; j < lx; j++) gel(z,j) = alC_add_i(al, gel(x,j), gel(y,j), l);
+  return z;
+}
+GEN
+algadd(GEN al, GEN x, GEN y)
+{
+  pari_sp av = avma;
+  long tx, ty;
+  GEN p;
+  checkalg(al);
+  tx = alg_model(al,x);
+  ty = alg_model(al,y);
+  p = alg_get_char(al);
+  if (signe(p)) return FpC_add(x,y,p);
+  if (tx==ty) {
+    if (tx!=al_MATRIX) return gadd(x,y);
+    return gerepilecopy(av, alM_add(al,x,y));
+  }
+  if (tx==al_ALGEBRAIC) x = algalgtobasis(al,x);
+  if (ty==al_ALGEBRAIC) y = algalgtobasis(al,y);
+  return gerepileupto(av, gadd(x,y));
+}
+
+GEN
+algneg(GEN al, GEN x) { checkalg(al); (void)alg_model(al,x); return gneg(x); }
+
+static GEN
+alC_sub_i(GEN al, GEN x, GEN y, long lx)
+{
+  long i;
+  GEN A = cgetg(lx, t_COL);
+  for (i=1; i<lx; i++) gel(A,i) = algsub(al, gel(x,i), gel(y,i));
+  return A;
+}
+static GEN
+alM_sub(GEN al, GEN x, GEN y)
+{
+  long lx = lg(x), l, j;
+  GEN z;
+  if (lg(y) != lx) pari_err_DIM("alM_sub (rows)");
+  if (lx == 1) return cgetg(1, t_MAT);
+  z = cgetg(lx, t_MAT); l = lgcols(x);
+  if (lgcols(y) != l) pari_err_DIM("alM_sub (columns)");
+  for (j = 1; j < lx; j++) gel(z,j) = alC_sub_i(al, gel(x,j), gel(y,j), l);
+  return z;
+}
+GEN
+algsub(GEN al, GEN x, GEN y)
+{
+  long tx, ty;
+  pari_sp av = avma;
+  GEN p;
+  checkalg(al);
+  tx = alg_model(al,x);
+  ty = alg_model(al,y);
+  p = alg_get_char(al);
+  if (signe(p)) return FpC_sub(x,y,p);
+  if (tx==ty) {
+    if(tx != al_MATRIX) return gsub(x,y);
+    return gerepilecopy(av, alM_sub(al,x,y));
+  }
+  if (tx==al_ALGEBRAIC) x = algalgtobasis(al,x);
+  if (ty==al_ALGEBRAIC) y = algalgtobasis(al,y);
+  return gerepileupto(av, gsub(x,y));
+}
+
+static GEN
+algalgmul_cyc(GEN al, GEN x, GEN y)
+{
+  pari_sp av = avma;
+  long n = alg_get_degree(al), i, k;
+  GEN xalg, yalg, res, rnf, auts, sum, b, prod, autx;
+  rnf = alg_get_splitting(al);
+  auts = alg_get_auts(al);
+  b = alg_get_b(al);
+
+  xalg = cgetg(n+1, t_COL);
+  for (i=0; i<n; i++) gel(xalg,i+1) = lift(rnfbasistoalg(rnf,gel(x,i+1)));
+
+  yalg = cgetg(n+1, t_COL);
+  for (i=0; i<n; i++) gel(yalg,i+1) = rnfbasistoalg(rnf,gel(y,i+1));
+
+  res = cgetg(n+1,t_COL);
+  for (k=0; k<n; k++) {
+    gel(res,k+1) = gmul(gel(xalg,k+1),gel(yalg,1));
+    for (i=1; i<=k; i++) {
+      autx = poleval(gel(xalg,k-i+1),gel(auts,i));
+      prod = gmul(autx,gel(yalg,i+1));
+      gel(res,k+1) = gadd(gel(res,k+1), prod);
+    }
+
+    sum = gen_0;
+    for (; i<n; i++) {
+      autx = poleval(gel(xalg,k+n-i+1),gel(auts,i));
+      prod = gmul(autx,gel(yalg,i+1));
+      sum = gadd(sum,prod);
+    }
+    sum = gmul(b,sum);
+
+    gel(res,k+1) = gadd(gel(res,k+1),sum);
+  }
+
+  return gerepilecopy(av, res);
+}
+
+static GEN
+_tablemul(GEN mt, GEN x, GEN y)
+{
+  pari_sp av = avma;
+  long D = lg(mt)-1, i;
+  GEN res = NULL;
+  for (i=1; i<=D; i++) {
+    GEN c = gel(x,i);
+    if (!gequal0(c)) {
+      GEN My = RgM_RgC_mul(gel(mt,i),y);
+      GEN t = RgC_Rg_mul(My,c);
+      res = res? RgC_add(res,t): t;
+    }
+  }
+  if (!res) { avma = av; return zerocol(D); }
+  return gerepileupto(av, res);
+}
+
+static GEN
+_tablemul_Fp(GEN mt, GEN x, GEN y, GEN p)
+{
+  pari_sp av = avma;
+  long D = lg(mt)-1, i;
+  GEN res = NULL;
+  for (i=1; i<=D; i++) {
+    GEN c = gel(x,i);
+    if (signe(c)) {
+      GEN My = FpM_FpC_mul(gel(mt,i),y,p);
+      GEN t = FpC_Fp_mul(My,c,p);
+      res = res? FpC_add(res,t,p): t;
+    }
+  }
+  if (!res) { avma = av; return zerocol(D); }
+  return gerepileupto(av, res);
+}
+
+/* x*ej */
+static GEN
+_tablemul_ej(GEN mt, GEN x, long j)
+{
+  pari_sp av = avma;
+  long D = lg(mt)-1, i;
+  GEN res = NULL;
+  for (i=1; i<=D; i++) {
+    GEN c = gel(x,i);
+    if (!gequal0(c)) {
+      GEN My = gel(gel(mt,i),j);
+      GEN t = RgC_Rg_mul(My,c);
+      res = res? RgC_add(res,t): t;
+    }
+  }
+  if (!res) { avma = av; return zerocol(D); }
+  return gerepileupto(av, res);
+}
+static GEN
+_tablemul_ej_Fp(GEN mt, GEN x, long j, GEN p)
+{
+  pari_sp av = avma;
+  long D = lg(mt)-1, i;
+  GEN res = NULL;
+  for (i=1; i<=D; i++) {
+    GEN c = gel(x,i);
+    if (!gequal0(c)) {
+      GEN My = gel(gel(mt,i),j);
+      GEN t = FpC_Fp_mul(My,c,p);
+      res = res? FpC_add(res,t,p): t;
+    }
+  }
+  if (!res) { avma = av; return zerocol(D); }
+  return gerepileupto(av, res);
+}
+#if 0
+GEN
+algbasismul_ej(GEN al, GEN x, long j) /* not used */
+{ return _tablemul_ej(alg_get_multable(al), x, j); }
+#endif
+static GEN
+_tablemul_ej_Fl(GEN mt, GEN x, long j, ulong p)
+{
+  pari_sp av = avma;
+  long D = lg(mt)-1, i;
+  GEN res = NULL;
+  for (i=1; i<=D; i++) {
+    ulong c = x[i];
+    if (c) {
+      GEN My = gel(gel(mt,i),j);
+      GEN t = Flc_Fl_mul(My,c, p);
+      res = res? Flv_add(res,t, p): t;
+    }
+  }
+  if (!res) { avma = av; return zero_Flv(D); }
+  return gerepileupto(av, res);
+}
+
+static GEN
+algalgmul_csa(GEN al, GEN x, GEN y)
+{ return _tablemul(alg_get_relmultable(al), x, y); }
+
+/* assumes x and y in algebraic form */
+static GEN
+algalgmul(GEN al, GEN x, GEN y)
+{
+  switch(alg_type(al))
+  {
+    case al_CYCLIC: return algalgmul_cyc(al, x, y);
+    case al_CSA: return algalgmul_csa(al, x, y);
+  }
+  return NULL; /*not reached*/
+}
+
+GEN
+algbasismul(GEN al, GEN x, GEN y)
+{
+  GEN mt = alg_get_multable(al), p = alg_get_char(al);
+  if (signe(p)) return _tablemul_Fp(mt, x, y, p);
+  return _tablemul(mt, x, y);
+}
+
+/* x[i,]*y. Assume lg(x) > 1 and 0 < i < lgcols(x) */
+static GEN
+alMrow_alC_mul_i(GEN al, GEN x, GEN y, long i, long lx)
+{
+  pari_sp av = avma;
+  GEN c = algmul(al,gcoeff(x,i,1),gel(y,1)), ZERO;
+  long k;
+  ZERO = zerocol(alg_get_absdim(al));
+  for (k = 2; k < lx; k++)
+  {
+    GEN t = algmul(al, gcoeff(x,i,k), gel(y,k));
+    if (!gequal(t,ZERO)) c = algadd(al, c, t);
+  }
+  return gerepilecopy(av, c);
+}
+/* return x * y, 1 < lx = lg(x), l = lgcols(x) */
+static GEN
+alM_alC_mul_i(GEN al, GEN x, GEN y, long lx, long l)
+{
+  GEN z = cgetg(l,t_COL);
+  long i;
+  for (i=1; i<l; i++) gel(z,i) = alMrow_alC_mul_i(al,x,y,i,lx);
+  return z;
+}
+static GEN
+alM_mul(GEN al, GEN x, GEN y)
+{
+  long j, l, lx=lg(x), ly=lg(y);
+  GEN z;
+  if (ly==1) return cgetg(1,t_MAT);
+  if (lx != lgcols(y)) pari_err_DIM("alM_mul");
+  if (lx==1) return zeromat(0, ly-1);
+  l = lgcols(x); z = cgetg(ly,t_MAT);
+  for (j=1; j<ly; j++) gel(z,j) = alM_alC_mul_i(al,x,gel(y,j),lx,l);
+  return z;
+}
+
+GEN
+algmul(GEN al, GEN x, GEN y)
+{
+  pari_sp av = avma;
+  long tx, ty;
+  checkalg(al);
+  tx = alg_model(al,x);
+  ty = alg_model(al,y);
+  if (tx==al_MATRIX) {
+    if (ty==al_MATRIX) return alM_mul(al,x,y);
+    pari_err_TYPE("algmul", y);
+  }
+  if (signe(alg_get_char(al))) return algbasismul(al,x,y);
+  if (tx==al_TRIVIAL) return gerepilecopy(av,mkcol(gmul(gel(x,1),gel(y,1))));
+  if (tx==al_ALGEBRAIC && ty==al_ALGEBRAIC) return algalgmul(al,x,y);
+  if (tx==al_ALGEBRAIC) x = algalgtobasis(al,x);
+  if (ty==al_ALGEBRAIC) y = algalgtobasis(al,y);
+  return gerepileupto(av,algbasismul(al,x,y));
+}
+
+GEN
+algsqr(GEN al, GEN x)
+{
+  pari_sp av = avma;
+  long tx;
+  checkalg(al);
+  tx = alg_model(al,x);
+  if (signe(alg_get_char(al))) return algbasismul(al,x,x);
+  if (tx==al_TRIVIAL) return gerepilecopy(av,mkcol(gsqr(gel(x,1))));
+  if (tx==al_ALGEBRAIC) return algalgmul(al,x,x);
+  if (tx==al_MATRIX) return gerepilecopy(av,alM_mul(al,x,x));
+  return gerepileupto(av,algbasismul(al,x,x));
+}
+
+static GEN
+algmtK2Z_cyc(GEN al, GEN m)
+{
+  pari_sp av = avma;
+  GEN nf = alg_get_abssplitting(al), res, mt, rnf = alg_get_splitting(al), c, dc;
+  long n = alg_get_degree(al), N = nf_get_degree(nf), Nn, i, j, i1, j1;
+  Nn = N*n;
+  res = zeromatcopy(Nn,Nn);
+  for (i=0; i<n; i++)
+  for (j=0; j<n; j++) {
+    c = gcoeff(m,i+1,j+1);
+    if (!gequal0(c)) {
+      c = rnfeltreltoabs(rnf,c);
+      c = algtobasis(nf,c);
+      c = Q_remove_denom(c,&dc);
+      mt = zk_multable(nf,c);
+      if (dc) mt = ZM_Z_div(mt,dc);
+      for (i1=1; i1<=N; i1++)
+      for (j1=1; j1<=N; j1++)
+        gcoeff(res,i*N+i1,j*N+j1) = gcoeff(mt,i1,j1);
+    }
+  }
+  return gerepilecopy(av,res);
+}
+
+static GEN
+algmtK2Z_csa(GEN al, GEN m)
+{
+  pari_sp av = avma;
+  GEN nf = alg_get_center(al), res, mt, c, dc;
+  long d2 = alg_get_dim(al), n = nf_get_degree(nf), D, i, j, i1, j1;
+  D = d2*n;
+  res = zeromatcopy(D,D);
+  for (i=0; i<d2; i++)
+  for (j=0; j<d2; j++) {
+    c = gcoeff(m,i+1,j+1);
+    if (!gequal0(c)) {
+      c = algtobasis(nf,c);
+      c = Q_remove_denom(c,&dc);
+      mt = zk_multable(nf,c);
+      if (dc) mt = ZM_Z_div(mt,dc);
+      for (i1=1; i1<=n; i1++)
+      for (j1=1; j1<=n; j1++)
+        gcoeff(res,i*n+i1,j*n+j1) = gcoeff(mt,i1,j1);
+    }
+  }
+  return gerepilecopy(av,res);
+}
+
+/* assumes al is a CSA or CYCLIC */
+static GEN
+algmtK2Z(GEN al, GEN m)
+{
+  switch(alg_type(al))
+  {
+    case al_CYCLIC: return algmtK2Z_cyc(al, m);
+    case al_CSA: return algmtK2Z_csa(al, m);
+  }
+  return NULL; /*not reached*/
+}
+
+/* left multiplication table, as a vector space of dimension n over the splitting field (by right multiplication) */
+static GEN
+algalgmultable_cyc(GEN al, GEN x)
+{
+  pari_sp av = avma;
+  long n = alg_get_degree(al), i, j;
+  GEN res, rnf, auts, b, pol;
+  rnf = alg_get_splitting(al);
+  auts = alg_get_auts(al);
+  b = alg_get_b(al);
+  pol = rnf_get_pol(rnf);
+
+  res = zeromatcopy(n,n);
+  for (i=0; i<n; i++)
+    gcoeff(res,i+1,1) = lift(rnfbasistoalg(rnf,gel(x,i+1)));
+
+  for (i=0; i<n; i++) {
+    for (j=1; j<=i; j++)
+      gcoeff(res,i+1,j+1) = gmodulo(poleval(gcoeff(res,i-j+1,1),gel(auts,j)),pol);
+    for (; j<n; j++)
+      gcoeff(res,i+1,j+1) = gmodulo(gmul(b,poleval(gcoeff(res,n+i-j+1,1),gel(auts,j))), pol);
+  }
+
+  for (i=0; i<n; i++)
+    gcoeff(res,i+1,1) = gmodulo(gcoeff(res,i+1,1),pol);
+
+  return gerepilecopy(av, res);
+}
+
+static GEN
+elementmultable(GEN mt, GEN x)
+{
+  pari_sp av = avma;
+  long D = lg(mt)-1, i;
+  GEN res, c;
+  res = zeromatcopy(D,D);
+  for (i=1; i<=D; i++) {
+    c = gel(x,i);
+    if (!gequal0(c)) res = RgM_add(res, RgM_Rg_mul(gel(mt,i),c));
+  }
+  return gerepileupto(av, res);
+}
+
+static GEN
+elementabsmultable(GEN mt, GEN x)
+{
+  pari_sp av = avma;
+  long D = lg(mt)-1, i;
+  GEN res, c, d=NULL;
+  res = zeromatcopy(D,D);
+  x = Q_remove_denom(x, &d);
+  for (i=1; i<=D; i++) {
+    c = gel(x,i);
+    if (!gequal0(c)) res = ZM_add(res, ZM_Z_mul(gel(mt,i),c));
+  }
+  if (d) res = ZM_Z_div(res, d);
+  return gerepileupto(av, res);
+}
+
+static GEN
+elementabsmultable_Fp(GEN mt, GEN x, GEN p)
+{
+  pari_sp av = avma;
+  long D = lg(mt)-1, i;
+  GEN res, c;
+  res = zeromatcopy(D,D);
+  for (i=1; i<=D; i++) {
+    c = gel(x,i);
+    if (!gequal0(c)) res = FpM_add(res, FpM_Fp_mul(gel(mt,i),c,p), p);
+  }
+  return gerepileupto(av, res);
+}
+
+static GEN
+algalgmultable_csa(GEN al, GEN x)
+{
+  return elementmultable(alg_get_relmultable(al), x);
+}
+
+/* assumes x in algebraic form */
+static GEN
+algalgmultable(GEN al, GEN x)
+{
+  switch(alg_type(al))
+  {
+    case al_CYCLIC: return algalgmultable_cyc(al, x);
+    case al_CSA: return algalgmultable_csa(al, x);
+  }
+  return NULL; /*not reached*/
+}
+
+/* on the natural basis */
+/* assumes x in algebraic form */
+static GEN
+algZmultable(GEN al, GEN x) {
+  pari_sp av = avma;
+  GEN res = NULL, x0;
+  long tx = alg_model(al,x);
+  switch(tx) {
+    case al_TRIVIAL:
+      x0 = gel(x,1);
+      if(typ(x0)==t_POLMOD) x0 = gel(x0,2);
+      if(typ(x0)==t_POL) x0 = constant_term(x0);
+      res = mkmatcopy(mkcol(x0));
+      break;
+    case al_ALGEBRAIC: res = algmtK2Z(al,algalgmultable(al,x)); break;
+  }
+  return gerepileupto(av,res);
+}
+
+static GEN
+algbasisrightmultable(GEN al, GEN x)
+{
+  long N = alg_get_absdim(al), i,j,k;
+  GEN res = zeromatcopy(N,N), c, mt = alg_get_multable(al);
+  for(i=1; i<=N; i++) {
+    c = gel(x,i);
+    if (!gequal0(c)) {
+      for(j=1; j<=N; j++)
+      for(k=1; k<=N; k++)
+        gcoeff(res,k,j) = addii(gcoeff(res,k,j), mulii(c, gcoeff(gel(mt,j),k,i)));
+    }
+  }
+  return res;
+}
+
+GEN
+algbasismultable(GEN al, GEN x)
+{
+  GEN p = alg_get_char(al);
+  if (signe(p)) return elementabsmultable_Fp(alg_get_multable(al), x, p);
+  return elementabsmultable(alg_get_multable(al), x);
+}
+/* mt a t_VEC of Flm modulo m */
+GEN
+algbasismultable_Flm(GEN mt, GEN x, ulong m)
+{
+  pari_sp av = avma;
+  long D = lg(gel(mt,1))-1, i;
+  GEN res = NULL;
+  for (i=1; i<=D; i++) {
+    ulong c = x[i];
+    GEN M = Flm_Fl_mul(gel(mt,i),c, m);
+    if (c) res = res? Flm_add(res, M, m): M;
+  }
+  if (!res) { avma = av; return zero_Flm(D,D); }
+  return gerepileupto(av, res);
+}
+
+/* basis for matrices : 1, E_{i,j} for (i,j)!=(1,1) */
+/* index : ijk = ((i-1)*N+j-1)*n + k */
+/* square matrices only, coefficients in basis form, shallow function */
+static GEN
+algmat2basis(GEN al, GEN M)
+{
+  long n = alg_get_absdim(al), N = lg(M)-1, i, j, k, ij, ijk;
+  GEN res, x;
+  res = zerocol(N*N*n);
+  for(i=1; i<=N; i++) {
+    for(j=1, ij=(i-1)*N+1; j<=N; j++, ij++) {
+      x = gcoeff(M,i,j);
+      for(k=1, ijk=(ij-1)*n+1; k<=n; k++, ijk++) {
+        gel(res, ijk) = gel(x, k);
+        if (i>1 && i==j) gel(res, ijk) = gsub(gel(res,ijk), gel(res,k));
+      }
+    }
+  }
+
+  return res;
+}
+
+static GEN
+algbasis2mat(GEN al, GEN M, long N)
+{
+  long n = alg_get_absdim(al), i, j, k, ij, ijk;
+  GEN res, x;
+  res = zeromatcopy(N,N);
+  for(i=1; i<=N; i++)
+  for(j=1; j<=N; j++)
+    gcoeff(res,i,j) = zerocol(n);
+
+  for(i=1; i<=N; i++) {
+    for(j=1, ij=(i-1)*N+1; j<=N; j++, ij++) {
+      x = gcoeff(res,i,j);
+      for(k=1, ijk=(ij-1)*n+1; k<=n; k++, ijk++) {
+        gel(x,k) = gel(M,ijk);
+        if (i>1 && i==j) gel(x,k) = gadd(gel(x,k), gel(M,k));
+      }
+    }
+  }
+
+  return res;
+}
+
+static GEN
+algmatbasis_ei(GEN al, long ijk, long N)
+{
+  long n = alg_get_absdim(al), i, j, k, ij;
+  GEN res;
+
+  res = zeromatcopy(N,N);
+  for(i=1; i<=N; i++)
+  for(j=1; j<=N; j++)
+    gcoeff(res,i,j) = zerocol(n);
+
+  k = ijk%n;
+  if(k==0) k=n;
+  ij = (ijk-k)/n+1;
+
+  if (ij==1) {
+    for(i=1; i<=N; i++)
+      gcoeff(res,i,i) = col_ei(n,k);
+    return res;
+  }
+
+  j = ij%N;
+  if(j==0) j=N;
+  i = (ij-j)/N+1;
+
+  gcoeff(res,i,j) = col_ei(n,k);
+  return res;
+}
+
+/* FIXME lazy implementation ! */
+static GEN
+algmultable_mat(GEN al, GEN M)
+{
+  long N = lg(M)-1, n = alg_get_absdim(al), D = N*N*n, j;
+  GEN res, x, Mx;
+  if (N == 0) return cgetg(1, t_MAT);
+  if (N != nbrows(M)) pari_err_DIM("algmultable_mat (nonsquare)");
+  res = cgetg(D+1, t_MAT);
+  for(j=1; j<=D; j++) {
+    x = algmatbasis_ei(al, j, N);
+    Mx = algmul(al, M, x);
+    gel(res, j) = algmat2basis(al, Mx);
+  }
+  return res;
+}
+
+/* left multiplication table on elements of the same model as x */
+GEN
+algmultable(GEN al, GEN x)
+{
+  pari_sp av = avma;
+  long tx;
+  GEN res;
+  checkalg(al);
+  tx = alg_model(al,x);
+  switch(tx) {
+    case al_TRIVIAL : res = mkmatcopy(mkcol(gel(x,1))); break;
+    case al_ALGEBRAIC : res = algalgmultable(al,x); break;
+    case al_BASIS : res = algbasismultable(al,x); break;
+    case al_MATRIX : res = algmultable_mat(al,x); break;
+    default : return NULL; /* not reached */
+  }
+  return gerepileupto(av,res);
+}
+
+GEN
+gp_algmultable(GEN al, GEN x)
+{
+  if(x) return algmultable(al,x);
+  return alggetmultable(al);
+}
+
+static GEN
+algbasissplittingmatrix_csa(GEN al, GEN x)
+{
+  long d = alg_get_degree(al), i, j;
+  GEN rnf = alg_get_splitting(al), splba = alg_get_splittingbasis(al), splbainv = alg_get_splittingbasisinv(al), M;
+  M = algbasismultable(al,x);
+  M = RgM_mul(M, splba); /* TODO best order ? big matrix /Q vs small matrix /nf */
+  M = RgM_mul(splbainv, M);
+  for(i=1; i<=d; i++)
+  for(j=1; j<=d; j++)
+    gcoeff(M,i,j) = rnfeltabstorel(rnf, gcoeff(M,i,j));
+  return M;
+}
+
+GEN
+algsplittingmatrix(GEN al, GEN x)
+{
+  pari_sp av = avma;
+  GEN res = NULL;
+  long tx, i, j;
+  checkalg(al);
+  tx = alg_model(al,x);
+  if (tx==al_MATRIX) {
+    if (lg(x) == 1) return cgetg(1, t_MAT);
+    res = zeromatcopy(nbrows(x),lg(x)-1);
+    for(j=1; j<lg(x); j++)
+    for(i=1; i<lgcols(x); i++)
+      gcoeff(res,i,j) = algsplittingmatrix(al,gcoeff(x,i,j));
+    res = shallowmatconcat(res);
+  }
+  else switch(alg_type(al))
+  {
+    case al_CYCLIC:
+      if (tx==al_BASIS) x = algbasistoalg(al,x);
+      res = algalgmultable(al,x);
+      break;
+    case al_CSA:
+      if (tx==al_ALGEBRAIC) x = algalgtobasis(al,x);
+      res = algbasissplittingmatrix_csa(al,x);
+      break;
+    default:
+      pari_err_DOMAIN("algsplittingmatrix", "alg_type(al)", "=", stoi(alg_type(al)), stoi(alg_type(al)));
+  }
+  return gerepilecopy(av,res);
+}
+
+/*  x^(-1)*y, NULL if no solution */
+static GEN
+algdivl_i(GEN al, GEN x, GEN y, long tx, long ty) {
+  pari_sp av = avma;
+  GEN res, p = alg_get_char(al);
+  if (tx != ty) {
+    if (tx==al_ALGEBRAIC) x = algalgtobasis(al,x);
+    if (ty==al_ALGEBRAIC) y = algalgtobasis(al,y);
+  }
+  if (ty == al_MATRIX) y = algmat2basis(al,y);
+  if (signe(p)) res = FpM_FpC_invimage(algmultable(al,x),y,p);
+  else          res = inverseimage(algmultable(al,x),y);
+  if (!res || lg(res)==1) { avma = av; return NULL; }
+  if (tx == al_MATRIX) {
+    res = algbasis2mat(al, res, lg(x)-1);
+    return gerepilecopy(av,res);
+  }
+  return gerepileupto(av,res);
+}
+static GEN
+algdivl_i2(GEN al, GEN x, GEN y)
+{
+  long tx, ty;
+  checkalg(al);
+  tx = alg_model(al,x);
+  ty = alg_model(al,y);
+  if (tx == al_MATRIX) {
+    if (ty != al_MATRIX) pari_err_TYPE2("\\", x, y);
+    if (lg(y) == 1) return cgetg(1, t_MAT);
+    if (lg(x) == 1) return NULL;
+    if (lgcols(x) != lgcols(y)) pari_err_DIM("algdivl");
+    if (lg(x) != lgcols(x) || lg(y) != lgcols(y))
+      pari_err_DIM("algdivl (nonsquare)");
+  }
+  return algdivl_i(al,x,y,tx,ty);
+}
+
+GEN algdivl(GEN al, GEN x, GEN y)
+{
+  GEN z;
+  z = algdivl_i2(al,x,y);
+  if (!z) pari_err_INV("algdivl", x);
+  return z;
+}
+
+int
+algisdivl(GEN al, GEN x, GEN y, GEN* ptz)
+{
+  pari_sp av = avma;
+  GEN z;
+  z = algdivl_i2(al,x,y);
+  if (!z) { avma = av; return 0; }
+  if (ptz != NULL) *ptz = z;
+  return 1;
+}
+
+static GEN
+alginv_i(GEN al, GEN x)
+{
+  pari_sp av = avma;
+  GEN res = NULL, p = alg_get_char(al);
+  long tx = alg_model(al,x), n;
+  switch(tx) {
+    case al_TRIVIAL :
+      if (signe(p)) { res = mkcol(Fp_inv(gel(x,1),p)); break; }
+      else          { res = mkcol(ginv(gel(x,1))); break; }
+    case al_ALGEBRAIC :
+      switch(alg_type(al)) {
+        case al_CYCLIC: n = alg_get_degree(al); break;
+        case al_CSA: n = alg_get_dim(al); break;
+        default: return NULL; /* not reached */
+      }
+      res = algdivl_i(al, x, col_ei(n,1), tx, al_ALGEBRAIC); break;
+    case al_BASIS : res = algdivl_i(al, x, col_ei(alg_get_absdim(al),1), tx, al_BASIS); break;
+    case al_MATRIX :
+      n = lg(x)-1;
+      if (n==0) return cgetg(1, t_MAT);
+      if (n != nbrows(x)) pari_err_DIM("alginv_i (nonsquare)");
+      res = algdivl_i(al, x, col_ei(n*n*alg_get_absdim(al),1), tx, al_BASIS); /* cheat on type because wrong dimension */
+  }
+  if (!res) { avma = av; return NULL; }
+  return gerepilecopy(av,res);
+}
+GEN
+alginv(GEN al, GEN x)
+{
+  GEN z;
+  checkalg(al);
+  z = alginv_i(al,x);
+  if (!z) pari_err_INV("alginv", x);
+  return z;
+}
+
+int
+algisinv(GEN al, GEN x, GEN* ptix)
+{
+  pari_sp av = avma;
+  GEN ix;
+  checkalg(al);
+  ix = alginv_i(al,x);
+  if (!ix) { avma = av; return 0; }
+  if (ptix != NULL) *ptix = ix;
+  return 1;
+}
+
+/*  x*y^(-1)  */
+GEN
+algdivr(GEN al, GEN x, GEN y) { return algmul(al, x, alginv(al, y)); }
+
+static GEN _mul(void* data, GEN x, GEN y) { return algmul((GEN)data,x,y); }
+static GEN _sqr(void* data, GEN x) { return algsqr((GEN)data,x); }
+
+static GEN
+algmatid(GEN al, long N)
+{
+  pari_sp av = avma;
+  long n = alg_get_absdim(al), i, j;
+  GEN res, one, zero;
+
+  one = col_ei(n,1);
+  zero = zerocol(n);
+  res = zeromatcopy(N,N);
+  for(i=1; i<=N; i++)
+  for(j=1; j<=N; j++)
+    gcoeff(res,i,j) = i==j ? one : zero;
+  return gerepilecopy(av,res);
+}
+
+GEN
+algpow(GEN al, GEN x, GEN n)
+{
+  pari_sp av = avma;
+  GEN res;
+  checkalg(al);
+  switch(signe(n)) {
+    case 0 :
+      if (alg_model(al,x) == al_MATRIX)
+                        res = algmatid(al,lg(x)-1);
+      else              res = col_ei(alg_get_absdim(al),1);
+      break;
+    case 1 :            res = gen_pow(x, n, (void*)al, _sqr, _mul); break;
+    default : /*-1*/    res = gen_pow(alginv(al,x), gneg(n), (void*)al, _sqr, _mul);
+  }
+  return gerepileupto(av,res);
+}
+
+static GEN
+algredcharpoly_i(GEN al, GEN x, long v)
+{
+  GEN rnf = alg_get_splitting(al);
+  GEN cp = charpoly(algsplittingmatrix(al,x),v);
+  long i, m = lg(cp);
+  for (i=2; i<m; i++) gel(cp,i) = rnfeltdown(rnf, gel(cp,i));
+  return cp;
+}
+
+/* assumes al is CSA or CYCLIC */
+static GEN
+algredcharpoly(GEN al, GEN x, long v)
+{
+  pari_sp av = avma;
+  switch(alg_type(al))
+  {
+    case al_CYCLIC:
+    case al_CSA:
+      return gerepileupto(av, algredcharpoly_i(al, x, v));
+  }
+  return NULL; /*not reached*/
+}
+
+GEN
+algbasischarpoly(GEN al, GEN x, long v)
+{
+  pari_sp av = avma;
+  GEN p = alg_get_char(al), mx;
+  if (alg_model(al,x) == al_MATRIX) mx = algmultable_mat(al,x);
+  else                              mx = algbasismultable(al,x);
+  if (signe(p)) {
+    GEN res = FpM_charpoly(mx,p);
+    setvarn(res,v);
+    return gerepileupto(av, res);
+  }
+  return gerepileupto(av, charpoly(mx,v));
+}
+
+GEN
+algcharpoly(GEN al, GEN x, long v)
+{
+  checkalg(al);
+  if (v<0) v=0;
+
+  /* gneg(x[1]) left on stack */
+  if (alg_model(al,x) == al_TRIVIAL) {
+    GEN p = alg_get_char(al);
+    if (signe(p)) return deg1pol(gen_1,Fp_neg(gel(x,1),p),v);
+    return deg1pol(gen_1,gneg(gel(x,1)),v);
+  }
+
+  switch(alg_type(al)) {
+    case al_CYCLIC: case al_CSA: return algredcharpoly(al,x,v);
+    case al_TABLE: return algbasischarpoly(al,x,v);
+    default : return NULL; /* not reached */
+  }
+}
+
+/* assumes x in basis form */
+static GEN
+algabstrace(GEN al, GEN x)
+{
+  pari_sp av = avma;
+  GEN res = NULL, p = alg_get_char(al);
+  if (signe(p)) return FpV_dotproduct(x, alg_get_tracebasis(al), p);
+  switch(alg_model(al,x)) {
+    case al_TRIVIAL: return gcopy(gel(x,1)); break;
+    case al_BASIS: res = RgV_dotproduct(x, alg_get_tracebasis(al)); break;
+  }
+  return gerepileupto(av,res);
+}
+
+static GEN
+algredtrace(GEN al, GEN x)
+{
+  pari_sp av = avma;
+  GEN res = NULL;
+  switch(alg_model(al,x)) {
+    case al_TRIVIAL: return gcopy(gel(x,1)); break;
+    case al_BASIS: return algredtrace(al, algbasistoalg(al,x)); /* TODO precompute too? */
+    case al_ALGEBRAIC:
+      switch(alg_type(al))
+      {
+        case al_CYCLIC:
+          res = rnfelttrace(alg_get_splitting(al),gel(x,1));
+          break;
+        case al_CSA:
+          res = gtrace(algalgmultable_csa(al,x));
+          res = gdiv(res, stoi(alg_get_degree(al)));
+          break;
+        default: return NULL; /* not reached */
+      }
+  }
+  return gerepileupto(av,res);
+}
+
+static GEN
+algtrace_mat(GEN al, GEN M) {
+  pari_sp av = avma;
+  long N = lg(M)-1, i;
+  GEN res, p = alg_get_char(al);
+  if (N == 0) {avma = av; return gen_0;}
+  if (N != nbrows(M)) pari_err_DIM("algtrace_mat (nonsquare)");
+
+  if(!signe(p)) p = NULL;
+  res = algtrace(al, gcoeff(M,1,1));
+  for(i=2; i<=N; i++) {
+    if (p)  res = Fp_add(res, algtrace(al,gcoeff(M,i,i)), p);
+    else    res = gadd(res, algtrace(al,gcoeff(M,i,i)));
+  }
+  if (alg_type(al) == al_TABLE) res = gmulgs(res, N); /* absolute trace */
+  return gerepilecopy(av, res);
+}
+
+GEN
+algtrace(GEN al, GEN x)
+{
+  checkalg(al);
+  if (alg_model(al,x) == al_MATRIX) return algtrace_mat(al,x);
+  switch(alg_type(al)) {
+    case al_CYCLIC: case al_CSA: return algredtrace(al,x);
+    case al_TABLE: return algabstrace(al,x);
+    default : return NULL; /* not reached */
+  }
+}
+
+static GEN
+ZM_trace(GEN x)
+{
+  long i, lx = lg(x);
+  GEN t;
+  if (lx < 3) return lx == 1? gen_0: gcopy(gcoeff(x,1,1));
+  t = gcoeff(x,1,1);
+  for (i = 2; i < lx; i++) t = addii(t, gcoeff(x,i,i));
+  return t;
+}
+static GEN
+FpM_trace(GEN x, GEN p)
+{
+  long i, lx = lg(x);
+  GEN t;
+  if (lx < 3) return lx == 1? gen_0: gcopy(gcoeff(x,1,1));
+  t = gcoeff(x,1,1);
+  for (i = 2; i < lx; i++) t = Fp_add(t, gcoeff(x,i,i), p);
+  return t;
+}
+
+static GEN
+algtracebasis(GEN al)
+{
+  pari_sp av = avma;
+  GEN mt = alg_get_multable(al), p = alg_get_char(al);
+  long i, l = lg(mt);
+  GEN v = cgetg(l, t_VEC);
+  if (signe(p)) for (i=1; i < l; i++) gel(v,i) = FpM_trace(gel(mt,i), p);
+  else          for (i=1; i < l; i++) gel(v,i) = ZM_trace(gel(mt,i));
+  return gerepileupto(av,v);
+}
+
+/* Assume: i > 0, expo := p^i <= absdim, x contained in I_{i-1} given by mult
+ * table modulo modu=p^(i+1). Return Tr(x^(p^i)) mod modu */
+static ulong
+algtracei(GEN mt, ulong p, ulong expo, ulong modu)
+{
+  pari_sp av = avma;
+  long j, l = lg(mt);
+  ulong tr = 0;
+  mt = Flm_powu(mt,expo,modu);
+  for (j=1; j<l; j++) tr += ucoeff(mt,j,j);
+  avma = av; return (tr/expo) % p;
+}
+
+GEN
+algnorm(GEN al, GEN x)
+{
+  pari_sp av = avma;
+  long tx;
+  GEN p, rnf, res, mx;
+  checkalg(al);
+  p = alg_get_char(al);
+  tx = alg_model(al,x);
+  if (signe(p)) {
+    if (tx == al_MATRIX)    mx = algmultable_mat(al,x);
+    else                    mx = algbasismultable(al,x);
+    return gerepileupto(av, FpM_det(mx,p));
+  }
+  if (tx == al_TRIVIAL) return gcopy(gel(x,1));
+
+  switch(alg_type(al)) {
+    case al_CYCLIC: case al_CSA:
+      rnf = alg_get_splitting(al);
+      res = rnfeltdown(rnf, det(algsplittingmatrix(al,x)));
+      break;
+    case al_TABLE:
+      if (tx == al_MATRIX)  mx = algmultable_mat(al,x);
+      else                  mx = algbasismultable(al,x);
+      res = det(mx);
+      break;
+    default: return NULL; /* not reached */
+  }
+  return gerepileupto(av, res);
+}
+
+static GEN
+algalgtonat_cyc(GEN al, GEN x)
+{
+  pari_sp av = avma;
+  GEN nf = alg_get_abssplitting(al), rnf = alg_get_splitting(al), res, c;
+  long n = alg_get_degree(al), N = nf_get_degree(nf), i, i1;
+  res = zerocol(N*n);
+  for (i=0; i<n; i++) {
+    c = gel(x,i+1);
+    c = rnfeltreltoabs(rnf,c);
+    if (!gequal0(c)) {
+      c = algtobasis(nf,c);
+      for (i1=1; i1<=N; i1++) gel(res,i*N+i1) = gel(c,i1);
+    }
+  }
+  return gerepilecopy(av, res);
+}
+
+static GEN
+algalgtonat_csa(GEN al, GEN x)
+{
+  pari_sp av = avma;
+  GEN nf = alg_get_center(al), res, c;
+  long d2 = alg_get_dim(al), n = nf_get_degree(nf), i, i1;
+  res = zerocol(d2*n);
+  for (i=0; i<d2; i++) {
+    c = gel(x,i+1);
+    if (!gequal0(c)) {
+      c = algtobasis(nf,c);
+      for (i1=1; i1<=n; i1++) gel(res,i*n+i1) = gel(c,i1);
+    }
+  }
+  return gerepilecopy(av, res);
+}
+
+/* assumes al CSA or CYCLIC */
+static GEN
+algalgtonat(GEN al, GEN x)
+{
+  switch(alg_type(al))
+  {
+    case al_CYCLIC: return algalgtonat_cyc(al, x);
+    case al_CSA: return algalgtonat_csa(al, x);
+  }
+  return NULL; /*not reached*/
+}
+
+static GEN
+algnattoalg_cyc(GEN al, GEN x)
+{
+  pari_sp av = avma;
+  GEN nf = alg_get_abssplitting(al), rnf = alg_get_splitting(al), res, c;
+  long n = alg_get_degree(al), N = nf_get_degree(nf), i, i1;
+  res = zerocol(n);
+  c = zerocol(N);
+  for (i=0; i<n; i++) {
+    for (i1=1; i1<=N; i1++) gel(c,i1) = gel(x,i*N+i1);
+    gel(res,i+1) = rnfeltabstorel(rnf,basistoalg(nf,c));
+  }
+  return gerepilecopy(av, res);
+}
+
+static GEN
+algnattoalg_csa(GEN al, GEN x)
+{
+  pari_sp av = avma;
+  GEN nf = alg_get_center(al), res, c;
+  long d2 = alg_get_dim(al), n = nf_get_degree(nf), i, i1;
+  res = zerocol(d2);
+  c = zerocol(n);
+  for (i=0; i<d2; i++) {
+    for (i1=1; i1<=n; i1++) gel(c,i1) = gel(x,i*n+i1);
+    gel(res,i+1) = basistoalg(nf,c);
+  }
+  return gerepilecopy(av, res);
+}
+
+/* assumes al CSA or CYCLIC */
+static GEN
+algnattoalg(GEN al, GEN x)
+{
+  switch(alg_type(al))
+  {
+    case al_CYCLIC: return algnattoalg_cyc(al, x);
+    case al_CSA: return algnattoalg_csa(al, x);
+  }
+  return NULL; /*not reached*/
+}
+
+static GEN
+algalgtobasis_mat(GEN al, GEN x) /* componentwise */
+{
+  pari_sp av = avma;
+  long lx, lxj, i, j;
+  GEN res;
+  lx = lg(x);
+  res = cgetg(lx, t_MAT);
+  for(j=1; j<lx; j++) {
+    lxj = lg(gel(x,j));
+    gel(res,j) = cgetg(lxj, t_COL);
+    for(i=1; i<lxj; i++)
+      gcoeff(res,i,j) = algalgtobasis(al,gcoeff(x,i,j));
+  }
+  return gerepilecopy(av,res);
+}
+GEN
+algalgtobasis(GEN al, GEN x)
+{
+  pari_sp av;
+  long tx;
+  checkalg(al);
+  if (alg_type(al) == al_TABLE) pari_err_TYPE("algalgtobasis [use alginit]", al);
+  tx = alg_model(al,x);
+  if (tx==al_BASIS) return gcopy(x);
+  if (tx==al_MATRIX) return algalgtobasis_mat(al,x);
+  av = avma;
+  x = algalgtonat(al,x);
+  x = RgM_RgC_mul(alg_get_invord(al),x);
+  return gerepileupto(av, x);
+}
+
+static GEN
+algbasistoalg_mat(GEN al, GEN x) /* componentwise */
+{
+  pari_sp av = avma;
+  long lx, lxj, i, j;
+  GEN res;
+  lx = lg(x);
+  res = cgetg(lx, t_MAT);
+  for(j=1; j<lx; j++) {
+    lxj = lg(gel(x,j));
+    gel(res,j) = cgetg(lxj, t_COL);
+    for(i=1; i<lxj; i++)
+      gcoeff(res,i,j) = algbasistoalg(al,gcoeff(x,i,j));
+  }
+  return gerepilecopy(av,res);
+}
+GEN
+algbasistoalg(GEN al, GEN x)
+{
+  pari_sp av;
+  long tx;
+  checkalg(al);
+  if (alg_type(al) == al_TABLE) pari_err_TYPE("algbasistoalg [use alginit]", al);
+  tx = alg_model(al,x);
+  if (tx==al_ALGEBRAIC) return gcopy(x);
+  if (tx==al_MATRIX) return algbasistoalg_mat(al,x);
+  av = avma;
+  x = RgM_RgC_mul(alg_get_ord(al),x);
+  x = algnattoalg(al,x);
+  return gerepileupto(av, x);
+}
+
+GEN
+algrandom(GEN al, GEN b)
+{
+  GEN res, p, N;
+  long i, n;
+  if (typ(b) != t_INT) pari_err_TYPE("algrandom",b);
+  if (signe(b)<0) pari_err_DOMAIN("algrandom", "b", "<", gen_0, b);
+  checkalg(al);
+  n = alg_get_absdim(al);
+  N = addiu(shifti(b,1), 1); /* left on stack */
+  p = alg_get_char(al);
+  res = cgetg(n+1,t_COL);
+  for (i=1; i<= n; i++)
+  {
+    pari_sp av = avma;
+    gel(res,i) = gerepileuptoint(av, subii(randomi(N),b));
+  }
+  if (signe(p)) res = FpC_red(res, p); /*FIXME: need garbage collection here?*/
+  return res;
+}
+
+/*Assumes pol has coefficients in the same ring as the COL x; x either
+ * in basis, algebraic or mult. table form.
+ TODO more general version: pol with coeffs in center and x in basis form*/
+GEN
+algpoleval(GEN al, GEN pol, GEN x)
+{
+  pari_sp av = avma;
+  GEN p, mx, res;
+  long i;
+  checkalg(al);
+  p = alg_get_char(al);
+  if (typ(pol) != t_POL) pari_err_TYPE("algpoleval",pol);
+  mx = (typ(x) == t_MAT)? x: algmultable(al,x);
+  res = zerocol(lg(mx)-1);
+  if (signe(p)) {
+    for (i=lg(pol)-1; i>1; i--)
+    {
+      gel(res,1) = Fp_add(gel(res,1), gel(pol,i), p);
+      if (i>2) res = FpM_FpC_mul(mx, res, p);
+    }
+  }
+  else {
+    for (i=lg(pol)-1; i>1; i--)
+    {
+      gel(res,1) = gadd(gel(res,1), gel(pol,i));
+      if (i>2) res = RgM_RgC_mul(mx, res);
+    }
+  }
+  return gerepileupto(av, res);
+}
+
+/** GRUNWALD-WANG **/
+/*
+These de Song Wang (pages des pdf)
+p.25 def de chi_b. K^Ker(chi_b) = K(b^(1/m))
+p.26 borne sur le conducteur (also Cohen adv. p.166)
+p.21 & p.34 description special case, also on wikipedia:
+http://en.wikipedia.org/wiki/Grunwald%E2%80%93Wang_theorem#Special_fields
+p.77 Kummer case
+*/
+
+/* n > 0. Is n = 2^k ? */
+static int
+uispow2(ulong n) { return !(n &(n-1)); }
+
+static GEN
+get_phi0(GEN bnr, GEN Lpr, GEN Ld, GEN pl, long *pr, long *pn)
+{
+  const long NTRY = 10; /* FIXME: magic constant */
+  const long n = (lg(Ld)==1)? 2: vecsmall_max(Ld);
+  GEN S = bnr_get_cyc(bnr);
+  GEN Sst, G, globGmod, loc, X, Rglob, Rloc, H, U, real;
+  long i, j, r, nbreal=0, nbfrob, nbloc, nz, t;
+
+  *pn = n;
+  *pr = r = lg(S)-1;
+  if (!r) return NULL;
+  real = new_chunk(lg(pl)-1);
+  if (uispow2(n))
+    for (i=1; i<lg(pl); i++)
+      if (pl[i]==-1) real[nbreal++] = i;
+  nbfrob = lg(Lpr)-1;
+  nbloc = nbfrob+nbreal;
+
+  /* compute Z/n-dual */
+  Sst = cgetg(r+1, t_VECSMALL);
+  for (i=1; i<=r; i++) Sst[i] = ugcd(umodiu(gel(S,i), n), n);
+  if (Sst[1] != n) return NULL;
+
+  globGmod = cgetg(r+1,t_MAT);
+  G = cgetg(r+1,t_VECSMALL);
+  for (i=1; i<=r; i++)
+  {
+    G[i] = n / Sst[i]; /* pairing between S and Sst */
+    gel(globGmod,i) = cgetg(nbloc+1,t_VECSMALL);
+  }
+
+  /* compute images of Frobenius elements (and complex conjugation) */
+  loc = cgetg(nbloc+1,t_VECSMALL);
+  for (i=1; i<=nbloc; i++) {
+    long L;
+    if (i<=nbfrob)
+    {
+      X = isprincipalray(bnr,gel(Lpr,i));
+      L = Ld[i];
+    }
+    else
+    {
+      X = bnrconj(bnr,real[i-nbfrob-1]);
+      L = 2;
+    }
+    X = ZV_to_Flv(X, n);
+    for (nz=0,j=1; j<=r; j++)
+    {
+      ulong c = (X[j] * G[j]) % L;
+      ucoeff(globGmod,i,j) = c;
+      if (c) nz = 1;
+    }
+    if (!nz) return NULL;
+    loc[i] = L;
+  }
+
+  /* try some random elements in the dual */
+  Rglob = cgetg(r+1,t_VECSMALL);
+  for (t=0; t<NTRY; t++) {
+    for (j=1; j<=r; j++) Rglob[j] = random_Fl(Sst[j]);
+    Rloc = zm_zc_mul(globGmod,Rglob);
+    for (i=1; i<=nbloc; i++)
+      if (Rloc[i] % loc[i] == 0) break;
+    if (i > nbloc)
+      return zv_to_ZV(Rglob);
+  }
+
+  /* try to realize some random elements of the product of the local duals */
+  H = ZM_hnfall(shallowconcat(zm_to_ZM(globGmod),
+                              diagonal_shallow(zv_to_ZV(loc))), &U, 2);
+  /* H,U nbloc x nbloc */
+  Rloc = cgetg(nbloc+1,t_COL);
+  for (t=0; t<NTRY; t++) {
+    /* nonzero random coordinate */ /*TODO add special case ?*/
+    for (i=1; i<=nbloc; i++) gel(Rloc,i) = stoi(1 + random_Fl(loc[i]-1));
+    Rglob = hnf_invimage(H, Rloc);
+    if (Rglob)
+    {
+      Rglob = ZM_ZC_mul(U,Rglob);
+      return vecslice(Rglob,1,r);
+    }
+  }
+  return NULL;
+}
+
+GEN
+bnrgwsearch(GEN bnr, GEN Lpr, GEN Ld, GEN pl)
+{
+  pari_sp av = avma;
+  long n, r;
+  GEN phi0 = get_phi0(bnr,Lpr,Ld,pl, &r,&n), gn, v, H,U;
+  if (!phi0) { avma = av; return gen_0; }
+  gn = stoi(n);
+  /* compute kernel of phi0 */
+  v = ZV_extgcd(shallowconcat(phi0, gn));
+  U = vecslice(gel(v,2), 1,r);
+  H = ZM_hnfmodid(rowslice(U, 1,r), gn);
+  return gerepileupto(av, H);
+}
+
+GEN
+bnfgwgeneric(GEN bnf, GEN Lpr, GEN Ld, GEN pl, long var)
+{
+  pari_sp av = avma;
+  const long n = (lg(Ld)==1)? 2: vecsmall_max(Ld);
+  forprime_t S;
+  GEN bnr = NULL, ideal = gen_1, nf, dec, H = gen_0, finf, pol;
+  ulong ell, p;
+  long deg, i, degell;
+  (void)uisprimepower(n, &ell);
+  nf = bnf_get_nf(bnf);
+  deg = nf_get_degree(nf);
+  degell = cgcd(deg,ell-1);
+  finf = cgetg(lg(pl),t_VEC);
+  for (i=1; i<lg(pl); i++) gel(finf,i) = pl[i]==-1 ? gen_1 : gen_0;
+
+  u_forprime_init(&S, 2, ULONG_MAX);
+  while ((p = u_forprime_next(&S))) {
+    if (Fl_powu(p % ell, degell, ell) != 1) continue; /* ell | p^deg-1 ? */
+    dec = idealprimedec(nf, utoipos(p));
+    for (i=1; i<lg(dec); i++) {
+      GEN pp = gel(dec,i);
+      if (RgV_isin(Lpr,pp)) continue; /*TODO accepter aussi les ideaux premiers auxquels on pose une condition (utiliser Artin local) ?*/
+      if (smodis(idealnorm(nf,pp),ell) != 1) continue; /* ell | N(pp)-1 ? */
+      ideal = idealmul(bnf,ideal,pp);
+      /* TODO: give factorization ?*/
+      bnr = Buchray(bnf, mkvec2(ideal,finf), nf_GEN|nf_INIT);
+      H = bnrgwsearch(bnr,Lpr,Ld,pl);
+      if (H != gen_0)
+      {
+        pol = rnfkummer(bnr,H,0,nf_get_prec(nf));
+        setvarn(pol, var);
+        return gerepileupto(av,pol);
+      }
+    }
+  }
+  pari_err_BUG("bnfgwgeneric (no suitable p)");
+  return NULL;/*not reached*/
+}
+
+GEN
+bnrconj(GEN bnr, long i)
+{
+  pari_sp av = avma;
+  GEN x,y, nf = bnr_get_nf(bnr), I = gel(bnr_get_bid(bnr),3), pl, red;
+  long r1 = nf_get_r1(nf), n = nbrows(I);
+
+  pl = const_vecsmall(r1,1);
+  pl[i] = -1;
+  y = const_vec(n, gen_1);
+  x = extchinese(nf,I,y,pl,&red);
+  return gerepileupto(av, isprincipalray(bnr,x));
+}
+
+/* no garbage collection */
+static GEN
+localextdeg(GEN nf, GEN pr, GEN cnd, long d, long ell, long n)
+{
+  long g = n/d;
+  GEN res, modpr, ppr = pr, T, p, gen, k;
+  if (d==1) return gen_1;
+  if (equalsi(ell,pr_get_p(pr))) { /* ell == p */
+    res = nfadd(nf, gen_1, pr_get_gen(pr));
+    res = nfpowmodideal(nf, res, stoi(g), cnd);
+  }
+  else { /* ell != p */
+    k = powis(stoi(ell),Z_lval(subis(pr_norm(pr),1),ell));
+    k = divis(k,g);
+    modpr = nf_to_Fq_init(nf, &ppr, &T, &p);
+    (void)Fq_sqrtn(gen_1,k,T,p,&gen);
+    res = Fq_to_nf(gen, modpr);
+  }
+  return res;
+}
+
+/* Ld[i] must be nontrivial powers of the same prime ell */
+/* pl : -1 at real places at which the extention must ramify, 0 elsewhere */
+GEN
+nfgwkummer(GEN nf, GEN Lpr, GEN Ld, GEN pl, long var)
+{
+  const long n = (lg(Ld)==1)? 2: vecsmall_max(Ld);
+  pari_sp av = avma;
+  ulong ell;
+  long i, v;
+  GEN cnd, y, x, red, pol;
+  v = uisprimepower(n, &ell);
+  cnd = zeromatcopy(lg(Lpr)-1,2);
+
+  y = vec_ei(lg(Lpr)-1,1);
+  for (i=1; i<lg(Lpr); i++) {
+    GEN pr = gel(Lpr,i), p = pr_get_p(pr), E;
+    long e = pr_get_e(pr);
+    gcoeff(cnd,i,1) = pr;
+
+    if (!equalui(ell,p))
+      E = gen_1;
+    else
+      E = addsi(1 + v*e, divsi(e,subis(p,1)));
+    gcoeff(cnd,i,2) = E;
+    gel(y,i) = localextdeg(nf, pr, idealpow(nf,pr,E), Ld[i], ell, n);
+  }
+
+  x = extchinese(nf, cnd, y, pl, &red); /* TODO use a factoredextchinese to ease computations afterwards ? */
+  x = basistoalg(nf,x);
+  pol = gsub(gpowgs(pol_x(var),n),x);
+
+  return gerepileupto(av,pol);
+}
+
+static GEN
+get_vecsmall(GEN v)
+{
+  switch(typ(v))
+  {
+    case t_VECSMALL: return v;
+    case t_VEC: if (RgV_is_ZV(v)) return ZV_to_zv(v);
+  }
+  pari_err_TYPE("nfgrunwaldwang",v);
+  return NULL;/*not reached*/
+}
+GEN
+nfgrunwaldwang(GEN nf0, GEN Lpr, GEN Ld, GEN pl, long var)
+{
+  ulong n;
+  pari_sp av = avma;
+  GEN nf, bnf, pr;
+  long t, w, i, vnf;
+  ulong ell, ell2;
+  if (var < 0) var = 0;
+  nf = get_nf(nf0,&t);
+  if (!nf) pari_err_TYPE("nfgrunwaldwang",nf0);
+  vnf = nf_get_varn(nf);
+  if (varncmp(var, vnf) >= 0)
+    pari_err_PRIORITY("nfgrunwaldwang", pol_x(var), ">=", vnf);
+  if (typ(Lpr) != t_VEC) pari_err_TYPE("nfgrunwaldwang",Lpr);
+  if (lg(Lpr) != lg(Ld)) pari_err_DIM("nfgrunwaldwang [#Lpr != #Ld]");
+  for(i=1; i<lg(Lpr); i++) {
+    pr = gel(Lpr,i);
+    if (nf_get_degree(nf)==1 && typ(pr)==t_INT)
+      gel(Lpr,i) = gel(idealprimedec(nf,pr), 1);
+    else checkprid(pr);
+  }
+  if (lg(pl)-1 != nf_get_r1(nf))
+    pari_err_DOMAIN("nfgrunwaldwang [pl should have r1 components]", "#pl",
+        "!=", stoi(nf_get_r1(nf)), stoi(lg(pl)-1));
+
+  Ld = get_vecsmall(Ld);
+  pl = get_vecsmall(pl);
+  bnf = get_bnf(nf0,&t);
+  n = (lg(Ld)==1)? 2: vecsmall_max(Ld);
+
+  if (!uisprimepower(n, &ell))
+    pari_err_IMPL("nfgrunwaldwang for non prime-power local degrees (a)");
+  for(i=1; i<lg(Ld); i++)
+    if (Ld[i]!=1 && (!uisprimepower(Ld[i],&ell2) || ell2!=ell))
+      pari_err_IMPL("nfgrunwaldwang for non prime-power local degrees (b)");
+  for(i=1; i<lg(pl); i++)
+    if (pl[i]==-1 && ell%2)
+      pari_err_IMPL("nfgrunwaldwang for non prime-power local degrees (c)");
+
+  w = bnf? bnf_get_tuN(bnf): itos(gel(rootsof1(nf),1));
+
+  /*TODO choice between kummer and generic ? Let user choose between speed
+   * and size*/
+  if (w%n==0 && lg(Ld)>1)
+    return gerepileupto(av,nfgwkummer(nf,Lpr,Ld,pl,var));
+  if (ell==n) {
+    if (!bnf) bnf = Buchall(nf,0,0);
+    return gerepileupto(av,bnfgwgeneric(bnf,Lpr,Ld,pl,var));
+  }
+  else {
+    pari_err_IMPL("nfgrunwaldwang for non-prime degree");
+    av = avma; return gen_0;
+  }
+}
+
+/** HASSE INVARIANTS **/
+
+/*TODO long -> ulong + uel */
+static GEN
+hasseconvert(GEN H, long n)
+{
+  GEN h, c;
+  long i, l;
+  switch(typ(H)) {
+    case t_VEC:
+      l = lg(H); h = cgetg(l,t_VECSMALL);
+      if (l == 1) return h;
+      c = gel(H,1);
+      if (typ(c) == t_VEC && l == 3)
+        return mkvec2(gel(H,1),hasseconvert(gel(H,2),n));
+      for (i=1; i<l; i++)
+      {
+        c = gel(H,i);
+        switch(typ(c)) {
+          case t_INT:  break;
+          case t_INTMOD:
+            c = gel(c,2); break;
+          case t_FRAC :
+            c = gmulgs(c,n);
+            if (typ(c) == t_INT) break;
+            pari_err_DOMAIN("hasseconvert [degree should be a denominator of the invariant]", "denom(h)", "ndiv", stoi(n), Q_denom(gel(H,i)));
+          default : pari_err_TYPE("Hasse invariant", c);
+        }
+        h[i] = smodis(c,n);
+      }
+      return h;
+    case t_VECSMALL: return H;
+  }
+  pari_err_TYPE("Hasse invariant", H); return NULL;
+}
+
+/* assume f >= 2 */
+static long
+cyclicrelfrob0(GEN nf, GEN aut, GEN pr, GEN q, long f, long g)
+{
+  pari_sp av = avma;
+  long s;
+  GEN T, p, modpr, a, b;
+
+  modpr = nf_to_Fq_init(nf,&pr,&T,&p);
+  a = pol_x(nf_get_varn(nf));
+  b = galoisapply(nf, aut, modpr_genFq(modpr));
+  b = nf_to_Fq(nf, b, modpr);
+  for (s=0; !ZX_equal(a, b); s++) a = Fq_pow(a, q, T, p);
+  avma = av;
+  return g*Fl_inv(s, f);/*<n*/
+}
+
+static GEN
+rnfprimedec(GEN rnf, GEN nf2, GEN pr)
+{
+  GEN pr2;
+  pr2 = idealhnf(nf2,gtomat(matalgtobasis(nf2,rnfidealup(rnf, pr))));
+  return idealfactor(nf2, pr2);
+}
+
+long
+cyclicrelfrob(GEN rnf, GEN nf2, GEN auts, GEN pr)
+{
+  pari_sp av = avma;
+  long n,f,g,frob;
+  GEN nf, fa, ppr, autabs;
+  n = rnf_get_degree(rnf);
+  nf = rnf_get_nf(rnf);
+
+  fa = rnfprimedec(rnf, nf2, pr);
+
+  if (cmpis(gcoeff(fa,1,2), 1) > 0)
+    pari_err_DOMAIN("cyclicrelfrob","e(PR/pr)",">",gen_1,pr);
+  g = nbrows(fa);
+  f = n/g;
+
+  if (f <= 2) frob = g%n;
+  else {
+    ppr = gcoeff(fa,1,1);
+    autabs = rnfeltreltoabs(rnf,gel(auts,g));
+    autabs = nfadd(nf2, autabs, gmul(rnf_get_k(rnf), rnf_get_alpha(rnf)));
+    frob = cyclicrelfrob0(nf2, autabs, ppr, idealnorm(nf,pr), f, g);
+  }
+  avma = av; return frob;
+}
+
+long
+localhasse(GEN rnf, GEN nf2, GEN cnd, GEN pl, GEN auts, GEN b, long k)
+{
+  pari_sp av = avma;
+  long v, m, h, lfa, frob, n, i;
+  GEN previous, y, pr, nf, q, fa;
+  nf = rnf_get_nf(rnf);
+  n = rnf_get_degree(rnf);
+  pr = gcoeff(cnd,k,1);
+  v = nfval(nf, b, pr);
+  m = lg(cnd)>1 ? nbrows(cnd) : 0;
+
+  /* add the valuation of b to the conductor... */
+  previous = gcoeff(cnd,k,2);
+  gcoeff(cnd,k,2) = addis(previous, v);
+
+  y = const_vec(m, gen_1);
+  gel(y,k) = b;
+  /* find a factored element y congruent to b mod pr^(vpr(b)+vpr(cnd)) and to 1 mod the conductor. */
+  y = factoredextchinese(nf, cnd, y, pl, &fa);
+  h = 0;
+  lfa = nbrows(fa);
+  /* sum of all Hasse invariants of (rnf/nf,aut,y) is 0, Hasse invariants at q!=pr are easy, Hasse invariant at pr is the same as for al=(rnf/nf,aut,b). */
+  for (i=1; i<=lfa; i++) {
+    q = gcoeff(fa,i,1);
+    if (cmp_prime_ideal(pr,q)) {
+      frob = cyclicrelfrob(rnf, nf2, auts, q);
+      frob = Fl_mul(frob,umodiu(gcoeff(fa,i,2),n),n);
+      h = Fl_add(h,frob,n);
+    }
+  }
+  /* ...then restore it. */
+  gcoeff(cnd,k,2) = previous;
+
+  avma = av; return Fl_neg(h,n);
+}
+
+static GEN
+allauts(GEN rnf, GEN aut)
+{
+  long n = rnf_get_degree(rnf), i;
+  GEN pol = rnf_get_pol(rnf), vaut;
+  if(n==1) n=2;
+  vaut = cgetg(n,t_VEC);
+  aut = lift(rnfbasistoalg(rnf,aut));
+  gel(vaut,1) = aut;
+  for (i=1; i<n-1; i++)
+    gel(vaut,i+1) = RgX_rem(poleval(gel(vaut,i), aut), pol);
+  return vaut;
+}
+
+static GEN
+clean_factor(GEN fa)
+{
+  GEN P2,E2, P = gel(fa,1), E = gel(fa,2);
+  long l = lg(P), i, j = 1;
+  P2 = cgetg(l, t_COL);
+  E2 = cgetg(l, t_COL);
+  for (i = 1;i < l; i++)
+    if (signe(gel(E,i))) {
+      gel(P2,j) = gel(P,i);
+      gel(E2,j) = gel(E,i); j++;
+    }
+  setlg(P2,j);
+  setlg(E2,j); return mkmat2(P2,E2);
+}
+
+/* shallow concat x[1],...x[nx],y[1], ... y[ny], returning a t_COL. To be
+ * used when we do not know whether x,y are t_VEC or t_COL */
+static GEN
+colconcat(GEN x, GEN y)
+{
+  long i, lx = lg(x), ly = lg(y);
+  GEN z=cgetg(lx+ly-1, t_COL);
+  for (i=1; i<lx; i++) z[i]     = x[i];
+  for (i=1; i<ly; i++) z[lx+i-1]= y[i];
+  return z;
+}
+
+/* return v(x) at all primes in listpr, replace x by cofactor */
+static GEN
+nfmakecoprime(GEN nf, GEN *px, GEN listpr)
+{
+  long j, l = lg(listpr);
+  GEN x1, x = *px, L = cgetg(l, t_COL);
+
+  if (typ(x) != t_MAT)
+  { /* scalar, divide at the end (fast valuation) */
+    x1 = NULL;
+    for (j=1; j<l; j++)
+    {
+      GEN pr = gel(listpr,j), e;
+      long v = nfval(nf, x, pr);
+      e = stoi(v); gel(L,j) = e;
+      if (v) x1 = x1? idealmulpowprime(nf, x1, pr, e)
+                    : idealpow(nf, pr, e);
+    }
+    if (x1) x = idealdivexact(nf, idealhnf(nf,x), x1);
+  }
+  else
+  { /* HNF, divide as we proceed (reduce size) */
+    for (j=1; j<l; j++)
+    {
+      GEN pr = gel(listpr,j);
+      long v = idealval(nf, x, pr);
+      gel(L,j) = stoi(v);
+      if (v) x = idealmulpowprime(nf, x, pr, stoi(-v));
+    }
+  }
+  *px = x; return L;
+}
+
+/* Caveat: factorizations are not sorted wrt cmp_prime_ideal: Lpr comes first */
+static GEN
+computecnd(GEN rnf, GEN Lpr)
+{
+  GEN id, nf, fa, Le, P,E;
+  long n = rnf_get_degree(rnf);
+
+  nf = rnf_get_nf(rnf);
+  id = rnf_get_idealdisc(rnf);
+  Le = nfmakecoprime(nf, &id, Lpr);
+  fa = idealfactor(nf, id); /* part of D_{L/K} coprime with Lpr */
+  P =  colconcat(Lpr,gel(fa,1));
+  E =  colconcat(Le, gel(fa,2));
+  fa = mkmat2(P, gdiventgs(E, eulerphiu(n)));
+  return mkvec2(fa, clean_factor(fa));
+}
+
+static void
+nextgen(GEN gene, long h, GEN* gens, GEN* hgens, long* ngens, long* curgcd) {
+  long nextgcd = cgcd(h,*curgcd);
+  if (nextgcd == *curgcd) return;
+  (*ngens)++;
+  gel(*gens,*ngens) = gene;
+  gel(*hgens,*ngens) = stoi(h);
+  *curgcd = nextgcd;
+  return;
+}
+
+static int
+dividesmod(long d, long h, long n) { return !(h%cgcd(d,n)); }
+
+/* ramified prime with nontrivial Hasse invariant */
+static GEN
+localcomplete(GEN rnf, GEN nf2, GEN pl, GEN cnd, GEN auts, long j, long n, long h, long* v)
+{
+  GEN nf, gens, hgens, pr, modpr, T, p, Np, sol, U, D, b, gene, randg, pu;
+  long ngens, i, d, np, k, d1, d2, hg, dnf, vcnd, curgcd;
+  nf = rnf_get_nf(rnf);
+  pr = gcoeff(cnd,j,1);
+  Np = pr_norm(pr);
+  np = smodis(Np,n);
+  dnf = nf_get_degree(nf);
+  vcnd = itos(gcoeff(cnd,j,2));
+  ngens = 13+dnf;
+  gens = zerovec(ngens);
+  hgens = zerovec(ngens);
+  *v = 0;
+  curgcd = 0;
+  ngens = 0;
+
+  if (!uisprime(n)) {
+    gene =  pr_get_gen(pr);
+    hg = localhasse(rnf, nf2, cnd, pl, auts, gene, j);
+    nextgen(gene, hg, &gens, &hgens, &ngens, &curgcd);
+  }
+
+  if (cgcd(np,n) != 1) { /* GCD(Np,n) != 1 */
+    pu = idealprincipalunits(nf,pr,vcnd);
+    pu = abgrp_get_gen(pu);
+    for (i=1; i<lg(pu) && !dividesmod(curgcd,h,n); i++) {
+      gene = gel(pu,i);
+      hg = localhasse(rnf, nf2, cnd, pl, auts, gene, j);
+      nextgen(gene, hg, &gens, &hgens, &ngens, &curgcd);
+    }
+  }
+
+  d = cgcd(np-1,n);
+  if (d != 1) { /* GCD(Np-1,n) != 1 */
+    modpr = nf_to_Fq_init(nf, &pr, &T, &p);
+    while (!dividesmod(curgcd,h,n)) { /*TODO gener_FpXQ_local*/
+      if (T==NULL) randg = randomi(p);
+      else randg = random_FpX(degpol(T), varn(T),p);
+
+      if (!gequal0(randg) && !gequal1(randg)) {
+        gene = Fq_to_nf(randg, modpr);
+        hg = localhasse(rnf, nf2, cnd, pl, auts, gene, j);
+        nextgen(gene, hg, &gens, &hgens, &ngens, &curgcd);
+      }
+    }
+  }
+
+  setlg(gens,ngens+1);
+  setlg(hgens,ngens+1);
+
+  sol = ZV_extgcd(hgens);
+  D = gel(sol,1);
+  U = gmael(sol,2,ngens);
+
+  b = gen_1;
+  d = itos(D);
+  d1 = cgcd(d,n);
+  d2 = d/d1;
+  d = ((h/d1)*Fl_inv(d2,n))%n;
+  for (i=1; i<=ngens; i++) {
+    k = (itos(gel(U,i))*d)%n;
+    if (k<0) k = n-k;
+    if (k) b = nfmul(nf, b, nfpow_u(nf, gel(gens,i),k));
+    if (i==1) *v = k;
+  }
+  return b;
+}
+
+static int
+testsplits(GEN data, GEN b, GEN fa)
+{
+  GEN rnf, nf2, fapr, pr, forbid, nf;
+  long i, g, n;
+  rnf = gel(data,1);
+  nf2 = gel(data,2);
+  forbid = gel(data,3);
+  n = rnf_get_degree(rnf);
+  nf = rnf_get_nf(rnf);
+  if (gequal0(b)) return 0;
+  for (i=1; i<lgcols(fa); i++) {
+    pr = gcoeff(fa,i,1);
+    if (idealval(nf,forbid,pr)) return 0;
+    fapr = rnfprimedec(rnf,nf2,pr);
+    g = nbrows(fapr);
+    if ((itos(gcoeff(fa,i,2))*g)%n) return 0;
+  }
+  return 1;
+}
+
+/* remove entries with Hasse invariant 0 */
+static GEN
+hassereduce(GEN hf)
+{
+  GEN pr,h, PR = gel(hf,1), H = gel(hf,2);
+  long i, j, l = lg(PR);
+
+  pr= cgetg(l, t_VEC);
+  h = cgetg(l, t_VECSMALL);
+  for (i = j = 1; i < l; i++)
+    if (H[i]) {
+      gel(pr,j) = gel(PR,i);
+      h[j] = H[i]; j++;
+    }
+  setlg(pr,j);
+  setlg(h,j); return mkvec2(pr,h);
+}
+
+/* v vector of prid. Return underlying list of rational primes */
+static GEN
+pr_primes(GEN v)
+{
+  long i, l = lg(v);
+  GEN w = cgetg(l,t_VEC);
+  for (i=1; i<l; i++) gel(w,i) = pr_get_p(gel(v,i));
+  return ZV_sort_uniq(w);
+}
+
+static GEN
+alg_complete0(GEN rnf, GEN aut, GEN hf, GEN hi, int maxord)
+{
+  pari_sp av = avma;
+  GEN nf, pl, pl2, cnd, prcnd, cnds, y, Lpr, auts, nf2, b, fa, data, hfe;
+  GEN forbid, al;
+  long D, n, d, i, j;
+  nf = rnf_get_nf(rnf);
+  n = rnf_get_degree(rnf);
+  d = nf_get_degree(nf);
+  D = d*n*n;
+  checkhasse(nf,hf,hi,n);
+  hf = hassereduce(hf);
+  Lpr = gel(hf,1);
+  hfe = gel(hf,2);
+
+  auts = allauts(rnf,aut);
+  nf2 = check_and_build_nfabs(rnf, nf_get_prec(rnf_get_nf(rnf)));
+
+  pl = gcopy(hi); /* conditions on the final b */
+  pl2 = gcopy(hi); /* conditions for computing local Hasse invariants */
+  for (i=1; i<lg(pl); i++) {
+    if (hi[i]) {
+      pl[i] = -1;
+      pl2[i] = 1;
+    }
+    else if (!rnfrealdec(rnf,i)) {
+      pl[i] = 1;
+      pl2[i] = 1;
+    }
+  }
+
+  cnds = computecnd(rnf,Lpr);
+  prcnd = gel(cnds,1);
+  cnd = gel(cnds,2);
+  y = cgetg(lgcols(prcnd),t_VEC);
+  forbid = gen_1;
+  for (i=j=1; i<lg(Lpr); i++)
+  {
+    GEN pr = gcoeff(prcnd,i,1);
+    long v, e = itos( gcoeff(prcnd,i,2) );
+    if (!e) {
+      long frob, f1, f2;
+      gel(y,i) = gen_0;
+      frob = cyclicrelfrob(rnf,nf2,auts,pr);
+      f1 = cgcd(frob,n);
+      f2 = frob/f1;
+      v = ((hfe[i] / f1) * Fl_inv(f2,n)) % n;
+      forbid = idealmul(nf,forbid,pr);
+    }
+    else {
+      gel(y,i) = localcomplete(rnf, nf2, pl2, cnd, auts, j, n, hfe[i], &v);
+      j++;
+    }
+    gcoeff(prcnd,i,2) = stoi(e + v);
+  }
+  for (; i<lgcols(prcnd); i++) gel(y,i) = gen_1;
+
+  data = mkvec3(rnf,nf2,forbid);
+  b = factoredextchinesetest(nf,prcnd,y,pl,&fa,data,testsplits);
+
+  al = cgetg(12, t_VEC);
+  gel(al,10)= gen_0; /* must be set first */
+  gel(al,1) = rnf;
+  gel(al,2) = auts;
+  gel(al,3) = basistoalg(nf,b);
+  gel(al,4) = hi;
+  /* add primes | disc or b with trivial Hasse invariant to hf */
+  Lpr = gel(prcnd,1); y = b;
+  (void)nfmakecoprime(nf, &y, Lpr);
+  Lpr = shallowconcat(Lpr, gel(idealfactor(nf,y), 1));
+  settyp(Lpr,t_VEC);
+  hf = mkvec2(Lpr, shallowconcat(hfe, const_vecsmall(lg(Lpr)-lg(hfe), 0)));
+  gel(al,5) = hf;
+  gel(al,6) = gen_0;
+  gel(al,7) = matid(D);
+  gel(al,8) = matid(D); /* TODO modify 7, 8 et 9 once LLL added */
+  gel(al,9) = algnatmultable(al,D);
+  gel(al,11)= algtracebasis(al);
+  if (maxord) al = alg_maximal_primes(al, pr_primes(Lpr));
+  return gerepilecopy(av, al);
+}
+
+GEN
+alg_complete(GEN rnf, GEN aut, GEN hf, GEN hi, int maxord)
+{
+  long n = rnf_get_degree(rnf);
+  return alg_complete0(rnf,aut,hasseconvert(hf,n),hasseconvert(hi,n), maxord);
+}
+
+void
+checkhasse(GEN nf, GEN hf, GEN hi, long n)
+{
+  GEN Lpr, Lh;
+  long i, sum;
+  if (typ(hf) != t_VEC || lg(hf) != 3) pari_err_TYPE("checkhasse [hf]", hf);
+  Lpr = gel(hf,1);
+  Lh = gel(hf,2);
+  if (typ(Lpr) != t_VEC) pari_err_TYPE("checkhasse [Lpr]", Lpr);
+  if (typ(Lh) != t_VECSMALL) pari_err_TYPE("checkhasse [Lh]", Lh);
+  if (typ(hi) != t_VECSMALL)
+    pari_err_TYPE("checkhasse [hi]", hi);
+  if ((nf && lg(hi) != nf_get_r1(nf)+1))
+    pari_err_DOMAIN("checkhasse [hi should have r1 components]","#hi","!=",stoi(nf_get_r1(nf)),stoi(lg(hi)-1));
+  if (lg(Lpr) != lg(Lh))
+    pari_err_DIM("checkhasse [Lpr and Lh should have same length]");
+  for (i=1; i<lg(Lpr); i++) checkprid(gel(Lpr,i));
+  if (lg(gen_sort_uniq(Lpr, (void*)cmp_prime_ideal, cmp_nodata)) < lg(Lpr))
+    pari_err(e_MISC, "error in checkhasse [duplicate prime ideal]");
+  sum = 0;
+  for (i=1; i<lg(Lh); i++) sum = (sum+Lh[i])%n;
+  for (i=1; i<lg(hi); i++) {
+      if(hi[i] && 2*hi[i] != n) pari_err_DOMAIN("checkhasse", "Hasse invariant at real place [must be 0 or 1/2]", "!=", n%2? gen_0 : stoi(n/2), stoi(hi[i]));
+      sum = (sum+hi[i])%n;
+  }
+  if (sum<0) sum = n+sum;
+  if (sum != 0)
+    pari_err_DOMAIN("checkhasse","sum(Hasse invariants)","!=",gen_0,Lh);
+}
+
+GEN
+hassecoprime(GEN hf, GEN hi, long n)
+{
+  pari_sp av = avma;
+  long l, i, j, lk, inv;
+  GEN fa, P,E, res, hil, hfl;
+  hi = hasseconvert(hi, n);
+  hf = hasseconvert(hf, n);
+  checkhasse(NULL,hf,hi,n);
+  fa = factoru(n);
+  P = gel(fa,1); l = lg(P);
+  E = gel(fa,2);
+  res = cgetg(l,t_VEC);
+  for (i=1; i<l; i++) {
+    lk = upowuu(P[i],E[i]);
+    inv = Fl_invsafe((n/lk)%lk, lk);
+    hil = gcopy(hi);
+    hfl = gcopy(hf);
+
+    if (P[i] == 2)
+      for (j=1; j<lg(hil); j++) hil[j] = hi[j]==0 ? 0 : lk/2;
+    else
+      for (j=1; j<lg(hil); j++) hil[j] = 0;
+    for (j=1; j<lgcols(hfl); j++) gel(hfl,2)[j] = (gel(hf,2)[j]*inv)%lk;
+    hfl = hassereduce(hfl);
+    gel(res,i) = mkvec3(hfl,hil,stoi(lk));
+  }
+
+  return gerepilecopy(av, res);
+}
+
+#if 0
+/* not used */
+
+static GEN
+zv_z_div(GEN z, long k)
+{
+  long i, l;
+  GEN x = cgetg_copy(z,&l);
+  for (i = 1; i < l; i++) x[i] = z[i]/k;
+  return x;
+}
+
+GEN
+hassewedderburn(GEN hf, GEN hi, long n)
+{
+  pari_sp av = avma;
+  long ind = 1, denom, i, k;
+  GEN hid, hfd;
+  hi = hasseconvert(hi,n);
+  hf = hasseconvert(hf,n);
+  checkhasse(NULL,hf,hi,n);
+  for (i=1; i<lg(hi); i++) {
+    denom = n/cgcd(hi[i],n);
+    ind = clcm(ind,denom);
+  }
+  for (i=1; i<lgcols(hf); i++) {
+    denom = n/cgcd(gel(hf,2)[i],n);
+    ind = clcm(ind,denom);
+  }
+  k = n/ind;
+  hid = zv_z_div(hi, k);
+  hfd = mkmat2(gel(hf,1), zv_z_div(gel(hf,2),k));
+  return gerepilecopy(av, mkvec3(hfd,hid,stoi(k)));
+}
+#endif
+
+static long
+alldegmultiple(GEN pr, long d)
+{
+  long i;
+  for (i=1; i<lg(pr); i++)
+    if ((pr_get_e(gel(pr,i))*pr_get_f(gel(pr,i))) % d) return 0;
+  return 1;
+}
+
+/* no garbage collection */
+static long
+searchprimedeg(GEN nf, long d, GEN forbidden, GEN *pp)
+{
+  ulong p, n = nf_get_degree(nf);
+  GEN b, pr;
+  forprime_t T;
+
+  if (n%d) return 0;
+
+  /* replace with a simple bound ? */
+  b = glog(nf_get_disc(nf),5);
+  b = mulrs(b,n);
+  b = mpsqr(b);
+  b = ceil_safe(b);
+  b = gmin(b, stoi(ULONG_MAX/2));
+  if (!u_forprime_init(&T, 0, itos(b))) return 0;
+
+  while ((p=u_forprime_next(&T))) {/* not a comparison : test p!=0 */
+    if (tablesearch(forbidden, stoi(p), cmpii)) continue;
+    pr = idealprimedec(nf,stoi(p));
+    if (alldegmultiple(pr,d)) { *pp = stoi(p); return 1; }
+  }
+  return 0;
+}
+
+/* no garbage collection */
+static GEN
+sortedp(GEN Lpr)
+{
+  long i;
+  GEN Lp = zerovec(lg(Lpr)-1);
+  for (i=1; i<lg(Lp); i++) gel(Lp,i) = pr_get_p(gel(Lpr,i));
+  return gen_sort_uniq(Lp, (void*)cmpii, cmp_nodata);
+}
+
+static long
+solvablecrt(long x1, long N1, long x2, long N2, long *x0, long *N)
+{
+  long d, a, b, u;
+  d = cbezout(N1, N2, &a, &b);
+  if ((x1-x2)%d != 0) return 0;
+  N1 /= d;
+  *N = N1*N2;
+  N2 /= d;
+  u = a*N1;
+  *x0 = smodss(u*x2+(1-u)*x1,*N);
+  return 1;
+}
+
+static long
+hdown(GEN pr, long h, long n, long *nn)
+{
+  long prdeg, d, u, v;
+  prdeg = pr_get_e(pr)*pr_get_f(pr);
+  d = cgcd(prdeg,n);
+  if (h%d) return 0;
+  h /= d;
+  prdeg /= d;
+  *nn = n/d;
+  d = cbezout(prdeg, *nn, &u, &v);
+  return (h*u)%(*nn); /* can be <0 */
+}
+
+/* Assumes hf contains no prime or all primes above every rational primes */
+/* Less efficient (might not find a soution) if a set of primes above p all have Hasse invariant 0. */
+static GEN
+hassedown0(GEN nf, long n, GEN hf, GEN hi)
+{
+  pari_sp av = avma;
+  long totcplx=(lg(hi)==1), hid=0, i, j, h, nn, total, nbp;
+  GEN pr, pv, h0v, nnv;
+  checkhasse(nf,hf,hi,n);
+
+  /* The Hasse invariant at gel(pv,i) has to be h0v[i] mod nnv[i], where nnv[i] | n. */
+  if (!totcplx) {
+    hid = hi[1];
+    for (i=2;i<lg(hi);i++)
+      if (hi[i] != hid) {avma = av; return gen_0;}
+  }
+
+  pv = sortedp(gel(hf,1));
+  h0v = cgetg(lg(pv),t_VECSMALL);
+  nnv = const_vecsmall(lg(pv)-1, 0);
+
+  for (i=1; i<lgcols(hf); i++) {
+    pr = gmael(hf,1,i);
+    h = gel(hf,2)[i];
+    h %= n;
+    nn = 0;
+    h = hdown(pr, h, n, &nn);
+    if (nn==0) {avma = av; return gen_0;}
+
+    j = ZV_search(pv, pr_get_p(pr));
+    if (nnv[j]==0) {
+      nnv[j] = nn;
+      h0v[j] = h;
+    }
+    else if (!solvablecrt(h0v[j], nnv[j], h, nn, &h0v[j], &nnv[j])) {avma = av; return gen_0;}
+  }
+  total = (hid + zv_sum(h0v)) % n;
+  nbp = lg(pv)-1;
+  if (total==n/2 && totcplx)
+    hid = n/2;
+  else if (total!=0) {
+    GEN p;
+    nn = n/cgcd(total,n);
+    if (!searchprimedeg(nf, nn, pv, &p)) {avma = av; return gen_0;}
+    nbp++;
+    pv = vec_append(pv, p);
+    h0v= vecsmall_append(h0v, (n-total)%n);
+  }
+  return gerepilecopy(av, mkvec2(mkvec2(pv,h0v),
+                                 mkvecsmall(hid)));
+}
+
+GEN
+hassedown(GEN nf, long n, GEN hf, GEN hi)
+{
+  return hassedown0(nf,n,hasseconvert(hf,n),hasseconvert(hi,n));
+}
+
+/* no garbage collection */
+static GEN
+genefrob(GEN nf, GEN gal, GEN r)
+{
+  long i;
+  GEN g = identity_perm(nf_get_degree(nf)), fa = Z_factor(r), p, pr, frob;
+  for (i=1; i<lgcols(fa); i++) {
+    p = gcoeff(fa,i,1);
+    pr = idealprimedec(nf, p);
+    pr = gel(pr,1);
+    frob = idealfrobenius(nf, gal, pr);
+    g = perm_mul(g, perm_pow(frob, itos(gcoeff(fa,i,2))));
+  }
+  return g;
+}
+
+static GEN
+rnfcycaut(GEN rnf, GEN nf2)
+{
+  GEN L, alpha, pol, salpha, s, sj, polabs, k, X, pol0, nf;
+  long i, d, j;
+  d = rnf_get_degree(rnf);
+  L = galoisconj(nf2,NULL);
+  alpha = lift(rnf_get_alpha(rnf));
+  pol = rnf_get_pol(rnf);
+  k = rnf_get_k(rnf);
+  polabs = rnf_get_polabs(rnf);
+  nf = rnf_get_nf(rnf);
+  pol0 = nf_get_pol(nf);
+  X = RgX_rem(pol_x(varn(pol0)), pol0);
+
+  /* TODO: check mod prime of degree 1 */
+  for (i=1; i<lg(L); i++) {
+    s = gel(L,i);
+    salpha = RgX_RgXQ_eval(alpha,s,polabs);
+    if (!gequal(alpha,salpha)) continue;
+
+    s = lift(rnfeltabstorel(rnf,s));
+    sj = s = gsub(s, gmul(k,X));
+    for (j=1; !gequal0(gsub(sj,pol_x(varn(s)))); j++)
+      sj = RgX_RgXQ_eval(sj,s,pol);
+    if (j<d) continue;
+    return s;
+  }
+  return NULL; /*not reached*/
+}
+
+GEN
+alg_hasse(GEN nf, long n, GEN hf, GEN hi, long var, long maxord)
+{
+  pari_sp av = avma;
+  GEN primary, al = gen_0, al2, rnf, hil, hfl, Ld, pl, pol, nf2, Lpr, aut;
+  long i, lk, j;
+  primary = hassecoprime(hf, hi, n);
+  if (var < 0) var = 0;
+  for (i=1; i<lg(primary); i++) {
+    lk = itos(gmael(primary,i,3));
+    hfl = gmael(primary,i,1);
+    hil = gmael(primary,i,2);
+    checkhasse(nf, hfl, hil, lk);
+
+    if (lg(gel(hfl,1))>1 || lk%2==0) {
+      Lpr = gel(hfl,1);
+      Ld = gcopy(gel(hfl,2));
+      for (j=1; j<lg(Ld); j++) Ld[j] = lk/cgcd(lk,Ld[j]);
+      pl = gcopy(hil);
+      for (j=1; j<lg(pl); j++) pl[j] = pl[j] ? -1 : 0;
+
+      pol = nfgrunwaldwang(nf,Lpr,Ld,pl,var);
+      rnf = rnfinit(nf,pol);
+      nf2 = check_and_build_nfabs(rnf, nf_get_prec(nf));
+
+      aut = rnfcycaut(rnf,nf2);
+      al2 = alg_complete0(rnf,aut,hfl,hil,maxord);
+    }
+    else al2 = alg_matrix(nf, lk, var, cgetg(1,t_VEC), maxord);
+
+    if (i==1) al = al2;
+    else      al = algtensor(al,al2,maxord);
+  }
+  return gerepilecopy(av,al);
+}
+
+/** CYCLIC ALGEBRA WITH GIVEN HASSE INVARIANTS **/
+
+/* no garbage collection */
+static int
+linindep(GEN pol, GEN L)
+{
+  long i;
+  GEN fa;
+  for (i=1; i<lg(L); i++) {
+    fa = nffactor(gel(L,i),pol);
+    if (lgcols(fa)>2) return 0;
+  }
+  return 1;
+}
+
+/* no garbage collection */
+static GEN
+subcycloindep(GEN nf, long n, long v, GEN L, GEN *pr)
+{
+  pari_sp av;
+  forprime_t S;
+  ulong p;
+  u_forprime_arith_init(&S, 1, ULONG_MAX, 1, n);
+  av = avma;
+  while ((p = u_forprime_next(&S)))
+  {
+    ulong r = pgener_Fl(p);
+    GEN pol = galoissubcyclo(utoipos(p), utoipos(Fl_powu(r,n,p)), 0, v);
+    GEN fa = nffactor(nf, pol);
+    if (lgcols(fa) == 2 && linindep(pol,L)) { *pr = utoipos(r); return pol; }
+    avma = av;
+  }
+  pari_err_BUG("subcycloindep (no suitable prime = 1(mod n))");
+  *pr = NULL; return NULL;
+}
+
+GEN
+alg_matrix(GEN nf, long n, long v, GEN L, long flag)
+{
+  pari_sp av = avma;
+  GEN pol, gal, rnf, cyclo, g, r, aut;
+  if (n<=0) pari_err_DOMAIN("alg_matrix", "n", "<=", gen_0, stoi(n));
+  pol = subcycloindep(nf, n, v, L, &r);
+  rnf = rnfinit(nf, pol);
+  cyclo = nfinit(pol, nf_get_prec(nf));
+  gal = galoisinit(cyclo, NULL);
+  g = genefrob(cyclo,gal,r);
+  aut = galoispermtopol(gal,g);
+  return gerepileupto(av, alg_cyclic(rnf, aut, gen_1, flag));
+}
+
+GEN
+alg_hilbert(GEN nf, GEN a, GEN b, long v, long flag)
+{
+  pari_sp av = avma;
+  GEN C, P, rnf, aut;
+  checknf(nf);
+  if (!isint1(Q_denom(a)))
+    pari_err_DOMAIN("alg_hilbert", "denominator(a)", "!=", gen_1,a);
+  if (!isint1(Q_denom(b)))
+    pari_err_DOMAIN("alg_hilbert", "denominator(b)", "!=", gen_1,b);
+
+  if (v < 0) v = 0;
+  C = Rg_col_ei(gneg(a), 3, 3);
+  gel(C,1) = gen_1;
+  P = gtopoly(C,v);
+  rnf = rnfinit(nf, P);
+  aut = gneg(pol_x(v));
+  return gerepileupto(av, alg_cyclic(rnf, aut, b, flag));
+}
+
+GEN
+alginit(GEN A, GEN B, long v, long flag)
+{
+  switch(nftyp(A))
+  {
+    case typ_NF:
+      switch(typ(B))
+      {
+        long nB;
+        case t_INT: return alg_matrix(A, itos(B), v, cgetg(1,t_VEC), flag);
+        case t_VEC:
+          nB = lg(B)-1;
+          if (nB && typ(gel(B,1)) == t_MAT) return alg_csa_table(A, B, v, flag);
+          switch(nB)
+          {
+            case 2: return alg_hilbert(A, gel(B,1),gel(B,2), v, flag);
+            case 3: return alg_hasse(A, itos(gel(B,1)),gel(B,2),gel(B,3),v,flag);
+          }
+      }
+      pari_err_TYPE("alinit1", B); break;
+
+    case typ_RNF:
+      if (typ(B) != t_VEC || lg(B) != 3) pari_err_TYPE("alinit2", B);
+      return alg_cyclic(A,gel(B,1),gel(B,2),flag);
+  }
+  pari_err_TYPE("alinit3", A);
+  return NULL;/*not reached*/
+}
+
+/* assumes al CSA or CYCLIC */
+static GEN
+algnatmultable(GEN al, long D)
+{
+  GEN res, x;
+  long i;
+  res = cgetg(D+1,t_VEC);
+  for (i=1; i<=D; i++) {
+    x = algnattoalg(al,col_ei(D,i));
+    gel(res,i) = algZmultable(al,x);
+  }
+  return res;
+}
+
+/* no garbage collection */
+static void
+algcomputehasse(GEN al)
+{
+  long r1, k, n, m, m1, m2, m3, i, m23, m123;
+  GEN rnf, nf, b, fab, disc2, cnd, fad, auts, nf2, pr, pl, perm;
+  GEN hi, PH, H, L;
+
+  rnf = alg_get_splitting(al);
+  n = rnf_get_degree(rnf);
+  nf = rnf_get_nf(rnf);
+  b = alg_get_b(al);
+  r1 = nf_get_r1(nf);
+  auts = alg_get_auts(al);
+  nf2 = alg_get_abssplitting(al);
+
+  /* real places where rnf/nf ramifies */
+  pl = cgetg(r1+1, t_VECSMALL);
+  for (k=1; k<=r1; k++) pl[k] = !rnfrealdec(rnf,k);
+
+  /* infinite Hasse invariants */
+  if (odd(n)) hi = const_vecsmall(r1, 0);
+  else
+  {
+    GEN s = nfsign(nf, b);
+    hi = cgetg(r1+1, t_VECSMALL);
+    for (k = 1; k<=r1; k++) hi[k] = (s[k] && pl[k]) ? (n/2) : 0;
+  }
+
+  fab = idealfactor(nf, b);
+  disc2 = rnf_get_idealdisc(rnf);
+  L = nfmakecoprime(nf, &disc2, gel(fab,1));
+  m = lg(L)-1;
+  /* m1 = #{pr|b: pr \nmid disc}, m3 = #{pr|b: pr | disc} */
+  perm = cgetg(m+1, t_VECSMALL);
+  for (i=1, m1=m, k=1; k<=m; k++)
+    if (signe(gel(L,k))) perm[m1--] = k; else perm[i++] = k;
+  m3 = m - m1;
+
+  /* disc2 : factor of disc coprime to b */
+  fad = idealfactor(nf, disc2);
+  /* m2 : number of prime factors of disc not dividing b */
+  m2 = nbrows(fad);
+  m23 = m2+m3;
+  m123 = m1+m2+m3;
+
+  /* initialize the possibly ramified primes (hasse) and the factored conductor of rnf/nf (cnd) */
+  cnd = zeromatcopy(m23,2);
+  PH = cgetg(m123+1, t_VEC); /* ramified primes */
+  H = cgetg(m123+1, t_VECSMALL); /* Hasse invariant */
+  /* compute Hasse invariant at primes that are unramified in rnf/nf */
+  for (k=1; k<=m1; k++) {/* pr | b, pr \nmid disc */
+    long frob, e, j = perm[k];
+    pr = gcoeff(fab,j,1);
+    e = itos(gcoeff(fab,j,2));
+    frob = cyclicrelfrob(rnf, nf2, auts, pr);
+    gel(PH,k) = pr;
+    H[k] = Fl_mul(frob, e, n);
+  }
+  /* compute Hasse invariant at primes that are ramified in rnf/nf */
+  for (k=1; k<=m2; k++) {/* pr \nmid b, pr | disc */
+    pr = gcoeff(fad,k,1);
+    gel(PH,k+m1) = pr;
+    gcoeff(cnd,k,1) = pr;
+    gcoeff(cnd,k,2) = gcoeff(fad,k,2);
+  }
+  for (k=1; k<=m3; k++) { /* pr | (b, disc) */
+    long j = perm[k+m1];
+    pr = gcoeff(fab,j,1);
+    gel(PH,k+m1+m2) = pr;
+    gcoeff(cnd,k+m2,1) = pr;
+    gcoeff(cnd,k+m2,2) = gel(L,j);
+  }
+  gel(cnd,2) = gdiventgs(gel(cnd,2), eulerphiu(n));
+  for (k=1; k<=m23; k++) H[k+m1] = localhasse(rnf, nf2, cnd, pl, auts, b, k);
+  gel(al,4) = hi;
+  gel(al,5) = mkvec2(PH,H);
+  checkhasse(nf,alg_get_hasse_f(al),alg_get_hasse_i(al),n);
+}
+
+#if 0
+static GEN
+pr_idem(GEN nf, GEN pr)
+{
+  pari_sp av = avma;
+  GEN p, pri, dec, u;
+  long i;
+
+  p = pr_get_p(pr);
+  dec = idealprimedec(nf,p);
+  pri = gen_1;
+  for (i=1; i<lg(dec); i++)
+    if (!pr_equal(nf,pr,gel(dec,i))) pri = idealmul(nf,pri,gel(dec,i));
+  u = idealaddtoone_i(nf, pr, pri);
+  return gerepilecopy(av,u);
+}
+#endif
+
+static GEN
+alg_maximal_primes(GEN al, GEN P)
+{
+  pari_sp av = avma;
+  long l = lg(P), i;
+  for (i=1; i<l; i++)
+  {
+    if (i != 1) al = gerepilecopy(av, al);
+    al = alg_pmaximal(al,gel(P,i));
+  }
+  return al;
+}
+
+GEN
+alg_cyclic(GEN rnf, GEN aut, GEN b, int maxord)
+{
+  pari_sp av = avma;
+  GEN al, nf;
+  long D, n, d;
+  checkrnf(rnf);
+  if (!isint1(Q_denom(b)))
+    pari_err_DOMAIN("alg_cyclic", "denominator(b)", "!=", gen_1,b);
+
+  nf = rnf_get_nf(rnf);
+  n = rnf_get_degree(rnf);
+  d = nf_get_degree(nf);
+  D = d*n*n;
+
+  al = cgetg(12,t_VEC);
+  gel(al,10)= gen_0; /* must be set first */
+  gel(al,1) = rnf;
+  gel(al,2) = allauts(rnf, aut);
+  gel(al,3) = basistoalg(nf,b);
+  check_and_build_nfabs(rnf, nf_get_prec(nf));
+  gel(al,6) = gen_0;
+  gel(al,7) = matid(D);
+  gel(al,8) = matid(D); /* TODO modify 7, 8 et 9 once LLL added */
+  gel(al,9) = algnatmultable(al,D);
+  gel(al,11)= algtracebasis(al);
+
+  algcomputehasse(al);
+
+  if (maxord) {
+    GEN hf = alg_get_hasse_f(al), pr = gel(hf,1);
+    al = alg_maximal_primes(al, pr_primes(pr));
+#if 0
+    /* check result */
+    GEN h, disc = powiu(nf_get_disc(nf), n*n);
+    long i;
+    disc = absi(disc);
+    h = gel(hf,2);
+    for (i=1; i<lg(pr); i++) {
+      long dp = cgcd(n,h[i]);
+      disc = mulii(disc, powiu(pr_norm(gel(pr,i)), n*(n-dp)));
+    }
+    disc = mulii(disc, powuu(n,D));
+    if (!absi_equal(disc, algdisc(al)))
+      pari_err_BUG("alg_cyclic (wrong maximal order)");
+#endif
+  }
+  return gerepilecopy(av, al);
+}
+
+static int
+ismaximalsubfield(GEN al, GEN x, GEN d, long v, GEN *pt_minpol)
+{
+  GEN cp = algbasischarpoly(al, x, v), lead;
+  if (!ispower(cp, d, pt_minpol)) return 0;
+  lead = leading_term(*pt_minpol);
+  if(isintm1(lead)) *pt_minpol = gneg(*pt_minpol);
+  return ZX_is_irred(*pt_minpol);
+}
+
+static GEN
+findmaximalsubfield(GEN al, GEN d, long v)
+{
+  long count, nb=2, i, N = alg_get_absdim(al), n = nf_get_degree(alg_get_center(al));
+  GEN x, minpol, maxc = gen_1;
+
+  for(i=n+1; i<=N; i+=n) {
+    for(count=0; count<2 && i+count<=N; count++) {
+      x = col_ei(N,i+count);
+      if (ismaximalsubfield(al, x, d, v, &minpol)) return mkvec2(x,minpol);
+    }
+  }
+
+  while(1) {
+    x = zerocol(N);
+    for(count=0; count<nb; count++)
+    {
+      i = random_Fl(N)+1;
+      gel(x,i) = addis(randomi(maxc),1);
+      if (random_bits(1)) gel(x,i) = negi(gel(x,i));
+    }
+    if (ismaximalsubfield(al, x, d, v, &minpol)) return mkvec2(x,minpol);
+    if (!random_bits(3)) maxc = addis(maxc,1);
+    if (nb<N) nb++;
+  }
+
+  return NULL; /* not reached */
+}
+
+static GEN
+frobeniusform(GEN al, GEN x)
+{
+  GEN M, FP, P, Pi;
+
+  /* /!\ has to be the *right* multiplication table */
+  M = algbasisrightmultable(al, x);
+
+  FP = matfrobenius(M,2,0); /*M = P^(-1)*F*P*/
+  P = gel(FP,2);
+  Pi = RgM_inv(P);
+  return mkvec2(P, Pi);
+}
+
+static void
+computesplitting(GEN al, long d, long v)
+{
+  GEN subf, x, pol, polabs, basis, P, Pi, nf = alg_get_center(al), rnf, Lbasis, Lbasisinv, Q, pows;
+  long i, n = nf_get_degree(nf), nd = n*d, N = alg_get_absdim(al), j, j2;
+
+  subf = findmaximalsubfield(al, utoipos(d), v);
+  x = gel(subf, 1);
+  polabs = gel(subf, 2);
+
+  /* Frobenius form to obtain L-vector space structure */
+  basis = frobeniusform(al, x);
+  P = gel(basis, 1);
+  Pi = gel(basis, 2);
+
+  /* construct rnf of splitting field */
+  pol = nffactor(nf,polabs);
+  pol = gcoeff(pol,1,1);
+  gel(al,1) = rnf = rnfinit(nf, pol);
+  /* if (!gequal0(rnf_get_k(rnf)))                    NECESSARY ?? */
+  /*  pari_err_BUG("computesplitting (k!=0)");                     */
+  gel(al,6) = gen_0;
+  check_and_build_nfabs(rnf, nf_get_prec(nf));
+
+  //TODO check whether should change polabs and generator here !!!
+
+  /* construct splitting data */
+  Lbasis = cgetg(d+1, t_MAT);
+  for(j=j2=1; j<=d; j++, j2+=nd)
+    gel(Lbasis,j) = gel(Pi,j2);
+
+  Q = zeromatcopy(d,N);
+  pows = pol_x_powers(nd,v);
+  for(i=j=1; j<=N; j+=nd, i++)
+  for(j2=0; j2<nd; j2++)
+    gcoeff(Q,i,j+j2) = mkpolmod(gel(pows,j2+1),polabs);
+  Lbasisinv = RgM_mul(Q,P);
+
+  gel(al,3) = mkvec3(x,Lbasis,Lbasisinv);
+  return;
+}
+
+/* assumes that mt defines a central simple algebra over nf */
+GEN
+alg_csa_table(GEN nf, GEN mt0, long v, int maxord)
+{
+  pari_sp av = avma;
+  GEN al, mt;
+  long n, D, d2 = lg(mt0)-1, d = usqrt(d2);
+
+  nf = checknf(nf);
+  mt = check_mt(mt0,NULL);
+  if (!mt) pari_err_TYPE("alg_csa_table", mt0);
+  if (!isint1(Q_denom(mt)))
+    pari_err_DOMAIN("alg_csa_table", "denominator(mt)", "!=", gen_1,mt);
+  n = nf_get_degree(nf);
+  D = n*d2;
+  if (d*d != d2)
+    pari_err_DOMAIN("alg_csa_table", "(nonsquare) dimension", "!=",stoi(d*d),mt);
+
+  al = cgetg(12, t_VEC);
+  gel(al,10) = gen_0; /* must be set first */
+  gel(al,1) = zerovec(12); gmael(al,1,10) = nf; gmael(al,1,1) = gpowgs(pol_x(0), d); /* placeholder before actual splitting field */
+  gel(al,2) = mt;
+  gel(al,3) = gen_0; /* placeholder */
+  gel(al,4) = gel(al,5) = gen_0; /* TODO Hasse invariants */
+  gel(al,5) = gel(al,6) = gen_0; /* placeholder */
+  gel(al,7) = matid(D);
+  gel(al,8) = matid(D);
+  gel(al,9) = algnatmultable(al,D);
+  gel(al,11)= algtracebasis(al);
+
+  if(maxord) al = alg_maximal(al);
+  computesplitting(al, d, v);
+
+  return gerepilecopy(av, al);
+}
+
+GEN
+algtableinit(GEN mt0, GEN p)
+{
+  pari_sp av = avma;
+  GEN al, mt;
+  long i, n;
+
+  if (p && typ(p) != t_INT) pari_err_TYPE("algtableinit",p);
+  if (p && !signe(p)) p = NULL;
+  mt = check_mt(mt0,p);
+  if (!mt) pari_err_TYPE("algtableinit", mt0);
+  if (!p && !isint1(Q_denom(mt0)))
+    pari_err_DOMAIN("algtableinit", "denominator(mt)", "!=", gen_1,mt0);
+  n = lg(mt)-1;
+  al = cgetg(12, t_VEC);
+  for (i=1; i<=6; i++) gel(al,i) = gen_0;
+  gel(al,7) = matid(n);
+  gel(al,8) = matid(n);
+  gel(al,9) = mt;
+  gel(al,10) = p? p: gen_0;
+  gel(al,11)= algtracebasis(al);
+
+  return gerepilecopy(av, al);
+}
+
+/** MAXIMAL ORDER **/
+
+static GEN
+mattocol(GEN M, long n)
+{
+  GEN C = cgetg(n*n+1, t_COL);
+  long i,j,ic;
+  ic = 1;
+  for (i=1; i<=n; i++)
+  for (j=1; j<=n; j++, ic++) gel(C,ic) = gcoeff(M,i,j);
+  return C;
+}
+
+/*Ip is a lift of a left O/pO-ideal where O is the integral basis of al*/
+GEN
+algleftordermodp(GEN al, GEN Ip, GEN p)
+{
+  pari_sp av = avma;
+  GEN I, Ii, M, mt, K, imi, p2;
+  long n, i;
+  n = alg_get_absdim(al);
+  mt = alg_get_multable(al);
+  p2 = sqri(p);
+
+  I = ZM_hnfmodid(Ip, p);
+  Ii = ZM_inv(I,p);
+
+  M = cgetg(n+1, t_MAT);
+  for (i=1; i<=n; i++) {
+    imi = FpM_mul(Ii, FpM_mul(gel(mt,i), I, p2), p2);
+    imi = ZM_Z_divexact(imi, p);
+    gel(M,i) = mattocol(imi, n);
+  }
+
+  /*TODO : FpM_invimage superbad documentation (have to read RgM_invimage) Does it really do what it claims if left matrix is not invertible ?*/
+  K = FpM_ker(M, p);
+  if (lg(K)==1) { avma = av; return matid(n); }
+  K = ZM_hnfmodid(K,p);
+
+  return gerepileupto(av, ZM_Z_div(K,p));
+}
+
+GEN
+alg_ordermodp(GEN al, GEN p)
+{
+  GEN alp;
+  long i, N = alg_get_absdim(al);
+  alp = cgetg(12, t_VEC);
+  for (i=1; i<=8; i++) gel(alp,i) = gen_0;
+  gel(alp,9) = cgetg(N+1, t_VEC);
+  for(i=1; i<=N; i++) gmael(alp,9,i) = FpM_red(gmael(al,9,i), p);
+  gel(alp,10) = p;
+  gel(alp,11) = cgetg(N+1, t_VEC);
+  for(i=1; i<=N; i++) gmael(alp,11,i) = Fp_red(gmael(al,11,i), p);
+
+  return alp;
+}
+
+static GEN
+algpradical_i(GEN al, GEN p, GEN zprad, GEN projs)
+{
+  pari_sp av = avma;
+  GEN alp = alg_ordermodp(al, p), liftrad, projrad, alq, alrad, res, Lalp, radq;
+  long i;
+  if(lg(zprad)==1) {
+    liftrad = NULL;
+    projrad = NULL;
+  }
+  else {
+    alq = alg_quotient(alp, zprad, 1);
+    alp = gel(alq,1);
+    projrad = gel(alq,2);
+    liftrad = gel(alq,3);
+  }
+
+  if (projs) {
+    if (projrad) {
+      projs = gcopy(projs);
+      for(i=1; i<lg(projs); i++)
+        gel(projs,i) = FpM_FpC_mul(projrad, gel(projs,i), p);
+    }
+    Lalp = alg_centralproj(alp,projs,1);
+
+    alrad = cgetg(lg(Lalp),t_VEC);
+    for(i=1; i<lg(Lalp); i++) {
+      alq = gel(Lalp,i);
+      radq = algradical(gel(alq,1));
+      if(gequal0(radq))
+        gel(alrad,i) = cgetg(1,t_MAT);
+      else {
+        radq = FpM_mul(gel(alq,3),radq,p);
+        gel(alrad,i) = radq;
+      }
+    }
+    alrad = shallowmatconcat(alrad);
+    alrad = FpM_image(alrad,p);
+  }
+  else alrad = algradical(alp);
+
+  if(!gequal0(alrad)) {
+    if (liftrad) alrad = FpM_mul(liftrad, alrad, p);
+    res = shallowmatconcat(mkvec2(alrad, zprad));
+    res = FpM_image(res,p);
+  }
+  else res = lg(zprad)==1 ? gen_0 : gcopy(zprad);
+  return gerepilecopy(av, res);
+}
+#if 0
+/* not used */
+GEN
+algpradical(GEN al, GEN p)
+{
+  GEN placeholder = cgetg(1,t_MAT); /*left on stack*/
+  return algpradical_i(al, p, placeholder, NULL);
+}
+#endif
+
+static GEN
+algpdecompose0(GEN al, GEN prad, GEN p, GEN projs)
+{
+  pari_sp av = avma;
+  GEN alp, quo, ss, liftm = NULL, projm = NULL, dec, res, I, Lss, deci;
+  long i, j;
+
+  alp = alg_ordermodp(al, p);
+  if (!gequal0(prad)) {
+    quo = alg_quotient(alp,prad,1);
+    ss = gel(quo,1);
+    projm = gel(quo,2);
+    liftm = gel(quo,3);
+  }
+  else ss = alp;
+
+  if (projs) {
+    if (projm) {
+      for(i=1; i<lg(projs); i++)
+        gel(projs,i) = FpM_FpC_mul(projm, gel(projs,i), p);
+    }
+    Lss = alg_centralproj(ss, projs, 1);
+
+    dec = cgetg(lg(Lss),t_VEC);
+    for(i=1; i<lg(Lss); i++) {
+      gel(dec,i) = algsimpledec(gmael(Lss,i,1), 1);
+      deci = gel(dec,i);
+      for(j=1; j<lg(deci); j++)
+       gmael(deci,j,3) = FpM_mul(gmael(Lss,i,3), gmael(deci,j,3), p);
+    }
+    dec = shallowconcat1(dec);
+  }
+  else dec = algsimpledec(ss,1);
+
+  res = cgetg(lg(dec),t_VEC);
+  for (i=1; i<lg(dec); i++) {
+    I = gmael(dec,i,3);
+    if (liftm) I = FpM_mul(liftm,I,p);
+    I = shallowmatconcat(mkvec2(I,prad));
+    gel(res,i) = I;
+  }
+
+  return gerepilecopy(av, res);
+}
+
+/*finds a nontrivial ideal of O/prad or gen_0 if there is none.*/
+static GEN
+algpdecompose_i(GEN al, GEN p, GEN zprad, GEN projs)
+{
+  pari_sp av = avma;
+  GEN prad = algpradical_i(al,p,zprad,projs);
+  return gerepileupto(av, algpdecompose0(al, prad, p, projs));
+}
+#if 0
+/* not used */
+GEN
+algpdecompose(GEN al, GEN p)
+{
+  GEN placeholder = cgetg(1,t_MAT); /*left on stack*/
+  return algpdecompose_i(al, p, placeholder, NULL);
+}
+#endif
+
+/* ord is assumed to be in hnf wrt the integral basis of al. */
+/* assumes that alg_get_invord(al) is integral. */
+GEN
+alg_change_overorder_shallow(GEN al, GEN ord)
+{
+  GEN al2, mt, iord, mtx, den, den2, div;
+  long i, n;
+  n = alg_get_absdim(al);
+
+  iord = QM_inv(ord,gen_1);
+  al2 = shallowcopy(al);
+  ord = Q_remove_denom(ord,&den);
+
+  gel(al2,7) = Q_remove_denom(gel(al,7), &den2);
+  if (den2) div = mulii(den,den2);
+  else      div = den;
+  gel(al2,7) = ZM_Z_div(ZM_mul(gel(al2,7), ord), div);
+
+  gel(al2,8) = ZM_mul(iord, gel(al,8));
+
+  mt = cgetg(n+1,t_VEC);
+  gel(mt,1) = matid(n);
+  div = sqri(den);
+  for(i=2; i<=n; i++) {
+    mtx = algbasismultable(al,gel(ord,i));
+    gel(mt,i) = ZM_mul(iord, ZM_mul(mtx, ord));
+    gel(mt,i) = ZM_Z_divexact(gel(mt,i), div);
+  }
+  gel(al2,9) = mt;
+
+  gel(al2,11) = algtracebasis(al2);
+
+  return al2;
+}
+
+#if 0
+/* not used */
+/*ord is assumed to be in hnf wrt the integral basis of al.*/
+GEN
+alg_changeorder_shallow(GEN al, GEN ord)
+{
+  GEN al2, mt, iord, mtx;
+  long i, n;
+  n = alg_get_absdim(al);
+
+  iord = RgM_inv_upper(ord);
+  al2 = shallowcopy(al);
+  gel(al2,7) = RgM_mul(gel(al,7), ord);
+  gel(al2,8) = RgM_mul(iord, gel(al,8));
+
+  mt = cgetg(n+1,t_VEC);
+  gel(mt,1) = matid(n);
+  for(i=2; i<=n; i++) {
+    mtx = algbasismultable(al,gel(ord,i));
+    gel(mt,i) = RgM_mul(iord, RgM_mul(mtx, ord));
+  }
+  gel(al2,9) = mt;
+  gel(al2,11)= algtracebasis(al2);
+
+  return al2;
+}
+
+GEN
+alg_changeorder(GEN al, GEN ord)
+{
+  pari_sp av = avma;
+  GEN res = alg_changeorder_shallow(al, ord);
+  return gerepilecopy(av, res);
+}
+#endif
+
+static GEN
+algfromcenter(GEN al, GEN x)
+{
+  GEN nf = alg_get_center(al);
+  long n;
+  switch(alg_type(al)) {
+    case al_CYCLIC:
+      n = alg_get_degree(al);
+      break;
+    case al_CSA:
+      n = alg_get_dim(al);
+      break;
+    default:
+      return NULL;
+  }
+  return algalgtobasis(al, scalarcol(basistoalg(nf, x), n));
+}
+
+/* x is an ideal of the center in hnf form */
+static GEN
+algfromcenterhnf(GEN al, GEN x)
+{
+  GEN res;
+  long i;
+  res = cgetg(lg(x), t_MAT);
+  for(i=1; i<lg(x); i++) gel(res,i) = algfromcenter(al, gel(x,i));
+  return res;
+}
+
+/* assumes al is CSA or CYCLIC */
+static GEN
+algcenter_precompute(GEN al, GEN p)
+{
+  GEN nf, fa, pdec, nfprad, projs;
+  long i, np;
+  nf = alg_get_center(al);
+  fa = cgetg(3, t_MAT);
+  pdec = idealprimedec(nf, p);
+  settyp(pdec, t_COL);
+  np = lg(pdec)-1;
+  gel(fa,1) = pdec;
+  gel(fa,2) = cgetg(np+1, t_COL);
+  for(i=1; i<=np; i++) gcoeff(fa,i,2) = gen_1;
+  nfprad = idealfactorback(nf,fa,NULL,0);
+  projs = cgetg(np+1, t_VEC);
+  for(i=1; i<=np; i++) gel(projs, i) = idealchinese(nf, fa, vec_ei(np,i));
+  return mkvec2(nfprad, projs);
+}
+
+static GEN
+algcenter_prad(GEN al, GEN p, GEN pre)
+{
+  GEN nfprad, zprad, mtprad;
+  long i;
+  nfprad = gel(pre,1);
+  zprad = algfromcenterhnf(al, nfprad);
+  zprad = FpM_image(zprad, p);
+  mtprad = cgetg(lg(zprad), t_VEC);
+  for(i=1; i<lg(zprad); i++) gel(mtprad, i) = algbasismultable(al, gel(zprad,i));
+  mtprad = shallowmatconcat(mtprad);
+  zprad = FpM_image(mtprad, p);
+  return zprad;
+}
+
+static GEN
+algcenter_p_projs(GEN al, GEN p, GEN pre)
+{
+  GEN projs, zprojs;
+  long i;
+  projs = gel(pre,2);
+  zprojs = cgetg(lg(projs), t_VEC);
+  for(i=1; i<lg(projs); i++) gel(zprojs,i) = FpC_red(algfromcenter(al, gel(projs,i)),p);
+  return zprojs;
+}
+
+/*al is assumed to be simple*/
+static GEN
+alg_pmaximal_i(GEN al, GEN p)
+{
+  GEN al2, prad, lord = gen_0, I, id, dec, zprad, projs, pre;
+  long n, i;
+  n = alg_get_absdim(al);
+  id = matid(n);
+  al2 = al;
+
+  pre = algcenter_precompute(al,p);
+
+  while (1) {
+    zprad = algcenter_prad(al2, p, pre);
+    projs = algcenter_p_projs(al2, p, pre);
+    if (lg(projs) == 2) projs = NULL;
+    prad = algpradical_i(al2,p,zprad,projs);
+    if (typ(prad) == t_INT) break;
+    lord = algleftordermodp(al2,prad,p);
+    if (!cmp_universal(lord,id)) break;
+    al2 = alg_change_overorder_shallow(al2,lord);
+  }
+
+  dec = algpdecompose0(al2,prad,p,projs);
+  while (lg(dec)>2) {
+    for (i=1; i<lg(dec); i++) {
+      I = gel(dec,i);
+      lord = algleftordermodp(al2,I,p);
+      if (cmp_universal(lord,matid(n))) break;
+    }
+    if (i==lg(dec)) break;
+    al2 = alg_change_overorder_shallow(al2,lord);
+    zprad = algcenter_prad(al2, p, pre);
+    projs = algcenter_p_projs(al2, p, pre);
+    if (lg(projs) == 2) projs = NULL;
+    dec = algpdecompose_i(al2,p,zprad,projs);
+  }
+  return al2;
+}
+static GEN
+alg_pmaximal(GEN al, GEN p)
+{
+  pari_sp av = avma;
+  return gerepilecopy(av, alg_pmaximal_i(al, p));
+}
+
+static GEN
+algtracematrix(GEN al)
+{
+  GEN M, mt;
+  long n, i, j;
+  n = alg_get_absdim(al);
+  mt = alg_get_multable(al);
+  M = cgetg(n+1, t_MAT);
+  for (i=1; i<=n; i++)
+  {
+    gel(M,i) = cgetg(n+1,t_MAT);
+    for (j=1; j<=i; j++)
+      gcoeff(M,j,i) = gcoeff(M,i,j) = algabstrace(al,gmael(mt,i,j));
+  }
+  return M;
+}
+GEN
+algdisc(GEN al)
+{
+  pari_sp av = avma;
+  checkalg(al);
+  return gerepileuptoint(av, ZM_det(algtracematrix(al)));
+}
+static GEN
+alg_maximal(GEN al)
+{
+  pari_sp av = avma;
+  GEN fa = absi_factor(algdisc(al));
+  return gerepilecopy(av, alg_maximal_primes(al, gel(fa,1)));
+}
+
+/** IDEALS **/
+
+/*
+TODO :
+
+lattice :
+inter
+add
+mul
+(A:B)
+index (ideal from base field)
+subset
+mul by an ideal from base field
+
+full lattice / ideal ?
+leftorder/right
+norm (reduced)
+norm abs
+test (isfulllattice, isideal)
+2elt rep
+mul with 2elt repr
++ with hnfmod ?
+invert
+2sidedpart/primitivepart
+idealprimedec for two-sided above a prime
+factorization : two-sided part + intersection of p-power-norm ideals,
+for which we give a loc HNF
+
+approx
+
+orders :
+test (isorder)
+disc (different ?) (rnfdisc)
+pmaximal
+connecting ideal
+loc splitting
+*/
diff --git a/src/modules/aprcl.c b/src/modules/aprcl.c
index 3af8919..e8c6761 100644
--- a/src/modules/aprcl.c
+++ b/src/modules/aprcl.c
@@ -246,11 +246,11 @@ _powpolmod(Cache *C, GEN jac, Red *R, GEN (*_sqr)(GEN, Red *))
   const long efin = lg(taba)-1, lv = R->lv;
   GEN L, res = jac, pol2 = _sqr(res, R);
   long f;
-  pari_sp av0 = avma, av, lim;
+  pari_sp av0 = avma, av;
 
   L = cgetg(lv+1, t_VEC); gel(L,1) = res;
   for (f=2; f<=lv; f++) gel(L,f) = _mul(gel(L,f-1), pol2, R);
-  av = avma; lim = stack_lim(av, 1);
+  av = avma;
   for (f = efin; f >= 1; f--)
   {
     GEN t = gel(L, taba[f]);
@@ -258,7 +258,7 @@ _powpolmod(Cache *C, GEN jac, Red *R, GEN (*_sqr)(GEN, Red *))
     res = (f==efin)? t: _mul(t, res, R);
     while (tf--) {
       res = _sqr(res, R);
-      if (low_stack(lim, stack_lim(av,1))) {
+      if (gc_needed(av,1)) {
         res = gerepilecopy(av, res);
         if(DEBUGMEM>1) pari_warn(warnmem,"powpolmod: f = %ld",f);
       }
diff --git a/src/modules/ellsea.c b/src/modules/ellsea.c
index 104ecc8..4e66a19 100644
--- a/src/modules/ellsea.c
+++ b/src/modules/ellsea.c
@@ -87,7 +87,11 @@ list_to_pol(GEN list, long vx, long vy)
   return RgV_to_RgX_reverse(P, vx);
 }
 
-struct meqn { char type; GEN eq; };
+struct meqn {
+  char type;
+  GEN eq;
+  long vx,vy;
+};
 
 static int
 get_modular_eqn(struct meqn *M, ulong ell, long vx, long vy)
@@ -99,10 +103,11 @@ get_modular_eqn(struct meqn *M, ulong ell, long vx, long vy)
     eqn = gel(modular_eqn, idx);
   else
     eqn = get_seadata(ell);
-  if (!eqn) return 0;
+  if (!eqn) { M->type = 0; M->eq = NULL; return 0; }
   M->type = *GSTR(gel(eqn, 2));
   M->eq = list_to_pol(gel(eqn, 3), vx, vy);
-  return 1;
+  M->vx = vx;
+  M->vy = vy; return 1;
 }
 
 static void
@@ -115,7 +120,7 @@ ellmodulareqn(long ell, long vx, long vy)
   pari_sp av = avma;
   struct meqn meqn;
   if (vx<0) vx=0;
-  if (vy<0) vy=fetch_user_var("y");
+  if (vy<0) vy=1;
   if (varncmp(vx,vy)>=0)
     pari_err_PRIORITY("ellmodulareqn", pol_x(vx), ">=", vy);
   if (ell < 0 || !uisprime(ell))
@@ -126,75 +131,123 @@ ellmodulareqn(long ell, long vx, long vy)
   return gerepilecopy(av,mkvec2(meqn.eq, stoi(meqn.type=='A')));
 }
 
+static GEN
+Fq_elldivpol2(GEN a4, GEN a6, GEN T, GEN p)
+{
+  return mkpoln(4, utoi(4), gen_0, Fq_mulu(a4, 4, T, p), Fq_mulu(a6, 4, T, p));
+}
+
+static GEN
+Fq_elldivpol2d(GEN a4, GEN T, GEN p)
+{
+  return mkpoln(3, utoi(6), gen_0, Fq_mulu(a4, 2, T, p));
+}
+
+static GEN
+FqX_numer_isog_abscissa(GEN h, GEN a4, GEN a6, GEN T, GEN p, long vx)
+{
+  GEN mp1, dh, ddh, t, u, t1, t2, t3, t4, f0;
+  long m = degpol(h);
+  mp1 = gel(h, m + 1); /* negative of first power sum */
+  dh = FqX_deriv(h, T, p);
+  ddh = FqX_deriv(dh, T, p);
+  t  = Fq_elldivpol2(a4, a6, T, p);
+  u  = Fq_elldivpol2d(a4, T, p);
+  t1 = FqX_sub(FqX_sqr(dh, T, p), FqX_mul(ddh, h, T, p), T, p);
+  t2 = FqX_mul(u, FqX_mul(h, dh, T, p), T, p);
+  t3 = FqX_mul(FqX_sqr(h, T, p),
+               deg1pol_shallow(stoi(2*m), Fq_mulu(mp1, 2, T, p), vx), T, p);
+  f0 = FqX_add(FqX_sub(FqX_mul(t, t1, T, p), t2, T, p), t3, T, p);
+  t4 = FqX_mul(pol_x(vx),  FqX_sqr(h, T, p), T, p);
+  return FqX_add(t4, f0, T, p);
+}
+
+static GEN
+Zq_inv(GEN b, GEN T, GEN q, GEN p, long e)
+{
+  return e==1 ? Fq_inv(b, T, p):
+         typ(b)==t_INT ? Fp_inv(b, q):  ZpXQ_inv(b, T, p, e);
+}
+
+static GEN
+Zq_div(GEN a, GEN b, GEN T, GEN q, GEN p, long e)
+{
+  if (e==1) return Fq_div(a, b, T, q);
+  return Fq_mul(a, Zq_inv(b, T, q, p, e), T, q);
+}
+
+static GEN
+Zq_sqrt(GEN b, GEN T, GEN q, GEN p, long e)
+{
+  return e==1 ? Fq_sqrt(b, T, q):
+         typ(b)==t_INT ? Zp_sqrt(b, p, e):  ZpXQ_sqrt(b, T, p, e);
+}
+
+static GEN
+Zq_divexact(GEN a, GEN b)
+{
+  return typ(a)==t_INT ? diviiexact(a, b): ZX_Z_divexact(a, b);
+}
+
+static long
+Zq_pval(GEN a, GEN p)
+{
+  return typ(a)==t_INT ? Z_pval(a, p): ZX_pval(a, p);
+}
+
+static GEN
+Zq_Z_div_safe(GEN a, GEN b, GEN T, GEN q, GEN p, long e)
+{
+  long v;
+  if (e==1) return Fq_div(a, b, T, q);
+  v = Z_pvalrem(b, p, &b);
+  if (v>0)
+  {
+    long w = Z_pval(Q_content(a), p);
+    if (v>w) pari_err_INV("Zq_div",b);
+    a = Zq_divexact(a, powiu(p,v));
+  }
+  return Fq_Fp_mul(a, Fp_inv(b, q), T, q);
+}
+
 /*Gives the first precS terms of the Weierstrass series related to */
 /*E: y^2 = x^3 + a4x + a6.  Assumes (precS-2)*(2precS+3) < ULONG_MAX, i.e.
  * precS < 46342 in 32-bit machines */
 static GEN
-find_coeff(GEN a4, GEN a6, GEN T, GEN p, long precS)
+find_coeff(GEN a4, GEN a6, GEN T, GEN p, long precS, GEN pp, long e)
 {
-  GEN res = cgetg(precS+1, t_VEC);
+  GEN res, den;
   long k, h;
+  if (e > 1) { p = sqri(p); e *= 2; }
+  res = cgetg(precS+1, t_VEC);
+  den = cgetg(precS+1, t_VECSMALL);
   if (precS == 0) return res;
   gel(res, 1) = Fq_div(a4, stoi(-5), T, p);
+  den[1] = 0;
   if (precS == 1) return res;
   gel(res, 2) = Fq_div(a6, stoi(-7), T, p);
+  den[2] = 0;
   for (k = 3; k <= precS; ++k)
   {
     pari_sp btop = avma;
-    GEN a = gen_0;
+    GEN a = gen_0, d;
+    long v=0;
+    if (e > 1)
+      for (h = 1; h <= k-2; h++)
+        v = maxss(v, den[h]+den[k-1-h]);
     for (h = 1; h <= k-2; h++)
-      a = Fq_add(a, Fq_mul(gel(res, h), gel(res, k-1-h), T, p), T, p);
-    a = Fq_div(Fq_mulu(a, 3, T, p), utoi((k-2) * (2*k + 3)), T, p);
+    {
+      GEN b = Fq_mul(gel(res, h), gel(res, k-1-h), T, p);
+      if (v)
+        b = Fq_Fp_mul(b, powiu(pp, v-(den[h]+den[k-1-h])), T, p);
+      a = Fq_add(a, b, T, p);
+    }
+    v += Z_pvalrem(utoi((k-2) * (2*k + 3)), pp, &d);
+    a = Zq_div(gmulgs(a, 3), d, T, p, pp, e);
     gel(res, k) = gerepileupto(btop, a);
+    den[k] = v;
   }
-  return res;
-}
-
-/* Given power series s1 and s2, finds a polynomial P such that s2 = P(s1) */
-static GEN
-find_transformation(GEN s2, GEN s1)
-{
-  pari_sp ltop = avma, btop, st_lim;
-  long i, vx = varn(s1), vs1 = valp(s1), vs2 = valp(s2), degP = vs2/vs1;
-  GEN invs1coeff = ginv(gel(s1, 2)), P = gen_0, s1pl = cgetg(degP+1, t_VEC);
-
-  gel(s1pl, 1) = s1;
-  for (i = 2; i <= degP; i++) gel(s1pl, i) = gmul(s1, gel(s1pl, i-1));
-  btop = avma; st_lim = stack_lim(btop, 1);
-  for (i = 0; i < degP; i++)
-  {
-    GEN Pcoeff = gmul(gel(s2,2), invs1coeff);
-    P = gadd(P, gmul(Pcoeff, monomial(gen_1, degP-i, vx)));
-    s2 = gsub(s2, gmul(Pcoeff, gel(s1pl, degP-i)));
-    if (low_stack(st_lim, stack_lim(btop, 1))) gerepileall(btop, 2, &P, &s2);
-  }
-  P = gadd(P, gmul(gel(s2,2), invs1coeff));
-  return gerepileupto(ltop, P);
-}
-
-static GEN
-compute_W(GEN a4, GEN a6, GEN T, GEN p, long vx, long precS)
-{
-  pari_sp ltop = avma;
-  GEN c  = find_coeff(a4, a6, T, p, precS);
-  GEN s  = RgX_inflate(RgV_to_RgX(c,vx), 2);
-  GEN z2 = monomial(gen_1, 2, vx);
-  s = gadd(gadd(ginv(z2), gmul(s, z2)), zeroser(vx, 2*precS));
-  return gerepileupto(ltop, s);
-}
-
-/*Finds numerator phi of the isogeny between Eb and Ec whose denominator is h*/
-static GEN
-find_numerator_isogeny(GEN Eba4, GEN Eba6, GEN Eca4, GEN Eca6, GEN h, GEN T, GEN p,
-                       long precS)
-{
-  pari_sp ltop = avma;
-  GEN mod1p = gmodulsg(1,p);
-  GEN mod = T ? gmodulo(mod1p, gmul(get_FpX_mod(T), mod1p)): mod1p;
-  GEN WEb = gmul(compute_W(Eba4, Eba6, T, p, varn(h), precS), mod);
-  GEN WEc = gmul(compute_W(Eca4, Eca6, T, p, varn(h), precS), mod);
-  GEN den = poleval(h, WEb);
-  return gerepileupto(ltop, find_transformation(gmul(gsqr(den), WEc), WEb));
+  return mkvec2(res, den);
 }
 
 /****************************************************************************/
@@ -211,6 +264,15 @@ Fq_ellj(GEN a4, GEN a6, GEN T, GEN p)
   return gerepileupto(ltop, j);
 }
 
+static GEN
+Zq_ellj(GEN a4, GEN a6, GEN T, GEN p, GEN pp, long e)
+{
+  pari_sp ltop=avma;
+  GEN a43 = Fq_mulu(Fq_powu(a4, 3, T, p), 4, T, p);
+  GEN j   = Zq_div(Fq_mulu(a43, 1728, T, p),
+                   Fq_add(a43, Fq_mulu(Fq_sqr(a6, T, p), 27, T, p), T, p), T, p, pp, e);
+  return gerepileupto(ltop, j);
+}
 /****************************************************************************/
 /*                              EIGENVALUE                                  */
 /****************************************************************************/
@@ -394,6 +456,12 @@ eigen_ellmulu(struct eigen_ellinit *E, GEN z, ulong n)
     return gerepileupto(av, gen_powu(z, n, E, &eigen_elldbl, &eigen_elladd));
 }
 
+static GEN
+Fq_to_Flx(GEN a4, GEN T, ulong p)
+{
+  return typ(a4)==t_INT ? Z_to_Flx(a4, p, get_FpX_var(T)): ZX_to_Flx(a4, p);
+}
+
 /*Finds the eigenvalue of the Frobenius given E, ell odd prime, h factor of the
  *ell-division polynomial, p and tr the possible values for the trace
  *(useful for primes with one root)*/
@@ -406,14 +474,14 @@ find_eigen_value(GEN a4, GEN a6, ulong ell, GEN h, GEN T, GEN p, GEN tr)
   struct eigen_ellinit Edat;
   ulong pp = T ?itou_or_0(p): 0;
   if (pp)
-    init_eigenu(&Edat, ZX_to_Flx(a4,pp), ZX_to_Flx(a6,pp),
+    init_eigenu(&Edat, Fq_to_Flx(a4, T, pp), Fq_to_Flx(a6, T, pp),
                        ZXX_to_FlxX(h,pp, get_FpX_var(T)), ZXT_to_FlxT(T,pp), pp);
   else
     init_eigen(&Edat, a4, a6, h, T, p);
   Dr = BP = Edat.O;
   /*[0,Gr], BP, Dr are not points on the curve. */
   /*To obtain the corresponding points, multiply the y-coordinates by Y */
-  if (!tr || lg(tr)==1)
+  if (!tr)
   {
     pari_sp btop = avma;
     for (t = 1; t <= (ell>>1); t++)
@@ -423,17 +491,16 @@ find_eigen_value(GEN a4, GEN a6, ulong ell, GEN h, GEN T, GEN p, GEN tr)
       Dr = pp ? eigenu_elladd(&Edat, Dr, BP): eigen_elladd(&Edat, Dr, BP);
       Dr = gerepileupto(btop, Dr);
     }
-    pari_err_BUG("find_eigen_value");
-    return 0; /* NOT REACHED */
   }
   else
   {
     t = Fl_div(tr[1], 2, ell);
     if (t < (ell>>1)) t = ell - t;
     Dr = eigen_ellmulu(&Edat, BP, t);
-    if (!gequal(gel(Dr,2), Edat.Gr)) t = ell - t;
-    avma = ltop; return t;
+    if (gequal(gel(Dr,2), Edat.Gr)) { avma = ltop; return t; }
+    if (gequal(gel(Dr,2), Edat.nGr)) { avma = ltop; return ell - t; }
   }
+  pari_err_BUG("find_eigen_value"); return 0; /* NOT REACHED */
 }
 
 /*Finds the eigenvalue of the Frobenius modulo ell^k given E, ell, k, h factor
@@ -442,7 +509,7 @@ static ulong
 find_eigen_value_power(GEN a4, GEN a6, ulong ell, long k, GEN h, ulong lambda, GEN T, GEN p)
 {
   pari_sp ltop = avma;
-  pari_sp btop, st_lim;
+  pari_sp btop;
   struct eigen_ellinit Edat;
   GEN BP, Dr, Gr, nGr;
   /*[0,Gr], BP, Dr are not points on the curve. */
@@ -450,7 +517,7 @@ find_eigen_value_power(GEN a4, GEN a6, ulong ell, long k, GEN h, ulong lambda, G
   ulong t, ellk1 = upowuu(ell, k-1), ellk = ell*ellk1;
   ulong pp = T ?itou_or_0(p): 0;
   if (pp)
-    init_eigenu(&Edat, ZX_to_Flx(a4,pp), ZX_to_Flx(a6,pp),
+    init_eigenu(&Edat, Fq_to_Flx(a4, T, pp), Fq_to_Flx(a6, T, pp),
         ZXX_to_FlxX(h, pp, get_FpX_var(T)), ZXT_to_FlxT(T,pp), pp);
   else
     init_eigen(&Edat, a4, a6, h, T, p);
@@ -458,13 +525,13 @@ find_eigen_value_power(GEN a4, GEN a6, ulong ell, long k, GEN h, ulong lambda, G
   Dr = eigen_ellmulu(&Edat, Edat.O, lambda);
   Gr = Edat.Gr; nGr = Edat.nGr;
 
-  btop = avma; st_lim = stack_lim(btop, 1);
+  btop = avma;
   for (t = 0; t < ellk; t += ellk1)
   {
     if (gequal(gel(Dr,2), Gr))  { avma = ltop; return t+lambda; }
     if (gequal(gel(Dr,2), nGr)) { avma = ltop; return ellk-(t+lambda); }
     Dr = pp ? eigenu_elladd(&Edat, Dr, BP): eigen_elladd(&Edat, Dr, BP);
-    if (low_stack(st_lim, stack_lim(btop, 1)))
+    if (gc_needed(btop, 1))
       Dr = gerepileupto(btop, Dr);
   }
   pari_err_BUG("find_eigen_value_power");
@@ -475,82 +542,83 @@ find_eigen_value_power(GEN a4, GEN a6, ulong ell, long k, GEN h, ulong lambda, G
   isogenous curve Eb and trace term pp1. Uses CCR algorithm and returns h.
   Return NULL if E and Eb are *not* isogenous. */
 static GEN
-find_kernel(GEN a4, GEN a6, ulong ell, GEN a4t, GEN a6t, GEN pp1, GEN T, GEN p)
+find_kernel(GEN a4, GEN a6, ulong ell, GEN a4t, GEN a6t, GEN pp1, GEN T, GEN p, GEN pp, long e)
 {
   const long ext = 2;
-  pari_sp ltop = avma;
-  GEN M, N, V, K, K1, K2, v, tlist, res;
+  pari_sp ltop = avma, btop;
+  GEN P, v, tlist, h;
   long i, j, k;
-  long deg = (ell - 1)/2, dim = deg + ext;
-  GEN Coeff  = find_coeff(a4, a6, T, p, dim);
-  GEN Coefft = find_coeff(a4t, a6t, T, p, dim);
-  GEN psi2  = mkpoln(4, utoi(4), gen_0, Fq_mulu(a4, 4, T, p), Fq_mulu(a6, 4, T, p));
-  GEN list  = cgetg(dim+1, t_VEC);
-  GEN Dpsi2 = mkpoln(3, utoi(6), gen_0, Fq_mulu(a4, 2, T, p));
-  gel(list, 1) = Dpsi2;
-  for (k = 2; k <= dim; k++)
+  long deg = (ell - 1)/2, dim = 2 + deg + ext;
+  GEN psi2 = Fq_elldivpol2(a4, a6, T, p);
+  GEN Dpsi2 = Fq_elldivpol2d(a4, T, p);
+  GEN C  = find_coeff(a4, a6, T, p, dim, pp, e);
+  GEN Ct = find_coeff(a4t, a6t, T, p, dim, pp, e);
+  GEN V = cgetg(dim+1, t_VEC);
+  for (k = 1; k <= dim; k++)
   {
-    pari_sp btop = avma;
-    GEN tsil = gel(list, k-1);
-    GEN r = FqX_Fq_mul(Dpsi2, gel(tsil,3), T, p);
-    for (j = 4; j < lg(tsil); j++)
+    long v = mael(C,2,k);
+    GEN z = gmul(gsub(gmael(Ct,1,k), gmael(C,1,k)), shifti(mpfact(2*k), -1));
+    if (signe(z) && Zq_pval(z, pp) < v) return NULL;
+    gel(V, k) = Zq_divexact(z, powiu(pp, v));
+  }
+  btop = avma;
+  v = zerovec(dim);
+  gel(v, 1) = utoi(deg);
+  gel(v, 2) = pp1;
+  P = pol_x(0);
+  for (k = 3; k <= dim; k++)
+  {
+    GEN s, r = FqX_Fq_mul(Dpsi2, gel(P, 3), T, p);
+    for (j = 4; j < lg(P); j++)
     {
       long o = j - 2;
       GEN D = FqX_add(RgX_shift_shallow(Dpsi2, 1), FqX_mulu(psi2, o-1, T, p), T, p);
-      GEN E = FqX_Fq_mul(D, Fq_mulu(gel(tsil, j), o, T, p), T, p);
+      GEN E = FqX_Fq_mul(D, Fq_mulu(gel(P, j), o, T, p), T, p);
       r = FqX_add(r, RgX_shift_shallow(E, o-2), T, p);
     }
-    gel(list, k) = gerepileupto(btop, r);
-  }
-  for (k = 2; k <= dim; k++)
-  {
-     GEN C = Fq_inv(shifti(mpfact(2*k),-1), T, p);
-     gel(list, k) = FqX_Fq_mul(gel(list, k), C, T, p);
+    P = r;
+    s = Fq_mul(gel(P, 2), gel(v, 1), T, p);
+    for (j = 3; j < lg(P)-1; j++)
+      s = Fq_add(s, Fq_mul(gel(P, j), gel(v, j-1), T, p), T, p);
+    gel(v, k) = Zq_Z_div_safe(Fq_sub(gel(V, k-2), s, T, p), gel(P, j), T, p, pp, e);
+    if (gc_needed(btop, 1))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"find_kernel");
+      gerepileall(btop, 2, &v, &P);
+    }
   }
-  M = shallowtrans(RgXV_to_RgM(list, dim+2));
-  N = vecslice(M, 1, dim);
-  V = FqC_sub(Coefft, Coeff, T, p);
-  v = shallowconcat(FqM_FqC_gauss(N, V, T, p), mkcol2(gen_0, gen_0));
-  K = FqM_ker(M, T, p);
-  if (lg(K) != 3) pari_err_BUG("trace not determined in a unique way");
-  K1 = FqC_Fq_mul(gel(K,1), Fq_inv(gcoeff(K,1,1), T, p), T, p);
-  K2 = FqC_sub(gel(K,2), FqC_Fq_mul(K1, gcoeff(K,1,2), T, p), T, p);
-  K2 = FqC_Fq_mul(K2, Fq_inv(gel(K2,2), T, p), T, p);
-  K1 = FqC_sub(K1, FqC_Fq_mul(K2, gel(K1,2), T, p), T, p);
-  v = FqC_add(v, FqC_Fq_mul(K1, Fq_sub(utoi(deg), gel(v,1), T, p), T, p), T, p);
-  v = FqC_add(v, FqC_Fq_mul(K2, Fq_sub(pp1, gel(v,2), T, p), T, p), T, p);
-  tlist = cgetg(dim+2, t_VEC);
-  gel(tlist, dim+1) = gen_1;
-  for (k = 1; k <= dim; k++)
+  tlist = cgetg(dim, t_VEC);
+  gel(tlist, dim-1) = gen_1;
+  for (k = 1; k <= dim-2; k++)
   {
     pari_sp btop = avma;
     GEN s = gel(v, k+1);
     for (i = 1; i < k; i++)
-      s = Fq_add(s, Fq_mul(gel(tlist, dim-i+1), gel(v, k-i+1), T, p), T, p);
-    gel(tlist, dim-k+1) = gerepileupto(btop, Fq_div(s, stoi(-k), T, p));
+      s = Fq_add(s, Fq_mul(gel(tlist, dim-i-1), gel(v, k-i+1), T, p), T, p);
+    gel(tlist, dim-k-1) = gerepileupto(btop, Zq_Z_div_safe(s, stoi(-k), T, p, pp, e));
   }
   for (i = 1; i <= ext; i++)
-    if (signe(gel(tlist, i))) { avma = ltop; return NULL; }
-  res = vecslice(tlist, ext+1, dim+1);
-
-  return RgV_to_RgX(res, 0);
+    if (signe(Fq_red(gel(tlist, i),T, pp))) { avma = ltop; return NULL; }
+  h = FqX_red(RgV_to_RgX(vecslice(tlist, ext+1, dim-1), 0),T,p);
+  return signe(Fq_elldivpolmod(a4, a6, ell, h, T, pp)) ? NULL: h;
 }
 
 static GEN
-compute_u(GEN gprime, GEN Dxxg, GEN DxJg, GEN DJJg, GEN j, GEN pJ, GEN px, ulong q, GEN E4, GEN E6, GEN T, GEN p)
+compute_u(GEN gprime, GEN Dxxg, GEN DxJg, GEN DJJg, GEN j, GEN pJ, GEN px, ulong q, GEN E4, GEN E6, GEN T, GEN p, GEN pp, long e)
 {
   pari_sp ltop = avma;
   GEN dxxgj = FqX_eval(Dxxg, j, T, p);
   GEN dxJgj = FqX_eval(DxJg, j, T, p);
   GEN dJJgj = FqX_eval(DJJg, j, T, p);
-  GEN E42 = Fq_sqr(E4, T, p), E6ovE4 = Fq_div(E6, E4, T, p);
+  GEN E42 = Fq_sqr(E4, T, p), E6ovE4 = Zq_div(E6, E4, T, p, pp, e);
   GEN a = Fq_mul(gprime, dxxgj, T, p);
   GEN b = Fq_mul(Fq_mul(Fq_mulu(j,2*q, T, p), dxJgj, T, p), E6ovE4, T, p);
-  GEN c = Fq_mul(Fq_div(Fq_sqr(E6ovE4, T, p), gprime, T, p), j, T, p);
+  GEN c = Fq_mul(Zq_div(Fq_sqr(E6ovE4, T, p), gprime, T, p, pp, e), j, T, p);
   GEN d = Fq_mul(Fq_mul(c,sqru(q), T, p), Fq_add(pJ, Fq_mul(j, dJJgj, T, p), T, p), T, p);
-  GEN e = Fq_sub(Fq_div(E6ovE4,utoi(3), T, p), Fq_div(E42, Fq_mulu(E6,2,T, p), T, p), T, p);
-  GEN f = Fq_sub(Fq_sub(b,a,T,p), d, T, p);
-  return gerepileupto(ltop, Fq_add(Fq_div(f,px,T,p), Fq_mulu(e,q,T,p), T, p));
+  GEN f = Fq_sub(Fq_div(E6ovE4,utoi(3), T, p),
+                 Zq_div(E42, Fq_mulu(E6,2,T, p), T, p, pp, e), T, p);
+  GEN g = Fq_sub(Fq_sub(b,a,T,p), d, T, p);
+  return gerepileupto(ltop, Fq_add(Zq_div(g,px,T,p,pp,e), Fq_mulu(f,q,T,p), T, p));
 }
 
 /* Finds the isogenous EC, and the sum of the x-coordinates of the points in
@@ -558,60 +626,70 @@ compute_u(GEN gprime, GEN Dxxg, GEN DxJg, GEN DJJg, GEN j, GEN pJ, GEN px, ulong
  * E: elliptic curve, ell: a prime, meqn: Atkin modular equation
  * g: root of meqn defining isogenous curve Eb. */
 static GEN
-find_isogenous_from_Atkin(GEN a4, GEN a6, long ell, GEN meqn, GEN g, GEN T, GEN p)
+find_isogenous_from_Atkin(GEN a4, GEN a6, ulong ell, struct meqn *MEQN, GEN g, GEN T, GEN pp, long e)
 {
   pari_sp ltop = avma, btop;
-  GEN Roots, gprime, u1;
-  long k, vx = 0, vJ = MAXVARN;
+  GEN meqn = MEQN->eq, meqnx, Roots, gprime, u1;
+  long k, vJ = MEQN->vy;
+  GEN p = e==1 ? pp: powiu(pp, e);
   GEN E4 = Fq_div(a4, stoi(-3), T, p);
-  GEN E6 = Fq_mul(a6, shifti(p, -1), T, p);
+  GEN E6 = Fq_neg(Fq_halve(a6, T, p), T, p);
   GEN E42 = Fq_sqr(E4, T, p);
   GEN E43 = Fq_mul(E4, E42, T, p);
   GEN E62 = Fq_sqr(E6, T, p);
   GEN delta = Fq_div(Fq_sub(E43, E62, T, p), utoi(1728), T, p);
-  GEN j = Fq_div(E43, delta, T, p);
-  GEN Dx = deriv(meqn, vx);
+  GEN j = Zq_div(E43, delta, T, p, pp, e);
+  GEN Dx = RgX_deriv(meqn);
   GEN DJ = deriv(meqn, vJ);
   GEN Dxg = FpXY_Fq_evaly(Dx, g, T, p, vJ);
   GEN px = FqX_eval(Dxg, j, T, p), dx = Fq_mul(px, g, T, p);
   GEN DJg = FpXY_Fq_evaly(DJ, g, T, p, vJ);
   GEN pJ = FqX_eval(DJg, j, T, p), dJ = Fq_mul(pJ, j, T, p);
-  GEN Dxx = deriv(Dx, vx);
+  GEN Dxx = RgX_deriv(Dx);
   GEN DxJg = FqX_deriv(Dxg, T, p);
 
   GEN Dxxg = FpXY_Fq_evaly(Dxx, g, T, p, vJ);
   GEN DJJg = FqX_deriv(DJg, T, p);
-
-  GEN a = Fq_mul(dJ, Fq_mul(g, E6, T, p), T, p);
-  GEN b = Fq_mul(E4, dx, T, p);
-  if (!signe(a) || !signe(b))
-  { /* TODO: understand what this means and use the information */
-    if (DEBUGLEVEL)
-      err_printf("find_isogenous_from_Atkin: division by zero at prime %ld", ell);
+  GEN a, b;
+  if (!signe(dJ) || !signe(dx))
+  {
+    if (DEBUGLEVEL>0) err_printf("[A: d%c=0]",signe(dJ)? 'x': 'J');
     avma = ltop; return NULL;
   }
-  gprime = Fq_div(a, b, T, p);
+  a = Fq_mul(dJ, Fq_mul(g, E6, T, p), T, p);
+  b = Fq_mul(E4, dx, T, p);
+  gprime = Zq_div(a, b, T, p, pp, e);
+
+  u1 = compute_u(gprime, Dxxg, DxJg, DJJg, j, pJ, px, 1, E4, E6, T, p, pp, e);
+  meqnx = FpXY_Fq_evaly(meqn, g, T, p, vJ);
+  Roots = FqX_roots(meqnx, T, pp);
 
-  u1 = compute_u(gprime, Dxxg, DxJg, DJJg, j, pJ, px, 1, E4, E6, T, p);
-  Roots = FqX_roots(FpXY_Fq_evaly(meqn, g, T, p, vJ), T, p);
   btop = avma;
   for (k = lg(Roots)-1; k >= 1; k--, avma = btop)
   {
-    GEN jt = gel(Roots, k);
-    GEN pxstar = FqX_eval(Dxg, jt, T, p);
-    GEN dxstar = Fq_mul(pxstar, g, T, p);
-    GEN pJstar = FqX_eval(DJg, jt, T, p);
-    GEN dJstar = Fq_mul(Fq_mulu(jt, ell, T, p), pJstar, T, p);
-    GEN u = Fq_mul(Fq_mul(dxstar, dJ, T, p), E6, T, p);
-    GEN v = Fq_mul(Fq_mul(dJstar, dx, T, p), E4, T, p);
-    GEN E4t = Fq_div(Fq_mul(Fq_sqr(u, T, p), jt, T, p), Fq_mul(Fq_sqr(v, T, p), Fq_sub(jt, utoi(1728), T, p), T, p), T, p);
-    GEN E6t = Fq_div(Fq_mul(u, E4t, T, p), v, T, p);
-    GEN u2 = compute_u(gprime, Dxxg, DxJg, DJJg, jt, pJstar, pxstar, ell, E4t, E6t, T, p);
-    GEN pp1 = Fq_mulu(Fq_sub(u1, u2, T, p), 3*ell, T, p);
-    GEN a4t = Fq_mul(mulsi(-3, powuu(ell,4)), E4t, T, p);
-    GEN a6t = Fq_mul(mulsi(-2, powuu(ell,6)), E6t, T, p);
-    GEN h = find_kernel(a4, a6, ell, a4t, a6t, pp1, T, p);
-    if (h) return gerepilecopy(ltop, mkvec3(a4t, a6t, h));
+    GEN jt = e==1 ? gel(Roots, k): ZpXQX_liftroot(meqnx, gel(Roots, k), T, pp, e);
+    if (signe(jt) == 0 || signe(Fq_sub(jt, utoi(1728), T, p)) == 0)
+    {
+      if (DEBUGLEVEL>0) err_printf("[A: jt=%ld]",signe(jt)? 1728: 0);
+      avma = ltop; return NULL;
+    }
+    else
+    {
+      GEN pxstar = FqX_eval(Dxg, jt, T, p);
+      GEN dxstar = Fq_mul(pxstar, g, T, p);
+      GEN pJstar = FqX_eval(DJg, jt, T, p);
+      GEN dJstar = Fq_mul(Fq_mulu(jt, ell, T, p), pJstar, T, p);
+      GEN u = Fq_mul(Fq_mul(dxstar, dJ, T, p), E6, T, p);
+      GEN v = Fq_mul(Fq_mul(dJstar, dx, T, p), E4, T, p);
+      GEN E4t = Zq_div(Fq_mul(Fq_sqr(u, T, p), jt, T, p), Fq_mul(Fq_sqr(v, T, p), Fq_sub(jt, utoi(1728), T, p), T, p), T, p, pp, e);
+      GEN E6t = Zq_div(Fq_mul(u, E4t, T, p), v, T, p, pp, e);
+      GEN u2 = compute_u(gprime, Dxxg, DxJg, DJJg, jt, pJstar, pxstar, ell, E4t, E6t, T, p, pp, e);
+      GEN pp1 = Fq_mulu(Fq_sub(u1, u2, T, p), 3*ell, T, p);
+      GEN a4t = Fq_mul(mulsi(-3, powuu(ell,4)), E4t, T, p);
+      GEN a6t = Fq_mul(mulsi(-2, powuu(ell,6)), E6t, T, p);
+      GEN h = find_kernel(a4, a6, ell, a4t, a6t, pp1, T, p, pp, e);
+      if (h) return gerepilecopy(ltop, mkvec3(a4t, a6t, h));
+    }
   }
   pari_err_BUG("find_isogenous_from_Atkin, kernel not found");
   return NULL;
@@ -622,25 +700,27 @@ find_isogenous_from_Atkin(GEN a4, GEN a6, long ell, GEN meqn, GEN g, GEN T, GEN
  * E: elliptic curve, ell: a prime, meqn: canonical modular equation
  * g: root of meqn defining isogenous curve Eb. */
 static GEN
-find_isogenous_from_canonical(GEN a4, GEN a6, long ell, GEN meqn, GEN g, GEN T, GEN p)
+find_isogenous_from_canonical(GEN a4, GEN a6, ulong ell, struct meqn *MEQN, GEN g, GEN T, GEN pp, long e)
 {
   pari_sp ltop = avma;
-  long vx = 0, vJ = MAXVARN;
+  GEN meqn = MEQN->eq;
+  long vJ = MEQN->vy;
+  GEN p = e==1 ? pp: powiu(pp, e);
   GEN h;
   GEN E4 = Fq_div(a4, stoi(-3), T, p);
-  GEN E6 = Fq_mul(a6, shifti(p, -1), T, p);
+  GEN E6 = Fq_neg(Fq_halve(a6, T, p), T, p);
   GEN E42 = Fq_sqr(E4, T, p);
   GEN E43 = Fq_mul(E4, E42, T, p);
   GEN E62 = Fq_sqr(E6, T, p);
   GEN delta = Fq_div(Fq_sub(E43, E62, T, p), utoi(1728), T, p);
-  GEN j = Fq_div(E43, delta, T, p);
-  GEN Dx = deriv(meqn, vx);
+  GEN j = Zq_div(E43, delta, T, p, pp, e);
+  GEN Dx = RgX_deriv(meqn);
   GEN DJ = deriv(meqn, vJ);
   GEN Dxg = FpXY_Fq_evaly(Dx, g, T, p, vJ);
   GEN px  = FqX_eval(Dxg, j, T, p), dx  = Fq_mul(px, g, T, p);
   GEN DJg = FpXY_Fq_evaly(DJ, g, T, p, vJ);
   GEN pJ = FqX_eval(DJg, j, T, p), dJ = Fq_mul(j, pJ, T, p);
-  GEN Dxx = deriv(Dx, vx);
+  GEN Dxx = RgX_deriv(Dx);
   GEN DxJg = FqX_deriv(Dxg, T, p);
 
   GEN ExJ = FqX_eval(DxJg, j, T, p);
@@ -648,49 +728,95 @@ find_isogenous_from_canonical(GEN a4, GEN a6, long ell, GEN meqn, GEN g, GEN T,
   GEN itis = Fq_inv(stoi(-tis), T, p);
   GEN deltal = Fq_div(Fq_mul(delta, Fq_powu(g, tis, T, p), T, p), powuu(ell, 12), T, p);
   GEN E4l, E6l, a4tilde, a6tilde, p_1;
+  if (signe(dx)==0)
+  {
+    if (DEBUGLEVEL>0) err_printf("[C: dx=0]");
+    avma = ltop; return NULL;
+  }
   if (signe(dJ)==0)
   {
     GEN jl;
-    if (DEBUGLEVEL) err_printf("Division by zero for prime %Ps\n", T, p);
+    if (DEBUGLEVEL>0) err_printf("[C: dJ=0]");
     E4l = Fq_div(E4, sqru(ell), T, p);
-    jl  = Fq_div(Fq_powu(E4l, 3, T, p), deltal, T, p);
-    E6l = Fq_sqrt(Fq_mul(Fq_sub(jl, utoi(1728), T, p), deltal, T, p), T, p);
+    jl  = Zq_div(Fq_powu(E4l, 3, T, p), deltal, T, p, pp, e);
+    E6l = Zq_sqrt(Fq_mul(Fq_sub(jl, utoi(1728), T, p), deltal, T, p), T, p, pp, e);
     p_1 = gen_0;
   }
   else
   {
     GEN jl, f, fd, Dgs, Djs, jld;
-    GEN E2s = Fq_div(Fq_mul(Fq_neg(Fq_mulu(E6, 12, T, p), T, p), dJ, T, p), Fq_mul(Fq_mulu(E4, is, T, p), dx, T, p), T, p);
+    GEN E2s = Zq_div(Fq_mul(Fq_neg(Fq_mulu(E6, 12, T, p), T, p), dJ, T, p), Fq_mul(Fq_mulu(E4, is, T, p), dx, T, p), T, p, pp, e);
     GEN gd = Fq_mul(Fq_mul(E2s, itis, T, p), g, T, p);
-    GEN jd = Fq_div(Fq_mul(Fq_neg(E42, T, p), E6, T, p), delta, T, p);
-    GEN E0b = Fq_div(E6, Fq_mul(E4, E2s, T, p), T, p);
+    GEN jd = Zq_div(Fq_mul(Fq_neg(E42, T, p), E6, T, p), delta, T, p, pp, e);
+    GEN E0b = Zq_div(E6, Fq_mul(E4, E2s, T, p), T, p, pp, e);
     GEN Dxxgj = FqXY_eval(Dxx, g, j, T, p);
     GEN Dgd = Fq_add(Fq_mul(gd, px, T, p), Fq_mul(g, Fq_add(Fq_mul(gd, Dxxgj, T, p), Fq_mul(jd, ExJ, T, p), T, p), T, p), T, p);
     GEN DJgJj = FqX_eval(FqX_deriv(DJg, T, p), j, T, p);
     GEN Djd = Fq_add(Fq_mul(jd, pJ, T, p), Fq_mul(j, Fq_add(Fq_mul(jd, DJgJj, T, p), Fq_mul(gd, ExJ, T, p), T, p), T, p), T, p);
-    GEN E0bd = Fq_div(Fq_sub(Fq_mul(Dgd, itis, T, p), Fq_mul(E0b, Djd, T, p), T, p), dJ, T, p);
-    E4l = Fq_div(Fq_sub(E4, Fq_mul(E2s, Fq_sub(Fq_sub(Fq_add(Fq_div(Fq_mulu(E0bd, 12, T, p), E0b, T, p), Fq_div(Fq_mulu(E42, 6, T, p), E6, T, p), T, p), Fq_div(Fq_mulu(E6, 4, T, p), E4, T, p), T, p), E2s, T, p), T, p), T, p), sqru(ell), T, p);
-    jl = Fq_div(Fq_powu(E4l, 3, T, p), deltal, T, p);
-    f =  Fq_div(powuu(ell, is), g, T, p);
+    GEN E0bd = Zq_div(Fq_sub(Fq_mul(Dgd, itis, T, p), Fq_mul(E0b, Djd, T, p), T, p), dJ, T, p, pp, e);
+    E4l = Zq_div(Fq_sub(E4, Fq_mul(E2s, Fq_sub(Fq_sub(Fq_add(Zq_div(Fq_mulu(E0bd, 12, T, p), E0b, T, p, pp, e), Zq_div(Fq_mulu(E42, 6, T, p), E6, T, p, pp, e), T, p), Zq_div(Fq_mulu(E6, 4, T, p), E4, T, p, pp, e), T, p), E2s, T, p), T, p), T, p), sqru(ell), T, p, pp, e);
+    jl = Zq_div(Fq_powu(E4l, 3, T, p), deltal, T, p, pp, e);
+    if (signe(jl)==0)
+    {
+      if (DEBUGLEVEL>0) err_printf("[C: jl=0]");
+      avma = ltop; return NULL;
+    }
+    f =  Zq_div(powuu(ell, is), g, T, p, pp, e);
     fd = Fq_neg(Fq_mul(Fq_mul(E2s, f, T, p), itis, T, p), T, p);
     Dgs = FqXY_eval(Dx, f, jl, T, p);
     Djs = FqXY_eval(DJ, f, jl, T, p);
-    jld = Fq_div(Fq_mul(Fq_neg(fd, T, p), Dgs, T, p), Fq_mulu(Djs, ell, T, p), T, p);
-    E6l = Fq_div(Fq_mul(Fq_neg(E4l, T, p), jld, T, p), jl, T, p);
-    p_1 = Fq_mul(Fq_mulu(E2s, ell, T, p), shifti(p, -1), T, p);
+    jld = Zq_div(Fq_mul(Fq_neg(fd, T, p), Dgs, T, p), Fq_mulu(Djs, ell, T, p), T, p, pp, e);
+    E6l = Zq_div(Fq_mul(Fq_neg(E4l, T, p), jld, T, p), jl, T, p, pp, e);
+    p_1 = Fq_neg(Fq_halve(Fq_mulu(E2s, ell, T, p), T, p),T,p);
   }
   a4tilde = Fq_mul(Fq_mul(stoi(-3), powuu(ell,4), T, p), E4l, T, p);
   a6tilde = Fq_mul(Fq_mul(stoi(-2), powuu(ell,6), T, p), E6l, T, p);
-  h = find_kernel(a4, a6, ell, a4tilde, a6tilde, p_1, T, p);
+  h = find_kernel(a4, a6, ell, a4tilde, a6tilde, p_1, T, p, pp, e);
+  if (!h) return NULL;
   return gerepilecopy(ltop, mkvec3(a4tilde, a6tilde, h));
 }
 
 static GEN
-find_isogenous(GEN a4, GEN a6, long ell, struct meqn *MEQN, GEN g, GEN T, GEN p)
+find_isogenous(GEN a4,GEN a6, ulong ell, struct meqn *MEQN, GEN g, GEN T,GEN p)
 {
+  ulong pp = itou_or_0(p);
+  long e = (pp && pp <= 2*ell+3) ? 2+factorial_lval(ell, pp): 1;
+  if (e > 1)
+  {
+    GEN pe = powiu(p, e);
+    GEN meqnj = FqXY_evalx(MEQN->eq, Zq_ellj(a4, a6, T, pe, p, e), T, pe);
+    g = ZpXQX_liftroot(meqnj, g, T, p, e);
+  }
   return (MEQN->type == 'C')
-    ? find_isogenous_from_canonical(a4, a6, ell, MEQN->eq, g, T, p)
-    : find_isogenous_from_Atkin(a4, a6, ell, MEQN->eq, g, T, p);
+    ? find_isogenous_from_canonical(a4, a6, ell, MEQN, g, T, p, e)
+    : find_isogenous_from_Atkin(a4, a6, ell, MEQN, g, T, p, e);
+}
+
+static GEN
+FqX_homogenous_eval(GEN P, GEN A, GEN B, GEN T, GEN p)
+{
+  long d = degpol(P), i, v = varn(A);
+  GEN s =  scalar_ZX_shallow(gel(P, d+2), v), Bn = pol_1(v);
+  for (i = d-1; i >= 0; i--)
+  {
+    Bn = FqX_mul(Bn, B, T, p);
+    s = FqX_add(FqX_mul(s, A, T, p), FqX_Fq_mul(Bn, gel(P,i+2), T, p), T, p);
+  }
+  return s;
+}
+
+static GEN
+FqX_homogenous_div(GEN P, GEN Q, GEN A, GEN B, GEN T, GEN p)
+{
+  GEN z = cgetg(3, t_RFRAC);
+  long d = degpol(Q)-degpol(P);
+  gel(z, 1) = FqX_homogenous_eval(P, A, B, T, p);
+  gel(z, 2) = FqX_homogenous_eval(Q, A, B, T, p);
+  if (d > 0)
+    gel(z, 1) = FqX_mul(gel(z, 1), FqX_powu(B, d, T, p), T, p);
+  else if (d < 0)
+    gel(z, 2) = FqX_mul(gel(z, 2), FqX_powu(B, -d, T, p), T, p);
+  return z;
 }
 
 static GEN
@@ -698,27 +824,27 @@ find_kernel_power(GEN Eba4, GEN Eba6, GEN Eca4, GEN Eca6, ulong ell, struct meqn
 {
   pari_sp ltop = avma, btop;
   GEN a4t, a6t, gtmp;
-  GEN num_iso = find_numerator_isogeny(Eba4, Eba6, Eca4, Eca6, kpoly, T, p, ell+1);
+  GEN num_iso = FqX_numer_isog_abscissa(kpoly, Eba4, Eba6, T, p, 0);
   GEN mpoly = FqXY_evalx(MEQN->eq, Fq_ellj(Eca4, Eca6, T, p), T, p);
-  GEN tmp, mroots = FqX_roots(mpoly, T, p);
-  long i, vx = 0, l1 = lg(mroots);
+  GEN mroots = FqX_roots(mpoly, T, p);
+  GEN kpoly2 = FqX_sqr(kpoly, T, p);
+  long i, l1 = lg(mroots);
   btop = avma;
   for (i = 1; i < l1; i++)
   {
-    GEN kpoly2, h;
-    tmp = find_isogenous(Eca4, Eca6, ell, MEQN, gel(mroots, i), T, p);
+    GEN h;
+    GEN tmp = find_isogenous(Eca4, Eca6, ell, MEQN, gel(mroots, i), T, p);
     if (!tmp) { avma = ltop; return NULL; }
     a4t =  gel(tmp, 1);
     a6t =  gel(tmp, 2);
     gtmp = gel(tmp, 3);
 
     /*check that the kernel kpoly is the good one */
-    kpoly2 = FqX_sqr(kpoly, T, p);
-    h = liftall_shallow(numer(gsubst(gtmp, vx, gdiv(num_iso, kpoly2))));
+    h = FqX_homogenous_eval(gtmp, num_iso, kpoly2, T, p);
     if (signe(Fq_elldivpolmod(Eba4, Eba6, ell, h, T, p)))
     {
-      GEN Ic = gdiv(gsubst(num_iso, vx, Ib), gsqr(gsubst(kpoly, vx, Ib)));
-      GEN kpoly_new = liftall_shallow(numer(gsubst(gtmp, vx, Ic)));
+      GEN Ic = FqX_homogenous_div(num_iso, kpoly2, numer(Ib), denom(Ib), T, p);
+      GEN kpoly_new = FqX_homogenous_eval(gtmp, numer(Ic), denom(Ic), T, p);
       return gerepilecopy(ltop, mkvecn(5, a4t, a6t, kpoly_new, gtmp, Ic));
     }
     avma = btop;
@@ -752,7 +878,7 @@ Flxq_study_eqn(long ell, GEN mpoly, GEN T, ulong p, long *pt_dG, long *pt_r)
 static GEN
 Fp_study_eqn(long ell, GEN mpoly, GEN p, long *pt_dG, long *pt_r)
 {
-  GEN XP = FpXQ_pow(pol_x(0), p, mpoly, p);
+  GEN XP = FpX_Frobenius(mpoly, p);
   GEN G  = FpX_gcd(FpX_sub(XP, pol_x(0), p), mpoly, p);
   *pt_dG = degpol(G);
   if (!*pt_dG)
@@ -831,7 +957,7 @@ study_modular_eqn(long ell, GEN mpoly, GEN T, GEN p, enum mod_type *mt, long *pt
 static GEN
 find_trace_Elkies_power(GEN a4, GEN a6, ulong ell, long k, struct meqn *MEQN, GEN g, GEN tr, GEN q, GEN T, GEN p, ulong smallfact, pari_timer *ti)
 {
-  pari_sp ltop = avma, btop, st_lim;
+  pari_sp ltop = avma, btop;
   GEN tmp, Eba4, Eba6, Eca4, Eca6, Ib, kpoly;
   ulong lambda, ellk = upowuu(ell, k), pellk = umodiu(q, ellk);
   long cnt;
@@ -853,7 +979,7 @@ find_trace_Elkies_power(GEN a4, GEN a6, ulong ell, long k, struct meqn *MEQN, GE
     ulong ap = Fl_add(lambda, Fl_div(pell, lambda, ell), ell);
     if (Fl_sub(pell, ap, ell)==ell-1) { avma = ltop; return mkvecsmall(ap); }
   }
-  btop = avma; st_lim = stack_lim(btop, 1);
+  btop = avma;
   for (cnt = 2; cnt <= k; cnt++)
   {
     GEN tmp;
@@ -867,8 +993,11 @@ find_trace_Elkies_power(GEN a4, GEN a6, ulong ell, long k, struct meqn *MEQN, GE
     Eca6 = gel(tmp,2);
     kpoly = gel(tmp,4);
     Ib = gel(tmp, 5);
-    if (low_stack(st_lim, stack_lim(btop, 1)))
+    if (gc_needed(btop, 1))
+    {
+      if(DEBUGMEM>1) pari_warn(warnmem,"find_trace_Elkies_power");
       gerepileall(btop, 6, &Eba4, &Eba6, &Eca4, &Eca6, &kpoly, &Ib);
+    }
     if (DEBUGLEVEL>1) err_printf(" [%ld ms]", timer_delay(ti));
   }
   avma = ltop;
@@ -928,7 +1057,8 @@ find_trace_lp1_roots(long ell, GEN q)
 
 /*trace modulo ell^k: [], [t] or [t1,...,td] */
 static GEN
-find_trace(GEN a4, GEN a6, ulong ell, GEN q, GEN T, GEN p, long *ptr_kt, ulong smallfact)
+find_trace(GEN a4, GEN a6, GEN j, ulong ell, GEN q, GEN T, GEN p, long *ptr_kt,
+  ulong smallfact, long vx, long vy)
 {
   pari_sp ltop = avma;
   GEN g, meqnj, tr, tr2;
@@ -949,10 +1079,10 @@ find_trace(GEN a4, GEN a6, ulong ell, GEN q, GEN T, GEN p, long *ptr_kt, ulong s
     }
   }
   kt = k;
-  if (!get_modular_eqn(&MEQN, ell, 0, MAXVARN)) err_modular_eqn(ell);
+  if (!get_modular_eqn(&MEQN, ell, vx, vy)) err_modular_eqn(ell);
   if (DEBUGLEVEL)
   { err_printf("Process prime %5ld. ", ell); timer_start(&ti); }
-  meqnj = FqXY_evalx(MEQN.eq, Fq_ellj(a4, a6, T, p), T, p);
+  meqnj = FqXY_evalx(MEQN.eq, j, T, p);
   g = study_modular_eqn(ell, meqnj, T, p, &mt, &r);
   /* If l is an Elkies prime, search for a factor of the l-division polynomial.
   * Then deduce the trace by looking for eigenvalues of the Frobenius by
@@ -969,8 +1099,14 @@ find_trace(GEN a4, GEN a6, ulong ell, GEN q, GEN T, GEN p, long *ptr_kt, ulong s
     break;
   case MTElkies:
     /* Contrary to MTone_root, may look mod higher powers of ell */
+    if (cmpiu(p, 2*ell+3) <= 0)
+      kt = k = 1; /* Not implemented in this case */
     tr = find_trace_Elkies_power(a4,a6,ell, k, &MEQN, g, NULL, q, T, p, smallfact, &ti);
-    if (!tr) { avma = ltop; return NULL; }
+    if (!tr)
+    {
+      if (DEBUGLEVEL) err_printf("[fail]\n");
+      avma = ltop; return NULL;
+    }
     break;
   case MTroots:
     tr = find_trace_lp1_roots(ell, q);
@@ -1005,7 +1141,7 @@ find_trace(GEN a4, GEN a6, ulong ell, GEN q, GEN T, GEN p, long *ptr_kt, ulong s
 static long
 separation(GEN cnt)
 {
-  pari_sp btop, st_lim;
+  pari_sp btop;
   long k = lg(cnt)-1, l = (1L<<k)-1, best_i, i, j;
   GEN best_r, P, P3, r;
 
@@ -1013,7 +1149,7 @@ separation(GEN cnt)
   for (j = 1; j <= k; ++j) P = mulis(P, cnt[j]);
   /* p_b * p_g = P is constant */
   P3 = mulsi(3, P);
-  btop = avma; st_lim = stack_lim(btop, 1);
+  btop = avma;
   best_i = 0;
   best_r = P3;
   for (i = 1; i < l; i++)
@@ -1025,7 +1161,7 @@ separation(GEN cnt)
     r = subii(shifti(sqri(p_b), 2), P3); /* (p_b/p_g - 3/4)*4*P */
     if (!signe(r)) { best_i = i; break; }
     if (absi_cmp(r, best_r) < 0) { best_i = i; best_r = r; }
-    if (low_stack(st_lim, stack_lim(btop, 1)))
+    if (gc_needed(btop, 1))
       best_r = gerepileuptoint(btop, best_r);
   }
   return best_i;
@@ -1251,24 +1387,30 @@ BSGS_pre(GEN *pdiff, GEN V, GEN P, void *E, const struct bb_group *grp)
 static GEN
 match_and_sort(GEN compile_atkin, GEN Mu, GEN u, GEN q, void *E, const struct bb_group *grp)
 {
-  pari_sp av1, av2, lim;
+  pari_sp av1, av2;
   GEN baby, giant, SgMb, Mb, Mg, den, Sg, dec_inf, div, pp1 = addis(q,1);
   GEN P, Pb, Pg, point, diff, pre, table, table_ind;
   long best_i, i, lbaby, lgiant, k = lg(compile_atkin)-1;
+  GEN bound = sqrti(shifti(q, 2)), card;
+  const long lcard = 100;
+  long lq = lgefint(q), nbcard;
   pari_timer ti;
 
   if (k == 1)
   { /*only one Atkin prime, check the cardinality with random points */
     GEN r = gel(compile_atkin, 1), r1 = gel(r,1), r2 = gel(r,2);
-    long l = lg(r2);
+    long l = lg(r2), j;
     GEN card = cgetg(l, t_VEC), Cs2, C, U;
     Z_chinese_pre(Mu, r1, &C,&U, NULL);
     Cs2 = shifti(C, -1);
-    for (i = 1; i < l; i++)
+    for (j = 1, i = 1; i < l; i++)
     {
       GEN t = Z_chinese_post(u, stoi(r2[i]), C, U, NULL);
-      gel(card, i) = subii(pp1, Fp_center(t, C, Cs2));
+      t = Fp_center(t, C, Cs2);
+      if (absi_cmp(t, bound) <= 0)
+        gel(card, j++) = subii(pp1, t);
     }
+    setlg(card, j);
     return gen_select_order(card, E, grp);
   }
   if (DEBUGLEVEL>=2) timer_start(&ti);
@@ -1300,6 +1442,13 @@ match_and_sort(GEN compile_atkin, GEN Mu, GEN u, GEN q, void *E, const struct bb
   gen_sort_inplace(baby, (void*)&cmpii, &cmp_nodata, NULL);
 
   SgMb = mulii(Sg, Mb);
+  card = cgetg(lcard+1,t_VEC);
+  for (i = 1; i <= lcard; i++) gel(card,i) = cgetipos(lq+1);
+
+  av2 = avma;
+MATCH_RESTART:
+  avma = av2;
+  nbcard = 0;
   P = grp->rand(E);
   point = grp->pow(E,P, Mu);
   Pb = grp->pow(E,point, Mg);
@@ -1310,7 +1459,7 @@ match_and_sort(GEN compile_atkin, GEN Mu, GEN u, GEN q, void *E, const struct bb
   /*Now we compute the table of babies, this table contains only the */
   /*lifted x-coordinate of the points in order to use less memory */
   table = cgetg(lbaby, t_VECSMALL);
-  av1 = avma; lim = stack_lim(av1,3);
+  av1 = avma;
   /* (p+1 - u - Mu*Mb*Sg) P - (baby[1]) Pb */
   point = grp->pow(E,P, subii(subii(pp1, u), mulii(Mu, addii(SgMb, mulii(Mg, gel(baby,1))))));
   table[1] = grp->hash(gel(point,1));
@@ -1319,7 +1468,7 @@ match_and_sort(GEN compile_atkin, GEN Mu, GEN u, GEN q, void *E, const struct bb
     GEN d = subii(gel(baby, i), gel(baby, i-1));
     point =  grp->mul(E, point, grp->pow(E, gel(pre, ZV_search(diff, d)), gen_m1));
     table[i] = grp->hash(gel(point,1));
-    if (low_stack(lim, stack_lim(av1,3)))
+    if (gc_needed(av1,3))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"match_and_sort, baby = %ld", i);
       point = gerepileupto(av1, point);
@@ -1333,7 +1482,7 @@ match_and_sort(GEN compile_atkin, GEN Mu, GEN u, GEN q, void *E, const struct bb
   table_ind = vecsmall_indexsort(table);
   table = perm_mul(table,table_ind);
 
-  av1 = avma; lim = stack_lim(av1,3);
+  av1 = avma;
   point = grp->pow(E, Pg, gel(giant, 1));
   for (i = 1; ; i++)
   {
@@ -1351,25 +1500,29 @@ match_and_sort(GEN compile_atkin, GEN Mu, GEN u, GEN q, void *E, const struct bb
         /* p+1 - u - Mu (Sg Mb + GIANT Mb + BABY Mg) */
         if (gequal(gel(Bp,1),gel(point,1)))
         {
-          GEN card = subii(Be, mulii(Mu, GMb));
-          card = mkvec2(card, addii(card, mulii(mulsi(2,Mu), GMb)));
+          GEN card1 = subii(Be, mulii(Mu, GMb));
+          GEN card2 = addii(card1, mulii(mulsi(2,Mu), GMb));
           if (DEBUGLEVEL>=2) timer_printf(&ti,"match_and_sort");
-          return gen_select_order(card, E, grp);
+          if (absi_cmp(subii(pp1, card1), bound) <= 0)
+            affii(card1, gel(card, ++nbcard));
+          if (nbcard >= lcard) goto MATCH_RESTART;
+          if (absi_cmp(subii(pp1, card2), bound) <= 0)
+            affii(card2, gel(card, ++nbcard));
+          if (nbcard >= lcard) goto MATCH_RESTART;
         }
       }
     }
     if (i==lgiant-1) break;
     d = subii(gel(giant, i+1), gel(giant, i));
     point = grp->mul(E,point, gel(pre, ZV_search(diff, d)));
-    if (low_stack(lim, stack_lim(av1,3)))
+    if (gc_needed(av1,3))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"match_and_sort, giant = %ld", i);
       point = gerepileupto(av1, point);
     }
   }
-  /* no match ? */
-  pari_err_BUG("match_and_sort");
-  return NULL; /* not reached */
+  setlg(card, nbcard+1);
+  return gen_select_order(card, E, grp);
 }
 
 static GEN
@@ -1392,8 +1545,9 @@ get_FqE_group(void ** pt_E, GEN a4, GEN a6, GEN T, GEN p)
   if (!T) return get_FpE_group(pt_E,a4,a6,p);
   else if (lgefint(p)==3)
   {
-    ulong pp=(ulong) p[2];
-    return get_FlxqE_group(pt_E, ZX_to_Flx(a4,pp),ZX_to_Flx(a6,pp),ZXT_to_FlxT(T,pp),pp);
+    ulong pp = uel(p,2);
+    return get_FlxqE_group(pt_E, Fq_to_Flx(a4, T, pp), Fq_to_Flx(a6, T, pp),
+                           ZXT_to_FlxT(T,pp),pp);
   }
   return get_FpXQE_group(pt_E,a4,a6,T,p);
 }
@@ -1408,23 +1562,21 @@ GEN
 Fq_ellcard_SEA(GEN a4, GEN a6, GEN q, GEN T, GEN p, long smallfact)
 {
   const long MAX_ATKIN = 21;
-  pari_sp ltop = avma, btop, st_lim;
-  long ell, i, nb_atkin;
+  pari_sp ltop = avma, btop;
+  long ell, i, nb_atkin, vx,vy;
   GEN TR, TR_mod, compile_atkin, bound, bound_bsgs, champ;
   GEN prod_atkin = gen_1, max_traces = gen_0;
+  GEN j;
   double bound_gr = 1.;
   const double growth_factor = 1.26;
   forprime_t TT;
   void *E;
 
   if (!modular_eqn && !get_seadata(0)) return NULL;
-  if (T && get_FpX_var(T)==0) /* 0 is used by the modular polynomial */
-  {
-    if (typ(T)==t_POL) { T  = shallowcopy(T); setvarn(T,1); }
-    else T = gsubst(T,0,pol_x(1));
-    a4 = shallowcopy(a4); setvarn(a4,1);
-    a6 = shallowcopy(a6); setvarn(a6,1);
-  }
+  j = Fq_ellj(a4, a6, T, p);
+  if (typ(j)==t_INT && (signe(j)==0 || equaliu(j, umodui(1728, p))))
+    return T ? FpXQ_ellcard(Fq_to_FpXQ(a4, T, p), Fq_to_FpXQ(a6, T, p), T, p)
+             : Fp_ellcard(a4, a6, p);
   /*First compute the trace modulo 2 */
   switch(FqX_nbroots(mkpoln(4, gen_1, gen_0, a4, a6), T, p))
   {
@@ -1444,6 +1596,8 @@ Fq_ellcard_SEA(GEN a4, GEN a6, GEN q, GEN T, GEN p, long smallfact)
     if (DEBUGLEVEL) err_printf("Aborting: #E(Fq) divisible by 2\n");
     avma = ltop; return gen_0;
   }
+  vy = fetch_var();
+  vx = fetch_var_higher();
 
   /* compile_atkin is a vector containing informations about Atkin primes,
    * informations about Elkies primes lie in Mod(TR, TR_mod). */
@@ -1451,12 +1605,13 @@ Fq_ellcard_SEA(GEN a4, GEN a6, GEN q, GEN T, GEN p, long smallfact)
   bound = sqrti(shifti(q, 4));
   bound_bsgs = get_bound_bsgs(expi(q));
   compile_atkin = zerovec(MAX_ATKIN); nb_atkin = 0;
-  btop = avma; st_lim = stack_lim(btop, 1);
+  btop = avma;
   while ( (ell = u_forprime_next(&TT)) )
   {
     long ellkt, kt = 1, nbtrace;
     GEN trace_mod;
-    trace_mod = find_trace(a4, a6, ell, q, T, p, &kt, smallfact);
+    if (equalui(ell, p)) continue;
+    trace_mod = find_trace(a4, a6, j, ell, q, T, p, &kt, smallfact, vx,vy);
     if (!trace_mod) continue;
 
     nbtrace = lg(trace_mod) - 1;
@@ -1484,7 +1639,7 @@ Fq_ellcard_SEA(GEN a4, GEN a6, GEN q, GEN T, GEN p, long smallfact)
     if (cmpii(mulii(TR_mod, prod_atkin), bound) > 0)
     {
       GEN bound_tr;
-      if (!nb_atkin) return gerepileuptoint(ltop, subii(addis(p,1),TR));
+      if (!nb_atkin) return gerepileuptoint(ltop, subii(addis(q, 1), TR));
       bound_tr = mulrr(bound_bsgs, dbltor(bound_gr));
       bound_gr *= growth_factor;
       if (signe(max_traces))
@@ -1512,7 +1667,7 @@ Fq_ellcard_SEA(GEN a4, GEN a6, GEN q, GEN T, GEN p, long smallfact)
         }
       }
     }
-    if (low_stack(st_lim, stack_lim(btop, 1)))
+    if (gc_needed(btop, 1))
       gerepileall(btop,5, &TR,&TR_mod, &compile_atkin, &max_traces, &prod_atkin);
   }
   return NULL;/*not reached*/
diff --git a/src/modules/galois.c b/src/modules/galois.c
index f7a282e..9c46f0c 100644
--- a/src/modules/galois.c
+++ b/src/modules/galois.c
@@ -2192,9 +2192,10 @@ closure11(long EVEN, buildroot *BR)
     GEN h = BR->p, r = compositum(h, h);
     r = gel(r,lg(r)-1);
     if (degpol(r) == 22) return 2; /* D11 */
-    h = leafcopy(h); setvarn(h, MAXVARN);
+    h = leafcopy(h); setvarn(h, fetch_var());
     setvarn(r, 0); r = nffactor(h, r);
     /* S11 (P10*P10*P90) or F_110[11] (11 factors of degree 10) */
+    (void)delete_var();
     return (lgcols(r)-1 == 11)? 4: 8;
   }
 }
@@ -2403,7 +2404,7 @@ galoisbig(GEN pol, long prec)
     }
     BR.coef = z;
     BR.p = pol;
-    BR.pr = prec + nbits2extraprec((long)(cauchy_bound(pol) / LOG2));
+    BR.pr = prec + nbits2extraprec((long)fujiwara_bound(pol));
     BR.prmax = BR.pr + BIGDEFAULTPREC-2;
     BR.N = N;
     BR.r = vectrunc_init(N+1);
diff --git a/src/modules/genus2red.c b/src/modules/genus2red.c
index 9558773..47d37a2 100644
--- a/src/modules/genus2red.c
+++ b/src/modules/genus2red.c
@@ -177,8 +177,8 @@ myval_zi2(GEN b)
 {
   long v0, v1;
   b = lift(b);
-  v0 = myval_zi(truecoeff(b,0));
-  v1 = myval_zi(truecoeff(b,1));
+  v0 = myval_zi(RgX_coeff(b,0));
+  v1 = myval_zi(RgX_coeff(b,1));
   return minss(2*v0, 2*v1+1);
 }
 
@@ -333,18 +333,18 @@ theta_j(GEN B, GEN p, long j)
 static GEN
 theta_3_zi(GEN B)
 {
-  long v2 = myval_zi(truecoeff(B,2));
-  long v1 = myval_zi(truecoeff(B,1));
-  long v0 = myval_zi(truecoeff(B,0));
+  long v2 = myval_zi(RgX_coeff(B,2));
+  long v1 = myval_zi(RgX_coeff(B,1));
+  long v0 = myval_zi(RgX_coeff(B,0));
   return frac2s(min3(6*v2, 3*v1, 2*v0), 6);
 }
 /* compute theta_3 for B in (Z[i,Y]/(Y^2-3))[X], p = 3 */
 static GEN
 theta_3_zi2(GEN B)
 {
-  long v2 = myval_zi2(truecoeff(B,2));
-  long v1 = myval_zi2(truecoeff(B,1));
-  long v0 = myval_zi2(truecoeff(B,0));
+  long v2 = myval_zi2(RgX_coeff(B,2));
+  long v1 = myval_zi2(RgX_coeff(B,1));
+  long v0 = myval_zi2(RgX_coeff(B,0));
   return frac2s(min3(6*v2, 3*v1, 2*v0), 6);
 }
 
@@ -416,9 +416,9 @@ polymini(GEN pol, GEN p)
 
   if (lambda <= 2)
   {
-    if (myval(truecoeff(H,2),p) > 1-alpha &&
-        myval(truecoeff(H,1),p) > 2-alpha &&
-        myval(truecoeff(H,0),p) > 3-alpha)
+    if (myval(RgX_coeff(H,2),p) > 1-alpha &&
+        myval(RgX_coeff(H,1),p) > 2-alpha &&
+        myval(RgX_coeff(H,0),p) > 3-alpha)
     {
       pol = RgX_unscale(H, p);
       if (alpha) pol = RgX_Rg_mul(pol, p);
@@ -429,8 +429,8 @@ polymini(GEN pol, GEN p)
   {
     if (degpol(Hp) == 3)
     {
-      if (myval(truecoeff(H,6),p) >= 3 &&
-          myval(truecoeff(H,5),p) >= 2)
+      if (myval(RgX_coeff(H,6),p) >= 3 &&
+          myval(RgX_coeff(H,5),p) >= 2)
       {
         H = RgX_rescale(H, p); /* H(x/p)p^(deg H) */
         H = RgX_Rg_div(H, powiu(p, degpol(H)-3)); /* H(x/p)p^3 */
@@ -488,7 +488,7 @@ polymini_zi(GEN pol) /* polynome minimal dans Z[i] */
   alpha = polval(pol,p) & 1;
   polh = alpha? RgX_Rg_div(pol, p): pol;
   beta = 0;
-  rac = mkcomplex(Fp_div(truecoeff(polh,3), truecoeff(polh,6), p), gen_1);
+  rac = mkcomplex(Fp_div(RgX_coeff(polh,3), RgX_coeff(polh,6), p), gen_1);
   for(;;)
   {
     polh = RgX_translate(polh, rac);
@@ -519,19 +519,23 @@ polymini_zi(GEN pol) /* polynome minimal dans Z[i] */
 static GEN
 polymini_zi2(GEN pol)
 {
-  long alpha, beta, v = MAXVARN;
+  long alpha, beta;
   GEN a0, a1, a2, a3, a4, a5, a6;
-  GEN p, polh, rac, theta, y = pol_x(v);
+  GEN p, polh, rac, theta, y = pol_x(fetch_var());
 
   p = stoi(3);
   if (polval(pol,p)) pari_err_BUG("polymini_zi2 [polynomial not minimal]");
   y = mkpolmod(y, gsubgs(gsqr(y), 3)); /* mod(y,y^2-3) */
   polh = pol;
   polh = gdivgs(RgX_unscale(polh, y),27); /* H(y*x) / 27 */
-  if (myval_zi2(truecoeff(polh,4)) <= 0 ||
-      myval_zi2(truecoeff(polh,2)) <= 0) return mkcol2(gen_0, gen_0);
+  if (myval_zi2(RgX_coeff(polh,4)) <= 0 ||
+      myval_zi2(RgX_coeff(polh,2)) <= 0)
+  {
+    (void)delete_var();
+    return mkcol2(gen_0, gen_0);
+  }
 
-  if (myval_zi2(gsub(truecoeff(polh,6), truecoeff(polh,0))) > 0)
+  if (myval_zi2(gsub(RgX_coeff(polh,6), RgX_coeff(polh,0))) > 0)
     rac = gen_I();
   else
     rac = gen_1;
@@ -552,8 +556,8 @@ polymini_zi2(GEN pol)
     }
     RgX_to_6(polh, &a0,&a1,&a2,&a3,&a4,&a5,&a6);
     if (!gequal0(theta) || !myval_zi2(a4) || !myval_zi2(a5)) break;
-    a3 = liftpol_shallow(a3); if (typ(a3)==t_POL) a3 = constant_term(a3);
-    a6 = liftpol_shallow(a6); if (typ(a6)==t_POL) a6 = constant_term(a6);
+    a3 = liftpol_shallow(a3); if (typ(a3)==t_POL) a3 = RgX_coeff(a3,0);
+    a6 = liftpol_shallow(a6); if (typ(a6)==t_POL) a6 = RgX_coeff(a6,0);
     rac = zi_pow3mod(gdiv(a6,gneg(a3)));
   }
   if (alpha)
@@ -566,6 +570,7 @@ polymini_zi2(GEN pol)
     }
     else pari_err_BUG("polymini_zi2 [alpha]");
   }
+  (void)delete_var();
   return mkcol2(theta, stoi(beta));
 }
 
@@ -2083,13 +2088,13 @@ genus2localred(struct igusa *I, struct igusa_p *Ip, GEN p, GEN polmini)
           Ip->type = stack_sprintf("[II-II*{%ld}] page 176", dism);
           Ip->neron = groupH(dism+1); break;
         case 21:
-          vb6 = myval(truecoeff(polh,0),p);
+          vb6 = myval(RgX_coeff(polh,0),p);
           if (vb6<2) pari_err_BUG("genus2localred [red3]");
           condp = dismin-14;
           Ip->type = "[IV*-II{0}] page 175";
           Ip->neron = cyclic(1); break;
         case 30:
-          vb5 = myval(truecoeff(polh,1),p);
+          vb5 = myval(RgX_coeff(polh,1),p);
           if (vb5 == 2)
           {
             if (Ip->tt >= 5) pari_err_BUG("genus2localred [tt 6]");
@@ -2144,7 +2149,7 @@ genus2localred(struct igusa *I, struct igusa_p *Ip, GEN p, GEN polmini)
           Ip->neron = groupH(dism+1); break;
           break;
         case 2: case 3:
-          if (myval(truecoeff(polh,0),p) == 2)
+          if (myval(RgX_coeff(polh,0),p) == 2)
           {
             if (Ip->tt>4) pari_err_BUG("genus2localred [tt 5]");
             return tame(polh, theta, alpha, dismin, I, Ip);
@@ -2185,13 +2190,25 @@ chk_pol(GEN P) {
 
 /* P,Q are ZX, study Y^2 + Q(X) Y = P(X) */
 GEN
-genus2red(GEN Q, GEN P, GEN p)
+genus2red(GEN PQ, GEN p)
 {
   pari_sp av = avma;
   struct igusa I;
+  GEN P, Q;
   GEN j22, j42, j2j6, a0,a1,a2,a3,a4,a5,a6, V,polr,facto,factp, vecmini, cond;
   long i, l, dd, vP,vQ;
 
+  if (typ(PQ) == t_VEC && lg(PQ) == 3)
+  {
+    P = gel(PQ,1);
+    Q = gel(PQ,2);
+  }
+  else
+  {
+    P = PQ;
+    Q = gen_0;
+  }
+
   vP = chk_pol(P);
   vQ = chk_pol(Q);
   if (vP < 0)
diff --git a/src/modules/krasner.c b/src/modules/krasner.c
index 1190f73..e094054 100644
--- a/src/modules/krasner.c
+++ b/src/modules/krasner.c
@@ -212,17 +212,17 @@ get_topx(KRASNER_t *data, GEN eis)
 {
   GEN p1, p2, rpl;
   long j;
-  pari_sp av, lim;
+  pari_sp av;
   /* top poly. is the minimal polynomial of root(pol) + root(upl) */
   rpl = FqX_translate(FqX_red(eis, data->upl, data->pr),
                       data->mv, data->upl, data->pr);
   p1 = p2 = rpl;
-  av = avma; lim = stack_lim(av, 1);
+  av = avma;
   for (j = 1; j < data->f; j++)
   {
     p1 = FqX_FpXQ_eval(p1, data->frob, data->upl, data->pr);
     p2 = FqX_mul(p2, p1, data->upl, data->pr);
-    if (low_stack(lim, stack_lim(av, 1))) gerepileall(av, 2, &p1, &p2);
+    if (gc_needed(av, 1)) gerepileall(av, 2, &p1, &p2);
   }
   return simplify_shallow(p2); /* ZX */
 }
@@ -654,7 +654,13 @@ RandomPol(KRASNER_t *data, GEN Omega)
     for (j = 1; j <= end-st; j++)
       c = ZX_add(c, ZX_Z_mul(RandomFF(data), gel(data->pk, j)));
     c = ZX_Z_mul(c, gel(data->pk, st));
-    gel(pol, i+1) = FpX_red(c, data->pr);
+    c = FpX_red(c, data->pr);
+    switch(degpol(c))
+    {
+      case -1: c = gen_0; break;
+      case  0: c = gel(c,2); break;
+    }
+    gel(pol, i+1) = c;
   }
   gel(pol, i+1) = gen_1; /* monic */
   return pol;
@@ -761,18 +767,23 @@ WildlyRamifiedCase(KRASNER_t *data)
   return gerepileupto(av, rep);
 }
 
-/* return the minimal polynomial (mod pr) of a generator of (F_p^f)^x with variable v */
+/* return the minimal polynomial (mod pr) of an element nu of (F_q)^x
+ * where q = p^f that is l-maximal for all primes l dividing g = (e,q-1). */
 static GEN
 CycloPol(KRASNER_t *d)
 {
-  GEN T, z;
+  long v = d->v, e = d->e;
+  GEN T, z, fa, p = d->p;
+
   /* v - primroot(p) */
   if (d->f == 1)
-    return deg1pol_shallow(gen_1, Fp_neg(pgener_Fp(d->p), d->pr), d->v);
-  T = init_Fq(d->p, d->f, d->v);
-  z = gener_FpXQ(T, d->p, NULL);
+    return deg1pol_shallow(gen_1, Fp_neg(pgener_Fp(p), d->pr), v);
+
+  T = init_Fq(d->p, d->f, v);
+  fa = factoru( ugcd(e, umodiu(d->qm1, e)) );
+  z = gener_FpXQ_local(T, d->p, zv_to_ZV(gel(fa,1)));
   z = ZpXQ_sqrtnlift(scalarpol(gen_1,varn(T)), d->qm1, z, T, d->p, d->r);
-  return FpX_red(ZXQ_charpoly(z, T, d->v), d->pr);
+  return FpX_red(ZXQ_charpoly(z, T, v), d->pr);
 }
 
 /* return [ p^1, p^2, ..., p^c ] */
diff --git a/src/modules/kummer.c b/src/modules/kummer.c
index 2ad3380..f2196fe 100644
--- a/src/modules/kummer.c
+++ b/src/modules/kummer.c
@@ -26,7 +26,7 @@ typedef struct {
 } tau_s;
 
 typedef struct {
-  GEN polnf, invexpoteta1;
+  GEN polnf, invexpoteta1, powg;
   tau_s *tau;
   long m;
 } toK_s;
@@ -84,13 +84,7 @@ ok_sign(GEN X, GEN msign, GEN arch)
 
 /* REDUCTION MOD ell-TH POWERS */
 
-static GEN
-fix_be(GEN bnfz, GEN be, GEN u)
-{
-  GEN nf = bnf_get_nf(bnfz), fu = bnf_get_fu_nocheck(bnfz);
-  return nfmul(nf, be, nffactorback(nf, fu, u));
-}
-
+#if 0
 static GEN
 logarch2arch(GEN x, long r1, long prec)
 {
@@ -107,46 +101,7 @@ logarch2arch(GEN x, long r1, long prec)
   }
   return y;
 }
-
-/* multiply be by ell-th powers of units as to find small L2-norm for new be */
-static GEN
-reducebetanaive(GEN bnfz, GEN be, long ell, GEN elllogfu)
-{
-  GEN z, nmax, b, c, nf = bnf_get_nf(bnfz);
-  const long r1 = nf_get_r1(nf), n = maxss(ell>>1,3);
-  long i, k, ru;
-
-  b = gmul(nf_get_M(nf), be);
-  z = cgetg(n+1, t_VEC);
-  c = logarch2arch(elllogfu, r1, nf_get_prec(nf)); /* embeddings of fu^ell */
-  c = gprec_w(gnorm(c), DEFAULTPREC);
-  b = gprec_w(gnorm(b), DEFAULTPREC); /* need little precision */
-  gel(z,1) = shallowconcat(c, vecinv(c));
-  for (k=2; k<=n; k++) gel(z,k) = vecmul(gel(z,1), gel(z,k-1));
-  nmax = embednorm_T2(b, r1);
-  ru = lg(c)-1; c = zerovec(ru);
-  for(;;)
-  {
-    GEN B = NULL;
-    long besti = 0, bestk = 0;
-    for (k=1; k<=n; k++)
-    {
-      GEN zk = gel(z,k);
-      for (i=1; i<=ru; i++)
-      {
-        GEN v, t;
-        v = vecmul(b, gel(zk,i));    t = embednorm_T2(v,r1);
-        if (gcmp(t,nmax) < 0) { B=v; nmax=t; besti=i; bestk = k; continue; }
-        v = vecmul(b, gel(zk,i+ru)); t = embednorm_T2(v,r1);
-        if (gcmp(t,nmax) < 0) { B=v; nmax=t; besti=i; bestk =-k; }
-      }
-    }
-    if (!B) break;
-    b = B; gel(c,besti) = addis(gel(c,besti), bestk);
-  }
-  if (DEBUGLEVEL) err_printf("naive reduction mod U^l: unit exp. = %Ps\n",c);
-  return fix_be(bnfz, be, ZC_z_mul(c, ell));
-}
+#endif
 
 static GEN
 reduce_mod_Qell(GEN bnfz, GEN be, GEN gell)
@@ -186,53 +141,66 @@ idealsqrtn(GEN nf, GEN x, GEN gn, int strict)
   return q? q: gen_1;
 }
 
+/* Assume B an LLL-reduced basis, t a vector. Apply Babai's nearest plane
+ * algorithm to (B,t) */
+static GEN
+Babai(GEN B, GEN t)
+{
+  GEN C, N, G = gram_schmidt(B, &N), b = t;
+  long j, n = lg(B)-1;
+
+  C = cgetg(n+1,t_COL);
+  for (j = n; j > 0; j--)
+  {
+    GEN c = gdiv( RgV_dotproduct(b, gel(G,j)), gel(N,j) );
+    long e;
+    c = grndtoi(c,&e);
+    if (e >= 0) return NULL;
+    if (signe(c)) b = RgC_sub(b, RgC_Rg_mul(gel(G,j), c));
+    gel(C,j) = c;
+  }
+  return C;
+}
+
 static GEN
 reducebeta(GEN bnfz, GEN be, GEN ell)
 {
-  long j,ru, prec = nf_get_prec(bnfz);
-  GEN emb, z, u, elllogfu, nf = bnf_get_nf(bnfz);
+  long prec = nf_get_prec(bnfz);
+  GEN y, elllogfu, nf = bnf_get_nf(bnfz), fu = bnf_get_fu_nocheck(bnfz);
 
   if (DEBUGLEVEL>1) err_printf("reducing beta = %Ps\n",be);
   /* reduce mod Q^ell */
   be = reduce_mod_Qell(nf, be, ell);
   /* reduce l-th root */
-  z = idealsqrtn(nf, be, ell, 0);
-  if (typ(z) == t_MAT && !is_pm1(gcoeff(z,1,1)))
+  y = idealsqrtn(nf, be, ell, 0);
+  if (typ(y) == t_MAT && !is_pm1(gcoeff(y,1,1)))
   {
-    z = idealred_elt(nf, z);
-    be = nfdiv(nf, be, nfpow(nf, z, ell));
+    y = idealred_elt(nf, y);
+    be = nfdiv(nf, be, nfpow(nf, y, ell));
     /* make be integral */
     be = reduce_mod_Qell(nf, be, ell);
   }
   if (DEBUGLEVEL>1) err_printf("beta reduced via ell-th root = %Ps\n",be);
-
-  for (;;)
-  {
-    z = get_arch_real(nf, be, &emb, prec);
-    if (z) break;
-    prec = precdbl(prec);
-    if (DEBUGLEVEL) pari_warn(warnprec,"reducebeta",prec);
-    nf = nfnewprec_shallow(nf,prec);
-  }
   /* log. embeddings of fu^ell */
   elllogfu = RgM_Rg_mul(real_i(bnf_get_logfu(bnfz)), ell);
-  z = shallowconcat(elllogfu, z);
-  u = lll(z);
-  if (lg(u) == lg(z))
+  for (;;)
   {
-    ru = lg(u);
-    for (j=1; j < ru; j++)
-      if (gequal1(gcoeff(u,ru-1,j))) break;
-    if (j < ru)
+    GEN emb, z = get_arch_real(nf, be, &emb, prec);
+    if (z)
     {
-      u = gel(u,j); /* coords on (fu^ell, be) of a small generator */
-      ru--; setlg(u, ru);
-      be = fix_be(bnfz, be, ZC_Z_mul(u, ell));
+      GEN ex = Babai(elllogfu, z);
+      if (ex)
+      {
+        be = nfdiv(nf, be, nffactorback(nf, fu, RgC_Rg_mul(ex,ell)));
+        break;
+      }
     }
+    prec = precdbl(prec);
+    if (DEBUGLEVEL) pari_warn(warnprec,"reducebeta",prec);
+    nf = nfnewprec_shallow(nf,prec);
   }
   if (DEBUGLEVEL>1) err_printf("beta LLL-reduced mod U^l = %Ps\n",be);
-  if (typ(be) == t_INT) return be;
-  return reducebetanaive(bnfz, be, itos(ell), elllogfu);
+  return be;
 }
 
 static GEN
@@ -276,9 +244,8 @@ tauofelt(GEN x, tau_s *tau)
 static GEN
 tauofvec(GEN x, tau_s *tau)
 {
-  long i, l = lg(x);
-  GEN y = cgetg(l, typ(x));
-
+  long i, l;
+  GEN y = cgetg_copy(x, &l);
   for (i=1; i<l; i++) gel(y,i) = tauofelt(gel(x,i), tau);
   return y;
 }
@@ -292,6 +259,28 @@ powtau(GEN x, long m, tau_s *tau)
   for (i=2; i<=m; i++) gel(y,i) = tauofelt(gel(y,i-1), tau);
   return y;
 }
+/* x^lambda */
+static GEN
+lambdaofelt(GEN x, toK_s *T)
+{
+  tau_s *tau = T->tau;
+  long i, m = T->m;
+  GEN y = cgetg(1, t_MAT), powg = T->powg; /* powg[i] = g^i */
+  for (i=1; i<m; i++)
+  {
+    y = famat_mul(y, famat_pow(x, gel(powg,m-i)));
+    x = tauofelt(x, tau);
+  }
+  return famat_mul(y, x);
+}
+static GEN
+lambdaofvec(GEN x, toK_s *T)
+{
+  long i, l;
+  GEN y = cgetg_copy(x, &l);
+  for (i=1; i<l; i++) gel(y,i) = lambdaofelt(gel(x,i), T);
+  return y;
+}
 
 static GEN
 tauoffamat(GEN x, tau_s *tau)
@@ -339,7 +328,7 @@ static GEN
 downtoK(toK_s *T, GEN x)
 {
   long degKz = lg(T->invexpoteta1) - 1;
-  GEN y = gmul(T->invexpoteta1, Rg_to_RgV(lift_intern(x), degKz));
+  GEN y = gmul(T->invexpoteta1, Rg_to_RgC(lift_intern(x), degKz));
   return gmodulo(gtopolyrev(y,varn(T->polnf)), T->polnf);
 }
 
@@ -644,6 +633,110 @@ Flv_fill(GEN v, GEN y)
   for (i = 1; i < l; i++) v[i] = y[i];
 }
 
+static GEN
+get_badbnf(GEN bnf)
+{
+  long i, l;
+  GEN bad = gen_1, gen = bnf_get_gen(bnf);
+  l = lg(gen);
+  for (i = 1; i < l; i++)
+  {
+    GEN g = gel(gen,i);
+    bad = lcmii(bad, gcoeff(g,1,1));
+  }
+  return bad;
+}
+/* Let K base field, L/K described by bnr (conductor f) + H. Return a list of
+ * primes coprime to f*ell of degree 1 in K whose images in Cl_f(K) generate H:
+ * thus they all split in Lz/Kz; t in Kz is such that
+ * t^(1/p) generates Lz => t is an ell-th power in k(pr) for all such primes.
+ * Restrict to primes not dividing
+ * - the index fz of the polynomial defining Kz, or
+ * - the modulus, or
+ * - ell, or
+ * - a generator in bnf.gen or bnfz.gen */
+static GEN
+get_prlist(GEN bnr, GEN H, ulong ell, GEN bnfz)
+{
+  pari_sp av0 = avma;
+  forprime_t T;
+  ulong p;
+  GEN L, nf, cyc, bad, cond, condZ, Hsofar;
+  L = cgetg(1, t_VEC);
+  cyc = bnr_get_cyc(bnr);
+  nf = bnr_get_nf(bnr);
+
+  cond = gel(bnr_get_mod(bnr), 1);
+  condZ = gcoeff(cond,1,1);
+  bad = get_badbnf(bnr_get_bnf(bnr));
+  if (bnfz)
+  {
+    GEN badz = lcmii(get_badbnf(bnfz), nf_get_index(bnf_get_nf(bnfz)));
+    bad = mulii(bad,badz);
+  }
+  bad = lcmii(muliu(condZ, ell), bad);
+  /* restrict to primes not dividing bad */
+
+  u_forprime_init(&T, 2, ULONG_MAX);
+  Hsofar = cgetg(1, t_MAT);
+  while ((p = u_forprime_next(&T)))
+  {
+    GEN LP;
+    long i, l;
+    if (p == ell || !umodiu(bad, p)) continue;
+    LP = idealprimedec_limit_f(nf, utoipos(p), 1);
+    l = lg(LP);
+    for (i = 1; i < l; i++)
+    {
+      pari_sp av = avma;
+      GEN M, P = gel(LP,i), v = bnrisprincipal(bnr, P, 0);
+      if (!hnf_invimage(H, v)) { avma = av; continue; }
+      M = shallowconcat(Hsofar, v);
+      M = ZM_hnfmodid(M, cyc);
+      if (ZM_equal(M, Hsofar)) continue;
+      L = shallowconcat(L, mkvec(P));
+      Hsofar = M;
+      /* the primes in L generate H */
+      if (ZM_equal(M, H)) return gerepilecopy(av0, L);
+    }
+  }
+  pari_err_BUG("rnfkummer [get_prlist]");
+  return NULL;
+}
+/*Lprz list of prime ideals in Kz that must split completely in Lz/Kz, vecWA
+ * generators for the S-units used to build the Kummer generators. Return
+ * matsmall M such that \prod WA[j]^x[j] ell-th power mod pr[i] iff
+ * \sum M[i,j] x[j] = 0 (mod ell) */
+static GEN
+subgroup_info(GEN bnfz, GEN Lprz, long ell, GEN vecWA)
+{
+  GEN nfz = bnf_get_nf(bnfz), M, gell = utoipos(ell), Lell = mkvec(gell);
+  long i, j, l = lg(vecWA), lz = lg(Lprz);
+  M = cgetg(l, t_MAT);
+  for (j=1; j<l; j++) gel(M,j) = cgetg(lz, t_VECSMALL);
+  for (i=1; i < lz; i++)
+  {
+    GEN pr = gel(Lprz,i), EX = subiu(pr_norm(pr), 1);
+    GEN N, g,T,p, prM = idealhnf(nfz, pr);
+    GEN modpr = zk_to_Fq_init(nfz, &pr,&T,&p);
+    long v = Z_lvalrem(divis(EX,ell), ell, &N) + 1; /* Norm(pr)-1 = N * ell^v */
+    GEN ellv = powuu(ell, v);
+    g = gener_Fq_local(T,p, Lell);
+    g = Fq_pow(g,N, T,p); /* order ell^v */
+    for (j=1; j < l; j++)
+    {
+      GEN logc, c = gel(vecWA,j);
+      if (typ(c) == t_MAT) /* famat */
+        c = famat_makecoprime(nfz, gel(c,1), gel(c,2), pr, prM, EX);
+      c = nf_to_Fq(nfz, c, modpr);
+      c = Fq_pow(c, N, T,p);
+      logc = Fq_log(c, g, ellv, T,p);
+      ucoeff(M, i,j) = umodiu(logc, ell);
+    }
+  }
+  return M;
+}
+
 /* if all!=0, give all equations of degree 'all'. Assume bnr modulus is the
  * conductor */
 static GEN
@@ -715,6 +808,12 @@ rnfkummersimple(GEN bnr, GEN subgroup, GEN gell, long all)
   }
   lW = lg(vecW);
   M = vconcat(M, shallowconcat(zero_Flm(rc,lW-1), ZM_to_Flm(matP, ell)));
+  if (!all)
+  { /* primes landing in subgroup must be totally split */
+    GEN Lpr = get_prlist(bnr, subgroup, ell, NULL);
+    GEN M2 = subgroup_info(bnf, Lpr, ell, vecWB);
+    M = vconcat(M, M2);
+  }
   K = Flm_ker(M, ell);
   dK = lg(K)-1;
 
@@ -952,12 +1051,12 @@ mod_Xell_a(GEN z, long v, long ell, GEN num_a, GEN den_a)
   return gadd(z0, z1);
 }
 static GEN
-to_alg(GEN nfz, GEN v)
+to_alg(GEN nfz, GEN c, long v)
 {
   GEN z;
-  if (typ(v) != t_COL) return v;
-  z = gmul(nf_get_zk(nfz), v);
-  if (typ(z) == t_POL) setvarn(z, MAXVARN);
+  if (typ(c) != t_COL) return c;
+  z = gmul(nf_get_zk(nfz), c);
+  if (typ(z) == t_POL) setvarn(z, v);
   return z;
 }
 
@@ -965,7 +1064,7 @@ to_alg(GEN nfz, GEN v)
 static GEN
 compute_polrel(GEN nfz, toK_s *T, GEN be, long g, long ell)
 {
-  long i, k, m = T->m, vT = fetch_var();
+  long i, k, m = T->m, vT = fetch_var(), vz = fetch_var();
   GEN r, powtaubet, S, p1, root, num_t, den_t, nfzpol, powtau_prim_invbe;
   GEN prim_Rk, C_Rk, prim_root, C_root, prim_invbe, C_invbe;
   pari_timer ti;
@@ -986,7 +1085,7 @@ compute_polrel(GEN nfz, toK_s *T, GEN be, long g, long ell)
      * 1/be = C_invbe * prim_invbe */
     GEN mmu = get_mmu(i, r, ell);
     /* p1 = prim_invbe ^ -mu */
-    p1 = to_alg(nfz, nffactorback(nfz, powtau_prim_invbe, mmu));
+    p1 = to_alg(nfz, nffactorback(nfz, powtau_prim_invbe, mmu), vz);
     if (C_invbe) p1 = gmul(p1, powgi(C_invbe, RgV_sumpart(mmu, m)));
     /* root += zeta_ell^{r_i} T^{r_i} be^mu_i */
     gel(root, 2 + r[i+1]) = monomial(p1, r[i+1], vT);
@@ -996,12 +1095,12 @@ compute_polrel(GEN nfz, toK_s *T, GEN be, long g, long ell)
   prim_Rk = prim_root = Q_primitive_part(root, &C_root);
   C_Rk = C_root;
 
-  /* Compute modulo X^ell - 1, T^ell - t, nfzpol(MAXVARN) */
-  p1 = to_alg(nfz, nffactorback(nfz, powtaubet, get_reverse(r)));
+  /* Compute modulo X^ell - 1, T^ell - t, nfzpol(vz) */
+  p1 = to_alg(nfz, nffactorback(nfz, powtaubet, get_reverse(r)), vz);
   num_t = Q_remove_denom(p1, &den_t);
 
   nfzpol = leafcopy(nf_get_pol(nfz));
-  setvarn(nfzpol, MAXVARN);
+  setvarn(nfzpol, vz);
   S = cgetg(ell+1, t_VEC); /* Newton sums */
   gel(S,1) = gen_0;
   for (k = 2; k <= ell; k++)
@@ -1030,11 +1129,21 @@ compute_polrel(GEN nfz, toK_s *T, GEN be, long g, long ell)
     gel(S,k) = z;
   }
   if (DEBUGLEVEL>1) err_printf("\n");
+  (void)delete_var();
   (void)delete_var(); return pol_from_Newton(S);
 }
 
+/* lift elt t in nf to nfz, algebraic form */
+static GEN
+lifttoKz(GEN nf, GEN t, compo_s *C)
+{
+  GEN x = nf_to_scalar_or_alg(nf, t);
+  if (typ(x) != t_POL) return x;
+  return RgX_RgXQ_eval(x, C->p, C->R);
+}
+/* lift ideal id in nf to nfz */
 static GEN
-lifttoKz(GEN nfz, GEN nf, GEN id, compo_s *C)
+ideallifttoKz(GEN nfz, GEN nf, GEN id, compo_s *C)
 {
   GEN I = idealtwoelt(nf,id);
   GEN x = nf_to_scalar_or_alg(nf, gel(I,2));
@@ -1042,6 +1151,30 @@ lifttoKz(GEN nfz, GEN nf, GEN id, compo_s *C)
   gel(I,2) = algtobasis(nfz, RgX_RgXQ_eval(x, C->p, C->R));
   return idealhnf_two(nfz,I);
 }
+/* lift ideal pr in nf to ONE prime in nfz (the others are conjugate under tau
+ * and bring no further information on e_1 W). Assume pr coprime to
+ * index of both nf and nfz, and unramified in Kz/K (minor simplification) */
+static GEN
+prlifttoKz(GEN nfz, GEN nf, GEN pr, compo_s *C)
+{
+  GEN F, p = pr_get_p(pr), t = pr_get_gen(pr), T = nf_get_pol(nfz);
+  if (nf_get_degree(nf) != 1)
+  { /* restrict to primes above pr */
+    t = Q_primpart( lifttoKz(nf,t,C) );
+    T = FpX_gcd(FpX_red(T,p), FpX_red(t,p), p);
+    T = FpX_normalize(T, p);
+  }
+  F = FpX_factor(T, p);
+  return primedec_apply_kummer(nfz,gcoeff(F,1,1), pr_get_e(pr), p);
+}
+static GEN
+get_przlist(GEN L, GEN nfz, GEN nf, compo_s *C)
+{
+  long i, l;
+  GEN M = cgetg_copy(L, &l);
+  for (i = 1; i < l; i++) gel(M,i) = prlifttoKz(nfz, nf, gel(L,i), C);
+  return M;
+}
 
 static void
 compositum_red(compo_s *C, GEN P, GEN Q)
@@ -1088,6 +1221,17 @@ nfX_Z_normalize(GEN nf, GEN P)
   }
 }
 
+/* v[i] = g^i mod ell, 1 <= i < m */
+static GEN
+Fl_powers_FpV(ulong g, long m, ulong ell)
+{
+  GEN v = cgetg(m, t_VEC);
+  ulong gi = g % ell;
+  long i;
+  for (i=1; i<m; i++) { gel(v,i) = utoi(gi); gi = (gi*g) % ell; }
+  return v;
+}
+
 static GEN
 _rnfkummer(GEN bnr, GEN subgroup, long all, long prec)
 {
@@ -1097,14 +1241,14 @@ _rnfkummer(GEN bnr, GEN subgroup, long all, long prec)
   GEN cyc,gen;
   GEN Q,idealz,gothf;
   GEN res=NULL,u,M,K,y,vecMsup,vecW,vecWA,vecWB,vecB,vecC,vecAp,vecBp;
-  GEN matP,Sp,listprSp,Tc,Tv,P;
+  GEN matP, Sp, listprSp, Tc, Tv, P;
   primlist L;
   toK_s T;
   tau_s _tau, *tau;
   compo_s COMPO;
   pari_timer t;
   long rk=0, ncyc=0;
-  GEN mat=NULL;
+  GEN mat = NULL;
   long firstpass = all<0;
 
   if (DEBUGLEVEL) timer_start(&t);
@@ -1168,8 +1312,8 @@ _rnfkummer(GEN bnr, GEN subgroup, long all, long prec)
   {
     p1 = tauofideal(gel(gen,j), tau);
     p1 = isprincipalell(bnfz, p1, cycgen,u,gell,rc);
-    Tc[j]  = p1[1];
-    vecB[j]= p1[2];
+    gel(Tc,j)  = gel(p1,1);
+    gel(vecB,j)= gel(p1,2);
   }
 
   vecC = cgetg(rc+1,t_VEC);
@@ -1212,9 +1356,10 @@ _rnfkummer(GEN bnr, GEN subgroup, long all, long prec)
   T.polnf = polnf;
   T.tau = tau;
   T.m = m;
+  T.powg = Fl_powers_FpV(g, m, ell);
 
-  idealz = lifttoKz(nfz, nf, ideal, &COMPO);
-  if (smodis(gcoeff(ideal,1,1), ell)) gothf = idealz;
+  idealz = ideallifttoKz(nfz, nf, ideal, &COMPO);
+  if (umodiu(gcoeff(ideal,1,1), ell)) gothf = idealz;
   else
   { /* ell | N(ideal) */
     GEN bnrz = Buchray(bnfz, idealz, nf_INIT|nf_GEN);
@@ -1235,22 +1380,16 @@ _rnfkummer(GEN bnr, GEN subgroup, long all, long prec)
   vecAp = cgetg(lSp+1, t_VEC);
   vecBp = cgetg(lSp+1, t_VEC);
   matP  = cgetg(lSp+1, t_MAT);
+
   for (j=1; j<=lSp; j++)
   {
-    GEN e, a, ap;
+    GEN e, a;
     p1 = isprincipalell(bnfz, gel(Sp,j), cycgen,u,gell,rc);
     e = gel(p1,1); gel(matP,j) = e;
     a = gel(p1,2);
-    p2 = famat_mul(famat_factorback(vecC, gneg(e)), a);
-    gel(vecBp,j) = p2;
-    ap = cgetg(1, t_MAT);
-    for (i=0; i<m; i++)
-    {
-      ap = famat_mul(ap, famat_pow(p2, utoi(Fl_powu(g,m-1-i,ell))));
-      if (i < m-1) p2 = tauofelt(p2, tau);
-    }
-    gel(vecAp,j) = ap;
+    gel(vecBp,j) = famat_mul(famat_factorback(vecC, gneg(e)), a);
   }
+  vecAp = lambdaofvec(vecBp, &T);
   /* step 13 */
   if (DEBUGLEVEL>2) err_printf("Step 13\n");
   vecWA = shallowconcat(vecW, vecAp);
@@ -1280,6 +1419,15 @@ _rnfkummer(GEN bnr, GEN subgroup, long all, long prec)
     M = vconcat(M, shallowconcat(zero_Flm(dc,lW-1), ZM_to_Flm(QtP,ell)));
   }
   if (!M) M = zero_Flm(1, lSp + lW - 1);
+
+  if (!all)
+  { /* primes landing in subgroup must be totally split */
+    GEN lambdaWB = shallowconcat(lambdaofvec(vecW, &T), vecAp);/*vecWB^lambda*/
+    GEN Lpr = get_prlist(bnr, subgroup, ell, bnfz);
+    GEN Lprz= get_przlist(Lpr, nfz, nf, &COMPO);
+    GEN M2 = subgroup_info(bnfz, Lprz, ell, lambdaWB);
+    M = vconcat(M, M2);
+  }
   /* step 16 */
   if (DEBUGLEVEL>2) err_printf("Step 16\n");
   K = Flm_ker(M, ell);
diff --git a/src/modules/mpqs.c b/src/modules/mpqs.c
index aa02241..1f42e58 100644
--- a/src/modules/mpqs.c
+++ b/src/modules/mpqs.c
@@ -2314,7 +2314,7 @@ stream_read_F2m(pariFILE *pFREL, long rows, long cols, long *fpos)
   char buf[MPQS_STRING_LENGTH], *s;
   GEN m;
   long space = 2*((nbits2nlong(rows)+3)*cols+1);
-  if ((long)((GEN)avma - (GEN)bot) < space)
+  if ((long)((GEN)avma - (GEN)pari_mainstack->bot) < space)
   {
     pari_sp av = avma;
     m = gclone(zero_F2m(rows, cols));
@@ -2424,7 +2424,7 @@ mpqs_solve_linear_system(mpqs_handle_t *h, pariFILE *pFREL, long rel)
 {
   GEN N = h->N, X, Y_prod, X_plus_Y, D1, res, new_res;
   mpqs_FB_entry_t *FB = h->FB;
-  pari_sp av=avma, av2, av3, lim, lim3;
+  pari_sp av=avma, av2, av3;
   long *fpos, *ei;
   long i, j, H_cols, H_rows;
   long res_last, res_next, res_size, res_max;
@@ -2471,7 +2471,7 @@ mpqs_solve_linear_system(mpqs_handle_t *h, pariFILE *pFREL, long rel)
    * about which factors we know to be composite (zero) or believe to be
    * composite (NULL) or suspect to be prime (one), or an exponent (two
    * or some t_INT) if it is a proper power */
-  av2 = avma; lim = stack_lim(av2,1);
+  av2 = avma;
   if (rank > (long)BITS_IN_LONG - 2)
     res_max = LONG_MAX; /* the common case, unfortunately */
   else
@@ -2488,13 +2488,13 @@ mpqs_solve_linear_system(mpqs_handle_t *h, pariFILE *pFREL, long rel)
     X = Y_prod = gen_1;
     memset((void *)ei, 0, (h->size_of_FB + 2) * sizeof(long));
 
-    av3 = avma; lim3 = stack_lim(av3,1);
+    av3 = avma;
     for (j = 1; j <= H_rows; j++)
     {
       if (F2m_coeff(ker_m, j, i))
         Y_prod = mpqs_add_relation(Y_prod, N, ei,
                                    mpqs_get_relation(buf, fpos[j-1], pFREL));
-      if (low_stack(lim3, stack_lim(av3,1)))
+      if (gc_needed(av3,1))
       {
         if(DEBUGMEM>1) pari_warn(warnmem,"[1]: mpqs_solve_linear_system");
         Y_prod = gerepileuptoint(av3, Y_prod);
@@ -2502,7 +2502,7 @@ mpqs_solve_linear_system(mpqs_handle_t *h, pariFILE *pFREL, long rel)
     }
     Y_prod = gerepileuptoint(av3, Y_prod);
 
-    av3 = avma; lim3 = stack_lim(av3,1);
+    av3 = avma;
     for (j = 2; j <= h->size_of_FB + 1; j++)
       if (ei[j])
       {
@@ -2510,7 +2510,7 @@ mpqs_solve_linear_system(mpqs_handle_t *h, pariFILE *pFREL, long rel)
         X = remii(mulii(X,
                         Fp_powu(utoipos(FB[j].fbe_p), (ulong)ei[j]>>1, N)),
                   N);
-        if (low_stack(lim3, stack_lim(av3,1)))
+        if (gc_needed(av3,1))
         {
           if(DEBUGMEM>1) pari_warn(warnmem,"[2]: mpqs_solve_linear_system");
           X = gerepileupto(av3, X);
@@ -2636,7 +2636,7 @@ mpqs_solve_linear_system(mpqs_handle_t *h, pariFILE *pFREL, long rel)
        * also when all current factors are probable primes */
       if (res_next > res_max || done == res_next - 1) break;
     } /* end case of further splitting of existing factors */
-    if (low_stack(lim, stack_lim(av2,1)))
+    if (gc_needed(av2,1))
     {
       long i1;
       if(DEBUGMEM>1) pari_warn(warnmem,"[3]: mpqs_solve_linear_system");
diff --git a/src/modules/part.c b/src/modules/part.c
index 1f5c91e..77380ab 100644
--- a/src/modules/part.c
+++ b/src/modules/part.c
@@ -12,18 +12,18 @@ with the package; see the file 'COPYING'. If not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 
 /* Original code contributed by: Ralf Stephan (ralf at ark.in-berlin.de).
+ * Updated by Bill Allombert (2014) to use Selberg formula for L
+ * following http://dx.doi.org/10.1112/S1461157012001088
  *
  * This program is basically the implementation of the script
  *
  * Psi(n, q) = my(a=sqrt(2/3)*Pi/q, b=n-1/24, c=sqrt(b));
  *             (sqrt(q)/(2*sqrt(2)*b*Pi))*(a*cosh(a*c)-(sinh(a*c)/c))
- * L(n,q)=if(q==1,1,sum(h=1,q-1,if(gcd(h,q)==1, cos((g(h,q)-24*h*n)*Pi/(12*q))))
- * g(h, q) = if(q>=3, 12*sum(k=1,q-1,k*(frac(h*k/q)-1/2)))
- *         \\ sumdedekind(h,q)*12*q
+ * L(n,q)=sqrt(k/3)*sum(l=0,2*k-1,
+          if(((3*l^2+l)/2+n)%k==0,(-1)^l*cos((6*l+1)/(6*k)*Pi)))
  * part(n) = round(sum(q=1,5 + 0.24*sqrt(n),L(n,q)*Psi(n,q)))
  *
- * only faster. It is a translation of the C/mpfr version at
- * http://www.ark.in-berlin.de/part.c
+ * only faster.
  *
  * ------------------------------------------------------------------
  *   The first restriction depends on Pari's maximum precision of floating
@@ -37,10 +37,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 
 /****************************************************************/
 
-/* Given:  b = N-1/24;
- *   c = sqrt(2/3)*Pi*sqrt(b)
- *   d = 1 / ((2*b)^(3/2) * Pi);
- *
+/* Given c = sqrt(2/3)*Pi*sqrt(N-1/24)
  * Psi(N, q) = my(a = c/q); sqrt(q) * (a*cosh(a) - sinh(a)) */
 static GEN
 psi(GEN c, ulong q, long prec)
@@ -51,45 +48,31 @@ psi(GEN c, ulong q, long prec)
   return mulrr(sqrtr(stor(q,prec)), subrr(mulrr(a,cha), sha));
 }
 
-/* g(h, q) = if(q>=3, 12*sum(k=1,q-1,k*(frac(h*k/q)-1/2)))
- *   \\ this is an integer = sumdedekind(h,q)*12*q
- * assume h < q and (h,q) = 1. Not memory clean. */
-static GEN
-g(ulong h, ulong q)
-{
-  long s1, s2;
-  GEN v;
-
-  if (q < 3)  return gen_0;
-  if (h == 1) return muluu(q-1,q-2);
-  if (h == 2) return q == 3? gen_m2: muluu(q-1,(q-5)>>1);
-  v = u_sumdedekind_coprime(h, q);
-  s1 = v[1];
-  s2 = v[2];
-  return addis(mulss(q,s1), s2);
-}
-
-/* L(n,q)=if(q==1,1,sum(h=1,q-1,if(gcd(h,q)==1, cos((g(h,q)-24*h*n)*Pi/(12*q))))
+/* L(n,q)=sqrt(k/3)*sum(l=0,2*k-1,
+          if(((3*l^2+l)/2+n)%k==0,(-1)^l*cos((6*l+1)/(6*k)*Pi)))
  * Never called with q < 3, so ignore this case */
 static GEN
-L(GEN n, ulong q, long bitprec)
+L(GEN n, ulong k, long bitprec)
 {
-  long pr = nbits2prec(bitprec / q + q);
-  ulong h, nmodq = umodiu(n, q), qov2 = q>>1, hn;
-  GEN r, res = stor(0, pr), q12 = muluu(q,12), q24 = shifti(q12,1);
-  GEN pi_q = divri(mppi(pr), q12);
+  ulong r, l, m;
+  long pr = nbits2prec(bitprec / k + k);
+  GEN s = stor(0,pr), pi = mppi(pr);
   pari_sp av = avma;
-  for (h = 1, hn = 0; h <= qov2; h++, avma = av) /* symmetry h <-> q-h */
+
+  r = 2; m = umodiu(n,k);
+  for (l = 0; l < 2*k; l++)
   {
-    GEN t;
-    hn += nmodq; if (hn >= q) hn -= q;
-    if (ugcd(q, h) > 1) continue;
-    r = subii(g(h,q), muluu(hn, 24));
-    r = centermodii(r, q24, q12);
-    t = isintzero(r)? addrs(res, 1): addrr(res, mpcos(mulri(pi_q,r)));
-    affrr(t, res);
+    if (m == 0)
+    {
+      GEN c = mpcos(divru(mulru(pi, 6*l+1), 6*k));
+      if (odd(l)) subrrz(s, c, s); else addrrz(s, c, s);
+      avma = av;
+    }
+    m += r; if (m >= k) m -= k;
+    r += 3; if (r >= k) r -= k;
   }
-  return shiftr(res,1);
+  /* multiply by sqrt(k/3) */
+  return mulrr(s, sqrtr((k % 3)? rdivss(k,3,pr): utor(k/3,pr)));
 }
 
 /* Return a low precision estimate of log p(n). */
@@ -106,6 +89,7 @@ estim(GEN n)
   return gerepileupto(av, mplog(p1));
 }
 
+/* c = sqrt(2/3)*Pi*sqrt(n-1/24);  d = 1 / ((2*b)^(3/2) * Pi); */
 static void
 pinit(GEN n, GEN *c, GEN *d, ulong prec)
 {
diff --git a/src/modules/stark.c b/src/modules/stark.c
index d14c8c7..323e655 100644
--- a/src/modules/stark.c
+++ b/src/modules/stark.c
@@ -19,8 +19,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 #include "pari.h"
 #include "paripriv.h"
 
-#define EXTRA_PREC (DEFAULTPREC-1)
-#define ADD_PREC   (DEFAULTPREC-2)*3
+static const long EXTRA_PREC = DEFAULTPREC-2;
+static const long EXTRA_BITS = 64;
 
 /* ComputeCoeff */
 typedef struct {
@@ -633,7 +633,7 @@ static GEN
 ArtinNumber(GEN bnr, GEN LCHI, long check, long prec)
 {
   long ic, i, j, nz, nChar = lg(LCHI)-1;
-  pari_sp av = avma, av2, lim;
+  pari_sp av = avma, av2;
   GEN sqrtnc, dc, cond, condZ, cond0, cond1, lambda, nf, T;
   GEN cyc, vN, vB, diff, vt, idg, idh, zid, gen, z, nchi;
   GEN indW, W, classe, s0, s, den, muslambda, sarch;
@@ -724,7 +724,7 @@ ArtinNumber(GEN bnr, GEN LCHI, long check, long prec)
   vN = cgetg(nChar+1, t_VEC);
   for (ic = 1; ic <= nChar; ic++) gel(vN,ic) = zero_zv(nz);
 
-  av2 = avma; lim = stack_lim(av2, 1);
+  av2 = avma;
   vB = const_vec(nz, gen_1);
   s0 = powgi(z, modii(gel(vt,1), den)); /* for beta = 1 */
   s = const_vec(nChar, s0);
@@ -749,7 +749,7 @@ ArtinNumber(GEN bnr, GEN LCHI, long check, long prec)
       gel(s,ic) = gadd(gel(s,ic), gmul(val, s0));
     }
 
-    if (low_stack(lim, stack_lim(av2, 1)))
+    if (gc_needed(av2, 1))
     {
       if (DEBUGMEM > 1) pari_warn(warnmem,"ArtinNumber");
       gerepileall(av2, 2, &s, &vB);
@@ -973,7 +973,7 @@ InitChar(GEN bnr, GEN listCR, long prec)
     {
       ch_C(dtcr) = gmul(C, gsqrt(ZM_det_triangular(gel(cond,1)), prec2));
       ch_4(dtcr) = _data4(gel(cond,2),r1,r2);
-      ch_cond(dtcr) = gel(cond,1);
+      ch_cond(dtcr) = cond;
       if (gequal(cond,modul))
       {
         ch_bnr(dtcr) = bnr;
@@ -1066,8 +1066,8 @@ CharNewPrec(GEN dataCR, GEN nf, long prec)
   l = lg(dataCR);
   for (j = 1; j < l; j++)
   {
-    GEN dtcr = gel(dataCR,j);
-    ch_C(dtcr) = gmul(C, gsqrt(ZM_det_triangular(ch_cond(dtcr)), prec2));
+    GEN dtcr = gel(dataCR,j), f0 = gel(ch_cond(dtcr),1);
+    ch_C(dtcr) = gmul(C, gsqrt(ZM_det_triangular(f0), prec2));
 
     gmael(ch_bnr(dtcr), 1, 7) = nf;
 
@@ -1296,7 +1296,7 @@ static long
 next_pow(long q, long p, long n)
 {
   const GEN x = muluu((ulong)q, (ulong)p);
-  const ulong qp = (ulong)x[2];
+  const ulong qp = uel(x,2);
   return (lgefint(x) > 3 || qp > (ulong)n)? 0: qp;
 }
 
@@ -1403,14 +1403,6 @@ deg0(LISTray *R, long p) { vecsmalltrunc_append(R->L0, p); }
 static void
 deg2(LISTray *R, long p) { vecsmalltrunc_append(R->L2, p); }
 
-/* pi(x) <= ?? */
-static long
-PiBound(ulong x)
-{
-  double lx = log((double)x);
-  return 1 + (long) (x/lx * (1 + 3/(2*lx)));
-}
-
 static void
 InitPrimesQuad(GEN bnr, ulong N0, LISTray *R)
 {
@@ -1420,7 +1412,7 @@ InitPrimesQuad(GEN bnr, ulong N0, LISTray *R)
   GEN prime, Lpr, nf = bnf_get_nf(bnf), dk = nf_get_disc(nf);
   forprime_t T;
 
-  l = 1 + PiBound(N0);
+  l = 1 + primepi_upper_bound(N0);
   R->L0 = vecsmalltrunc_init(l);
   R->L2 = vecsmalltrunc_init(l); R->condZ = condZ;
   R->L1 = vecsmalltrunc_init(l); R->L1ray = vectrunc_init(l);
@@ -1467,32 +1459,30 @@ InitPrimes(GEN bnr, ulong N0, LISTray *R)
 {
   GEN bnf = bnr_get_bnf(bnr), cond = gel(bnr_get_mod(bnr), 1);
   long p,j,k,l, condZ = itos(gcoeff(cond,1,1)), N = lg(cond)-1;
-  GEN tmpray, tabpr, prime, nf = bnf_get_nf(bnf);
+  GEN tmpray, tabpr, prime, BOUND, nf = bnf_get_nf(bnf);
   forprime_t T;
 
-  R->condZ = condZ; l = PiBound(N0) * N;
+  R->condZ = condZ; l = primepi_upper_bound(N0) * N;
   tmpray = cgetg(N+1, t_VEC);
   R->L1 = vecsmalltrunc_init(l);
   R->L1ray = vectrunc_init(l);
   u_forprime_init(&T, 2, N0);
   prime = utoipos(2);
+  BOUND = utoi(N0);
   while ( (p = u_forprime_next(&T)) )
   {
     pari_sp av = avma;
     prime[2] = p;
     if (DEBUGLEVEL>1 && (p & 2047) == 1) err_printf("%ld ", p);
-    tabpr = idealprimedec(nf, prime);
+    tabpr = idealprimedec_limit_norm(nf, prime, BOUND);
     for (j = 1; j < lg(tabpr); j++)
     {
       GEN pr  = gel(tabpr,j);
-      ulong np = upowuu(p, pr_get_f(pr));
-      if (!np || np > N0) break;
       if (condZ % p == 0 && idealval(nf, cond, pr))
       {
         gel(tmpray,j) = NULL; continue;
       }
-
-      vecsmalltrunc_append(R->L1, np);
+      vecsmalltrunc_append(R->L1, upowuu(p, pr_get_f(pr)));
       gel(tmpray,j) = gclone( isprincipalray(bnr, pr) );
     }
     avma = av;
@@ -2020,12 +2010,13 @@ computean(GEN dtcr, LISTray *R, long n, long deg)
 static GEN
 mpvecpowdiv(GEN A, long n)
 {
-  GEN v = powruvec(A, n);
   pari_sp av = avma;
   long i;
-
-  for (i=2; i<=n; i++) affrr(divru(gel(v,i), i), gel(v,i));
-  avma = av; return v;
+  GEN v = powersr(A, n);
+  GEN w = cgetg(n+1, t_VEC);
+  gel(w,1) = rcopy(gel(v,2));
+  for (i=2; i<=n; i++) gel(w,i) = divru(gel(v,i+1), i);
+  return gerepileupto(av, w);
 }
 
 static void GetST0(GEN bnr, GEN *pS, GEN *pT, GEN dataCR, GEN vChar, long prec);
@@ -2577,14 +2568,10 @@ LABDOUB:
   {
     long incr_pr;
     if (++cpt >= 3) pari_err_PREC( "stark (computation impossible)");
-
-    /* compute the precision, we need
-          a) get at least EXTRA_PREC fractional digits if there is none;
-       or b) double the fractional digits.
-    */
-    incr_pr = nbits2extraprec( prec2nbits(gprecision(polrelnum))- gexpo(polrelnum) );
-    if (incr_pr < 0) incr_pr = -incr_pr + EXTRA_PREC;
-    newprec = newprec + maxss(ADD_PREC, cpt*incr_pr);
+    /* estimate needed precision */
+    incr_pr = prec2nbits(gprecision(polrelnum))- gexpo(polrelnum);
+    if (incr_pr < 0) incr_pr = -incr_pr + EXTRA_BITS;
+    newprec += nbits2extraprec(maxss(3*EXTRA_BITS, cpt*incr_pr));
     if (DEBUGLEVEL) pari_warn(warnprec, "AllStark", newprec);
 
     nf = nfnewprec_shallow(nf, newprec);
@@ -2692,8 +2679,6 @@ bnrL1(GEN bnr, GEN subgp, long flag, long prec)
   checkbnr(bnr);
   if (flag < 0 || flag > 8) pari_err_FLAG("bnrL1");
 
-  /* compute bnr(conductor) */
-  if (!(flag & 2)) bnr = gel(bnrconductor(bnr, NULL, 2),2);
   cyc  = bnr_get_cyc(bnr);
   subgp = get_subgroup(subgp, cyc, "bnrL1");
 
@@ -2705,18 +2690,18 @@ bnrL1(GEN bnr, GEN subgp, long flag, long prec)
 
   /* make a list of all non-trivial characters modulo conjugation */
   listCR = cgetg(cl, t_VEC);
-  indCR = new_chunk(cl);
-  invCR = new_chunk(cl); nc = 0;
+  indCR = cgetg(cl, t_VECSMALL);
+  invCR = cgetg(cl, t_VECSMALL); nc = 0;
   for (i = 1; i < cl; i++)
   {
     /* lift to a character on Cl(bnr) */
     GEN lchi = LiftChar(cyc, gel(Qt,3), gel(allCR,i), gel(Qt,2));
     GEN clchi = ConjChar(lchi, cyc);
-    long j, a = i;
+    long j, a = 0;
     for (j = 1; j <= nc; j++)
-      if (ZV_equal(gmael(listCR, j, 1), clchi)) { a = -j; break; }
+      if (ZV_equal(gmael(listCR, j, 1), clchi)) { a = j; break; }
 
-    if (a > 0)
+    if (!a)
     {
       nc++;
       gel(listCR,nc) = mkvec2(lchi, bnrconductorofchar(bnr, lchi));
@@ -2724,7 +2709,7 @@ bnrL1(GEN bnr, GEN subgp, long flag, long prec)
       invCR[nc] = i;
     }
     else
-      indCR[i] = -invCR[-a];
+      indCR[i] = -invCR[a];
 
     gel(allCR,i) = lchi;
   }
@@ -2842,7 +2827,7 @@ quadray_init(GEN *pD, GEN f, GEN *pbnf, long prec)
     int isfund;
     if (pbnf) {
       long v = f? gvar(f): NO_VARIABLE;
-      if (v == NO_VARIABLE) v = fetch_user_var("y");
+      if (v == NO_VARIABLE) v = 1;
       bnf = Buchall(quadpoly0(D, v), nf_FORCE, prec);
       nf = bnf_get_nf(bnf);
       isfund = equalii(D, nf_get_disc(nf));
@@ -3235,7 +3220,7 @@ quadhilbertimag(GEN D)
     P = grndtoi(P,&exmax);
     if (DEBUGLEVEL>1) timer_printf(&ti,"product, error bits = %ld",exmax);
     if (exmax <= -10) break;
-    avma = av0; prec += (DEFAULTPREC-2) + nbits2extraprec(exmax);
+    avma = av0; prec += nbits2extraprec(prec2nbits(DEFAULTPREC)+exmax);
     if (DEBUGLEVEL) pari_warn(warnprec,"quadhilbertimag",prec);
   }
   return gerepileupto(av,P);
@@ -3490,19 +3475,22 @@ PRECPB:
 
 #define nexta(a) (a>0 ? -a : 1-a)
 static GEN
-do_compo(GEN x, GEN y)
+do_compo(GEN A0, GEN B)
 {
-  long a, i, l = lg(y);
-  GEN z;
-  y = leafcopy(y); /* y := t^deg(y) y(#/t) */
-  for (i = 2; i < l; i++)
-    if (signe(gel(y,i))) gel(y,i) = monomial(gel(y,i), l-i-1, MAXVARN);
+  long a, i, l = lg(B), v = fetch_var_higher();
+  GEN A, z;
+  /* now v > x = pol_x(0) > nf variable */
+  B = leafcopy(B); setvarn(B, v);
+  for (i = 2; i < l; i++) gel(B,i) = monomial(gel(B,i), l-i-1, 0);
+  /* B := x^deg(B) B(v/x) */
+  A = A0 = leafcopy(A0); setvarn(A0, v);
   for  (a = 0;; a = nexta(a))
   {
-    if (a) x = gsubst(x, 0, gaddsg(a, pol_x(0)));
-    z = gsubst(resultant(x,y), MAXVARN, pol_x(0));
-    if (issquarefree(z)) return z;
+    if (a) A = RgX_translate(A0, stoi(a));
+    z = resultant(A,B); /* in variable 0 */
+    if (issquarefree(z)) break;
   }
+  (void)delete_var(); return z;
 }
 #undef nexta
 
@@ -3529,7 +3517,7 @@ findquad(GEN a, GEN x, GEN p)
   v = simplify_shallow(v); tv = typ(v);
   if (!is_scalar_t(tu)) pari_err_TYPE("findquad", u);
   if (!is_scalar_t(tv)) pari_err_TYPE("findquad", v);
-  x = deg1pol(v, u, varn(a));
+  x = deg1pol(u, v, varn(a));
   if (typ(x) == t_POL) x = gmodulo(x,p);
   return gerepileupto(av, x);
 }
@@ -3570,7 +3558,7 @@ compocyclo(GEN nf, long m, long d)
   p2 = gcoeff(nffactor(nfL,p2),1,1);
   p3 = do_compo(p1,p2); /* relative equation over L */
   /* compute non trivial s in Gal(L / K) */
-  sb= gneg(gadd(b, truecoeff(polLK,1))); /* s(b) = Tr(b) - b */
+  sb= gneg(gadd(b, RgX_coeff(polLK,1))); /* s(b) = Tr(b) - b */
   s = gadd(pol_x(vx), gsub(sb, b)); /* s(t) = t + s(b) - b */
   p3 = gmul(p3, galoisapplypol(nfL, s, p3));
   return findquad_pol(nf_get_pol(nf), a, p3);
@@ -3622,8 +3610,7 @@ treatspecialsigma(GEN bnr)
   }
 
   p1 = gcoeff(f,1,1); /* integer > 0 */
-  if (is_bigint(p1)) return NULL;
-  tryf = p1[2];
+  tryf = itou_or_0(p1); if (!tryf) return NULL;
   p2 = gcoeff(f,2,2); /* integer > 0 */
   if (is_pm1(p2)) fl = 0;
   else {
diff --git a/src/modules/subfield.c b/src/modules/subfield.c
index 3889aab..1fbd78f 100644
--- a/src/modules/subfield.c
+++ b/src/modules/subfield.c
@@ -193,7 +193,7 @@ im_block_by_perm(GEN D,GEN perm)
 {
   long i, lb = lg(D);
   GEN Dn = cgetg(lb,t_VEC);
-  for (i=1; i<lb; i++) gel(Dn,i) = vecpermute(perm, gel(D,i));
+  for (i=1; i<lb; i++) gel(Dn,i) = vecsmallpermute(perm, gel(D,i));
   return Dn;
 }
 
@@ -458,7 +458,7 @@ static GEN
 init_traces(GEN ff, GEN T, GEN p)
 {
   long N = degpol(T),i,j,k, r = lg(ff);
-  GEN Frob = FpXQ_matrix_pow(FpXQ_pow(pol_x(varn(T)),p, T,p), N,N, T,p);
+  GEN Frob = FpX_matFrobenius(T,p);
   GEN y,p1,p2,Trk,pow,pow1;
 
   k = degpol(gel(ff,r-1)); /* largest degree in modular factorization */
diff --git a/src/modules/thue.c b/src/modules/thue.c
index e324305..a011aae 100644
--- a/src/modules/thue.c
+++ b/src/modules/thue.c
@@ -20,17 +20,21 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 /**                                                                **/
 /********************************************************************/
 /* In all the forthcoming remarks, "paper" designs the paper "Thue Equations of
- * High Degree", by Yu. Bilu and G. Hanrot, J. Number Theory (1996). The numbering
- * of the constants corresponds to Hanrot's thesis rather than to the paper */
+ * High Degree", by Yu. Bilu and G. Hanrot, J. Number Theory (1996). The
+ * numbering of the constants corresponds to Hanrot's thesis rather than to the
+ * paper. See also
+ * "Solving Thue equations without the full unit group", Math. Comp. (2000) */
 
 /* Check whether tnf is a valid structure */
 static int
 checktnf(GEN tnf)
 {
   long l = lg(tnf);
-  if (typ(tnf)!=t_VEC || (l!=8 && l!=3)) return 0;
-  if (typ(gel(tnf,1)) != t_VEC) return 0;
-  if (l != 8) return 1; /* S=0 */
+  GEN v;
+  if (typ(tnf)!=t_VEC || (l!=8 && l!=4)) return 0;
+  v = gel(tnf,1);
+  if (typ(v) != t_VEC || lg(v) != 4) return 0;
+  if (l == 4) return 1; /* s=0 */
 
   (void)checkbnf(gel(tnf,2));
   return (typ(gel(tnf,3)) == t_COL
@@ -40,13 +44,6 @@ checktnf(GEN tnf)
        && typ(gel(tnf,7)) == t_VEC);
 }
 
-static GEN
-distoZ(GEN z)
-{
-  GEN t = gfrac(z);
-  return gmin(t, gsubsg(1,t));
-}
-
 /* Compensates rounding errors for computation/display of the constants.
  * Round up if dir > 0, down otherwise */
 static GEN
@@ -80,10 +77,15 @@ tnf_get_roots(GEN poly, long prec, long S, long T)
 static GEN
 LogHeight(GEN x, long prec)
 {
+  pari_sp av = avma;
   long i, n = lg(x)-1;
   GEN LH = gen_1;
-  for (i=1; i<=n; i++) LH = gmul(LH, gmax(gen_1, gabs(gel(x,i), prec)));
-  return gdivgs(glog(LH,prec), n);
+  for (i=1; i<=n; i++)
+  {
+    GEN t = gabs(gel(x,i), prec);
+    if (gcmpgs(t,1) > 0) LH = gmul(LH, t);
+  }
+  return gerepileupto(av, gdivgs(glog(LH,prec), n));
 }
 
 /* |x|^(1/n), x t_INT */
@@ -102,7 +104,8 @@ get_emb(GEN x, GEN r)
   for (i=1; i<l; i++)
   {
     GEN e = poleval(x, gel(r,i));
-    if (gequal0(e) || (typ(e) != t_INT && precision(e) == 3)) return NULL;
+    if (gequal0(e) || (typ(e) != t_INT && precision(e) <= LOWDEFAULTPREC ))
+      return NULL;
     gel(y,i) = e;
   }
   return y;
@@ -125,9 +128,6 @@ Conj_LH(GEN v, GEN *H, GEN r, long prec)
   return M;
 }
 
-static GEN abslog(GEN x, long prec) { return gabs(glog(x,prec), prec); }
-static GEN logabs(GEN x, long prec) { return glog(gabs(x,prec), prec); }
-
 /* Computation of M, its inverse A and precision check (see paper) */
 static GEN
 T_A_Matrices(GEN MatFU, long r, GEN *eps5, long prec)
@@ -136,14 +136,13 @@ T_A_Matrices(GEN MatFU, long r, GEN *eps5, long prec)
   long e = prec2nbits(prec);
 
   m1 = rowslice(vecslice(MatFU, 1,r), 1,r); /* minor order r */
-  m1 = logabs(m1, 3);
-
+  m1 = glog(gabs(m1, prec), prec); /* HIGH accuracy */
   A = RgM_inv(m1); if (!A) pari_err_PREC("thue");
   IntM = RgM_Rg_add(RgM_mul(A,m1), gen_m1);
+  IntM = gabs(IntM, 0);
 
-  eps2 = gadd(vecmax(gabs(IntM, 3)), real2n(-e, LOWDEFAULTPREC)); /* t_REAL */
-  nia = vecmax(gabs(A, 3));
-  if (typ(nia) != t_REAL) nia = gtofp(nia, LOWDEFAULTPREC);
+  eps2 = gadd(vecmax(IntM), real2n(-e, LOWDEFAULTPREC)); /* t_REAL */
+  nia = vecmax(gabs(A, 0));
 
   /* Check for the precision in matrix inversion. See paper, Lemma 2.4.2. */
   p1 = addrr(mulsr(r, gmul2n(nia, e)), eps2); /* t_REAL */
@@ -160,6 +159,39 @@ T_A_Matrices(GEN MatFU, long r, GEN *eps5, long prec)
   *eps5 = mulur(r, eps3); return A;
 }
 
+/* find a few large primes such that p Z_K = P1 P2 P3 Q, whith f(Pi/p) = 1
+ * From x - \alpha y = \prod u_i^b_i we will deduce 3 equations in F_p
+ * in check_prinfo. Eliminating x,y we get a stringent condition on (b_i). */
+static GEN
+get_prime_info(GEN bnf)
+{
+  long n = 1, e = gexpo(bnf_get_reg(bnf)), nbp = e < 20? 1: 2;
+  GEN L = cgetg(nbp+1, t_VEC), nf = checknf(bnf), fu = bnf_get_fu(bnf);
+  GEN X = pol_x(nf_get_varn(nf));
+  ulong p;
+  for(p = 2147483659UL; n <= nbp; p = unextprime(p+1))
+  {
+    GEN PR, A, U, LP = idealprimedec_limit_f(bnf, utoipos(p), 1);
+    long i;
+    if (lg(LP) < 4) continue;
+    A = cgetg(5, t_VECSMALL);
+    U = cgetg(4, t_VEC);
+    PR = cgetg(4, t_VEC);
+    for (i = 1; i <= 3; i++)
+    {
+      GEN modpr = zkmodprinit(nf, gel(LP,i));
+      GEN a = nf_to_Fq(nf, X, modpr);
+      GEN u = nfV_to_FqV(fu, nf, modpr);
+      A[i] = itou(a);
+      gel(U,i) = ZV_to_Flv(u,p);
+      gel(PR,i) = modpr;
+    }
+    A[4] = p;
+    gel(L,n++) = mkvec3(A,U,PR);
+  }
+  return L;
+}
+
 /* Performs basic computations concerning the equation.
  * Returns a "tnf" structure containing
  *  1) the polynomial
@@ -178,7 +210,7 @@ inithue(GEN P, GEN bnf, long flag, long prec)
 
   if (!bnf)
   {
-    bnf = Buchall(P, nf_FORCE, DEFAULTPREC);
+    bnf = Buchall(P, nf_FORCE, maxss(prec, DEFAULTPREC));
     if (flag) (void)bnfcertify(bnf);
     else
       Ind = floorr(mulru(bnf_get_reg(bnf), 5));
@@ -234,7 +266,7 @@ inithue(GEN P, GEN bnf, long flag, long prec)
     err_printf("c1 = %Ps\nc2 = %Ps\nIndice <= %Ps\n", c1, c2, Ind);
 
   ALH = gmul2n(ALH, 1);
-  tnf = cgetg(8,t_VEC); csts = cgetg(8,t_VEC);
+  tnf = cgetg(8,t_VEC); csts = cgetg(9,t_VEC);
   gel(tnf,1) = P;
   gel(tnf,2) = bnf;
   gel(tnf,3) = ro;
@@ -245,58 +277,51 @@ inithue(GEN P, GEN bnf, long flag, long prec)
   gel(csts,1) = c1; gel(csts,2) = c2;   gel(csts,3) = LogHeight(ro, prec);
   gel(csts,4) = x0; gel(csts,5) = eps5; gel(csts,6) = utoipos(prec);
   gel(csts,7) = Ind;
+  gel(csts,8) = get_prime_info(bnf);
   return tnf;
 }
 
 typedef struct {
-  GEN c10, c11, c13, c15, bak, NE, ALH, Ind, hal, MatFU, ro, Hmu;
-  GEN delta, lambda, inverrdelta;
+  GEN c10, c11, c13, c15, c91, bak, NE, Ind, hal, MatFU, divro, Hmu;
+  GEN delta, lambda, inverrdelta, ro, Pi, Pi2;
   long r, iroot, deg;
 } baker_s;
 
+static void
+other_roots(long iroot, long *i1, long *i2)
+{
+  switch (iroot) {
+    case 1: *i1=2; *i2=3; break;
+    case 2: *i1=1; *i2=3; break;
+   default: *i1=1; *i2=2; break;
+  }
+}
+/* low precision */
+static GEN abslog(GEN x) { return gabs(glog(gtofp(x,DEFAULTPREC),0), 0); }
+
 /* Compute Baker's bound c9 and B_0, the bound for the b_i's. See Thm 2.3.1 */
 static GEN
 Baker(baker_s *BS)
 {
-  const long prec = DEFAULTPREC;
-  GEN tmp, B0, hb0, c9 = gen_1, ro = BS->ro, ro0 = gel(ro,BS->iroot);
-  long k, i1, i2, r = BS->r;
-
-  switch (BS->iroot) {
-    case 1: i1=2; i2=3; break;
-    case 2: i1=1; i2=3; break;
-   default: i1=1; i2=2; break;
-  }
-
-  /* Compute h_1....h_r */
-  for (k=1; k<=r; k++)
-  {
-    tmp = gdiv(gcoeff(BS->MatFU,i1,k), gcoeff(BS->MatFU,i2,k));
-    tmp = gmax(gen_1, abslog(tmp,prec));
-    c9 = gmul(c9, gmax(gel(BS->ALH,k), gdiv(tmp, BS->bak)));
-  }
+  GEN tmp, B0, hb0, c9, Indc11;
+  long i1, i2;
 
+  other_roots(BS->iroot, &i1,&i2);
   /* Compute a bound for the h_0 */
-  hb0 = gadd(gmul2n(BS->hal,2), gmul2n(gadd(BS->Hmu,mplog2(prec)), 1));
-  tmp = gdiv(gmul(gsub(ro0, gel(ro,i2)), gel(BS->NE,i1)),
-             gmul(gsub(ro0, gel(ro,i1)), gel(BS->NE,i2)));
-  tmp = gmax(gen_1, abslog(tmp, prec));
+  hb0 = gadd(gmul2n(BS->hal,2), gmul2n(gadd(BS->Hmu,mplog2(DEFAULTPREC)), 1));
+  tmp = gmul(BS->divro, gdiv(gel(BS->NE,i1), gel(BS->NE,i2)));
+  tmp = gmax(gen_1, abslog(tmp));
   hb0 = gmax(hb0, gdiv(tmp, BS->bak));
-  c9 = gmul(c9,hb0);
-  /* Multiply c9 by the "constant" factor */
-  c9 = gmul(c9, gmul(mulri(mulur(18,mppi(prec)), int2n(5*(4+r))),
-                     gmul(gmul(mpfact(r+3), powiu(muliu(BS->bak,r+2), r+3)),
-                          glog(muliu(BS->bak,2*(r+2)),prec))));
+  c9 = gmul(BS->c91,hb0);
   c9 = gprec_w(myround(c9, 1), DEFAULTPREC);
+  Indc11 = rtor(mulir(BS->Ind,BS->c11), DEFAULTPREC);
   /* Compute B0 according to Lemma 2.3.3 */
   B0 = mulir(shifti(BS->Ind,1),
              divrr(addrr(mulrr(c9,mplog(divrr(mulir(BS->Ind, c9),BS->c10))),
-                         mplog(mulir(BS->Ind, BS->c11))),
-                   BS->c10));
+                         mplog(Indc11)), BS->c10));
   B0 = gmax(B0, dbltor(2.71828183));
   B0 = gmax(B0, mulrr(divir(BS->Ind, BS->c10),
-                      mplog(divrr(mulir(BS->Ind, BS->c11),
-                                  Pi2n(1, prec)))));
+                      mplog(divrr(Indc11, BS->Pi2))));
 
   if (DEBUGLEVEL>1) {
     err_printf("  B0  = %Ps\n",B0);
@@ -368,8 +393,10 @@ LLL_1stPass(GEN *pB0, GEN kappa, baker_s *BS, GEN *pBx)
   else
     triv = addir(sqri(BS->Ind), sqrr(B0));
 
-  gcoeff(lllmat, 3, 1) = roundr(negr(mulir(C, BS->lambda)));
-  gcoeff(lllmat, 3, 2) = roundr(negr(mulir(C, BS->delta)));
+  gcoeff(lllmat, 3, 1) = grndtoi(negr(mulir(C, BS->lambda)), &e);
+  if (e >= 0) return -1;
+  gcoeff(lllmat, 3, 2) = grndtoi(negr(mulir(C, BS->delta)), &e);
+  if (e >= 0) return -1;
   gcoeff(lllmat, 3, 3) = C;
   lllmat = ZM_lll(lllmat, 0.99, LLL_IM|LLL_INPLACE);
 
@@ -392,24 +419,10 @@ LLL_1stPass(GEN *pB0, GEN kappa, baker_s *BS, GEN *pBx)
   *pB0 = B0; *pBx = Bx; return 1;
 }
 
-
-/* Check whether a solution has already been found */
-static int
-new_sol(GEN z, GEN S)
-{
-  long i, l = lg(S);
-  for (i=1; i<l; i++)
-    if (ZV_equal(z,gel(S,i))) return 0;
-  return 1;
-}
-
 /* add solution (x,y) if not already known */
 static void
 add_sol(GEN *pS, GEN x, GEN y)
-{
-  GEN u = mkvec2(x,y);
-  if (new_sol(u, *pS)) *pS = shallowconcat(*pS, mkvec(u));
-}
+{ *pS = shallowconcat(*pS, mkvec(mkvec2(x,y))); }
 /* z = P(p,q), d = deg P, |z| = |rhs|. Check signs and (possibly)
  * add solutions (p,q), (-p,-q) */
 static void
@@ -440,23 +453,140 @@ CheckSol(GEN *pS, GEN z1, GEN z2, GEN P, GEN rhs, GEN ro)
   if (e > 0) return 0;
   if (e <= -13)
   { /* y != 0 and rhs != 0; check whether P(x,y) = rhs or P(-x,-y) = rhs */
-    GEN z = poleval(RgX_rescale(P,y),x);
+    GEN z = poleval(ZX_rescale(P,y),x);
     if (absi_equal(z, rhs)) add_pm(pS, x,y, z, degpol(P), rhs);
   }
   return 1;
 }
 
-/* find q1,q2,q3 st q1 + b q2 + c q3 ~ 0 */
+static const long EXPO1 = 7;
+static int
+round_to_b(GEN v, long B, long b, GEN Delta2, long i1, GEN L)
+{
+  long i, l = lg(v);
+  if (!b)
+  {
+    for (i = 1; i < l; i++)
+    {
+      long c;
+      if (i == i1)
+        c = 0;
+      else
+      {
+        GEN d = gneg(gel(L,i));
+        long e;
+        d = grndtoi(d,&e);
+        if (e > -EXPO1 || is_bigint(d)) return 0;
+        c = itos(d); if (labs(c) > B) return 0;
+      }
+      v[i] = c;
+    }
+  }
+  else
+  {
+    for (i = 1; i < l; i++)
+    {
+      long c;
+      if (i == i1)
+        c = b;
+      else
+      {
+        GEN d = gsub(gmulgs(gel(Delta2,i), b), gel(L,i));
+        long e;
+        d = grndtoi(d,&e);
+        if (e > -EXPO1 || is_bigint(d)) return 0;
+        c = itos(d); if (labs(c) > B) return 0;
+      }
+      v[i] = c;
+    }
+  }
+  return 1;
+}
+
+/* mu \prod U[i]^b[i] */
+static ulong
+Fl_factorback(ulong mu, GEN U, GEN b, ulong p)
+{
+  long i, l = lg(U);
+  ulong r = mu;
+  for (i = 1; i < l; i++)
+  {
+    long c = b[i];
+    ulong u = U[i];
+    if (!c) continue;
+    if (c < 0) { u = Fl_inv(u,p); c = -c; }
+    r = Fl_mul(r, Fl_powu(u,c,p), p);
+  }
+  return r;
+}
+
+/* x - alpha y = \pm mu \prod \mu_i^{b_i}. Reduce mod 3 distinct primes of
+ * degree 1 above the same p, and eliminate x,y => drastic conditions on b_i */
+static int
+check_pr(GEN bi, GEN Lmu, GEN L)
+{
+  GEN A = gel(L,1), U = gel(L,2);
+  ulong a = A[1], b = A[2], c = A[3], p = A[4];
+  ulong r = Fl_mul(Fl_sub(c,b,p), Fl_factorback(Lmu[1],gel(U,1),bi, p), p);
+  ulong s = Fl_mul(Fl_sub(a,c,p), Fl_factorback(Lmu[2],gel(U,2),bi, p), p);
+  ulong t = Fl_mul(Fl_sub(b,a,p), Fl_factorback(Lmu[3],gel(U,3),bi, p), p);
+  return Fl_add(Fl_add(r,s,p),t,p) == 0;
+}
+static int
+check_prinfo(GEN b, GEN Lmu, GEN prinfo)
+{
+  long i;
+  for (i = 1; i < lg(prinfo); i++)
+    if (!check_pr(b, gel(Lmu,i), gel(prinfo,i))) return 0;
+  return 1;
+}
+/* For each possible value of b_i1, compute the b_i's
+* and 2 conjugates of z = x - alpha y. Then check. */
+static int
+TrySol(GEN *pS, GEN B0, long i1, GEN Delta2, GEN Lambda, GEN ro,
+       GEN Lmu, GEN NE, GEN MatFU, GEN prinfo, GEN P, GEN rhs)
+{
+  long bi1, i, B = itos(gceil(B0)), l = lg(Delta2);
+  GEN b = cgetg(l,t_VECSMALL), L = cgetg(l,t_VEC);
+
+  for (i = 1; i < l; i++)
+  {
+    if (i == i1)
+      gel(L,i) = gen_0;
+    else
+    {
+      GEN delta = gel(Delta2,i);
+      gel(L, i) = gsub(gmul(delta,gel(Lambda,i1)), gel(Lambda,i));
+    }
+  }
+  for (bi1 = -B; bi1 <= B; bi1++)
+  {
+    GEN z1, z2;
+    if (!round_to_b(b, B, bi1, Delta2, i1, L)) continue;
+    if (!check_prinfo(b, Lmu, prinfo)) continue;
+    z1 = gel(NE,1);
+    z2 = gel(NE,2);
+    for (i = 1; i < l; i++)
+    {
+      z1 = gmul(z1, gpowgs(gcoeff(MatFU,1,i), b[i]));
+      z2 = gmul(z2, gpowgs(gcoeff(MatFU,2,i), b[i]));
+    }
+    if (!CheckSol(pS, z1,z2,P,rhs,ro)) return 0;
+  }
+  return 1;
+}
+
+/* find q1,q2,q3 st q1 b + q2 c + q3 ~ 0 */
 static GEN
 GuessQi(GEN b, GEN c, GEN *eps)
 {
-  const long shift = 33;
-  GEN Q, Lat, C = int2n(shift);
+  const long shift = 65;
+  GEN Q, Lat;
 
   Lat = matid(3);
   gcoeff(Lat,3,1) = ground(gmul2n(b, shift));
   gcoeff(Lat,3,2) = ground(gmul2n(c, shift));
-  gcoeff(Lat,3,3) = C;
+  gcoeff(Lat,3,3) = int2n(shift);
 
   Q = gel(lllint(Lat),1);
   if (gequal0(gel(Q,2))) return NULL; /* FAIL */
@@ -471,25 +601,25 @@ myfloor(GEN x) { return expo(x) > 30 ? ceil_safe(x): floorr(x); }
 
 /* Check for not-so-small solutions. Return a t_REAL or NULL */
 static GEN
-MiddleSols(GEN *pS, GEN bound, GEN roo, GEN poly, GEN rhs, long s, GEN c1)
+MiddleSols(GEN *pS, GEN bound, GEN roo, GEN P, GEN rhs, long s, GEN c1)
 {
   long j, k, nmax, d;
   GEN bndcf;
 
   if (expo(bound) < 0) return bound;
-  d = degpol(poly);
+  d = degpol(P);
   bndcf = sqrtnr(shiftr(c1,1), d - 2);
   if (cmprr(bound, bndcf) < 0) return bound;
-  /* divide by log((1+sqrt(5))/2)
+  /* divide by log2((1+sqrt(5))/2)
    * 1 + ==> ceil
    * 2 + ==> continued fraction is normalized if last entry is 1
    * 3 + ==> start at a0, not a1 */
-  nmax = 3 + (long)(gtodouble(logr_abs(bound)) / 0.4812118250596);
+  nmax = 3 + (long)(dbllog2(bound) * 1.44042009041256);
   bound = myfloor(bound);
 
   for (k = 1; k <= s; k++)
   {
-    GEN t = contfrac0(real_i(gel(roo,k)), NULL, nmax);
+    GEN ro = real_i(gel(roo,k)), t = gboundcf(ro, nmax);
     GEN pm1, qm1, p0, q0;
 
     pm1 = gen_0; p0 = gen_1;
@@ -498,14 +628,15 @@ MiddleSols(GEN *pS, GEN bound, GEN roo, GEN poly, GEN rhs, long s, GEN c1)
     for (j = 1; j < lg(t); j++)
     {
       GEN p, q, z, Q, R;
+      pari_sp av;
       p = addii(mulii(p0, gel(t,j)), pm1); pm1 = p0; p0 = p;
       q = addii(mulii(q0, gel(t,j)), qm1); qm1 = q0; q0 = q;
       if (cmpii(q, bound) > 0) break;
       if (DEBUGLEVEL >= 2) err_printf("Checking (+/- %Ps, +/- %Ps)\n",p, q);
-
-      z = poleval(ZX_rescale(poly,q), p); /* = P(p/q) q^dep(P) */
+      av = avma;
+      z = poleval(ZX_rescale(P,q), p); /* = P(p/q) q^dep(P) */
       Q = dvmdii(rhs, z, &R);
-      if (R != gen_0) continue;
+      if (R != gen_0) { avma = av; continue; }
       setabssign(Q);
       if (Z_ispowerall(Q, d, &Q))
       {
@@ -513,7 +644,17 @@ MiddleSols(GEN *pS, GEN bound, GEN roo, GEN poly, GEN rhs, long s, GEN c1)
         add_pm(pS, p, q, z, d, rhs);
       }
     }
-    if (j == lg(t)) pari_err_BUG("Short continued fraction in thue");
+    if (j == lg(t))
+    {
+      long prec;
+      if (j > nmax) pari_err_BUG("thue [short continued fraction]");
+      /* the theoretical value is bit_prec = gexpo(ro)+1+log2(bound) */
+      prec = precdbl(precision(ro));
+      if (DEBUGLEVEL>1) pari_warn(warnprec,"thue",prec);
+      roo = realroots(P, NULL, prec);
+      if (lg(roo)-1 != s) pari_err_BUG("thue [realroots]");
+      k--;
+    }
   }
   return bndcf;
 }
@@ -546,7 +687,7 @@ check_y(GEN *pS, GEN P, GEN poly, GEN Y, GEN rhs)
 static GEN
 SmallSols(GEN S, GEN x3, GEN poly, GEN rhs)
 {
-  pari_sp av = avma, lim = stack_lim(av, 1);
+  pari_sp av = avma;
   GEN X, P, rhs2;
   long j, l = lg(poly), n = degpol(poly);
   ulong y, By;
@@ -584,7 +725,7 @@ SmallSols(GEN S, GEN x3, GEN poly, GEN rhs)
     check_y_root(&S, P, utoineg(y));
     if (lS == lg(S)) { avma = av2; continue; } /* no solution found */
 
-    if (low_stack(lim,stack_lim(av,1)))
+    if (gc_needed(av,1))
     {
       if(DEBUGMEM>1) pari_warn(warnmem,"SmallSols");
       gerepileall(av, 2, &S, &rhs2);
@@ -619,7 +760,7 @@ thueinit(GEN pol, long flag, long prec)
 {
   GEN POL, C, L, fa, tnf, bnf = NULL;
   pari_sp av = avma;
-  long k, s, lfa, dpol;
+  long s, lfa, dpol;
 
   if (checktnf(pol)) { bnf = checkbnf(gel(pol,2)); pol = gel(pol,1); }
   if (typ(pol)!=t_POL) pari_err_TYPE("thueinit",pol);
@@ -627,24 +768,22 @@ thueinit(GEN pol, long flag, long prec)
   if (dpol <= 0) pari_err_CONSTPOL("thueinit");
   RgX_check_ZX(pol, "thueinit");
   if (varn(pol)) { pol = leafcopy(pol); setvarn(pol, 0); }
-  /* POL monic: POL(x) = C pol(x/L), L integer */
-  POL = ZX_primitive_to_monic(Q_primpart(pol), &L);
-  C = gdiv(powiu(L, dpol), gel(pol, dpol+2));
-  pol = POL;
 
-  fa = ZX_factor(pol);
-  lfa = lgcols(fa);
+  POL = Q_primitive_part(pol, &C);
+  L = gen_1;
+  fa = ZX_factor(POL); lfa = lgcols(fa);
   if (lfa > 2 || itos(gcoeff(fa,1,2)) > 1)
-  { /* reducible polynomial */
+  { /* reducible polynomial, no need to reduce to the monic case */
     GEN P, Q, R, g, f = gcoeff(fa,1,1), E = gcoeff(fa,1,2);
     long e = itos(E);
     long vy = fetch_var();
     long va = fetch_var();
     long vb = fetch_var();
+    C = C? ginv(C): gen_1;
     if (e != 1)
     {
       if (lfa == 2) {
-        tnf = mkvec2(mkvec3(pol,C,L), mkvec2(thueinit(f, flag, prec), E));
+        tnf = mkvec3(mkvec3(POL,C,L), thueinit(f, flag, prec), E);
         delete_var(); delete_var(); delete_var();
         return gerepilecopy(av, tnf);
       }
@@ -652,22 +791,26 @@ thueinit(GEN pol, long flag, long prec)
     }
     else
       P = f;
-    g = RgX_div(pol, P);
+    g = RgX_div(POL, P);
     P = RgX_Rg_sub(RgX_homogenize(f, vy), pol_x(va));
     Q = RgX_Rg_sub(RgX_homogenize(g, vy), pol_x(vb));
     R = polresultant0(P, Q, -1, 0);
-    tnf = mkvec2(mkvec3(pol,C,L), mkvec2(mkvecsmall4(degpol(f), e, va,vb),  R));
+    tnf = mkvec3(mkvec3(POL,C,L), mkvecsmall4(degpol(f), e, va,vb),  R);
     delete_var(); delete_var(); delete_var();
     return gerepilecopy(av, tnf);
   }
+  /* POL monic: POL(x) = C pol(x/L), L integer */
+  POL = ZX_primitive_to_monic(POL, &L);
+  C = gdiv(powiu(L, dpol), gel(pol, dpol+2));
+  pol = POL;
 
-  if (dpol <= 2) pari_err_DOMAIN("thue", "degree","<=",gen_2,pol);
-  s = sturm(pol);
+  s = ZX_sturm(pol);
   if (s)
   {
     long PREC, n = degpol(pol);
     double d, dr, dn = (double)n;
 
+    if (dpol <= 2) pari_err_DOMAIN("thueinit", "P","=",pol,pol);
     dr = (double)((s+n-2)>>1); /* s+t-1 */
     d = dn*(dn-1)*(dn-2);
     /* Guess precision by approximating Baker's bound. The guess is most of
@@ -691,58 +834,76 @@ thueinit(GEN pol, long flag, long prec)
   }
   else
   {
-    GEN ro = roots(pol, DEFAULTPREC), c0 = imag_i(gel(ro,1));
-    for (k=2; k<lg(ro); k++) c0 = mulrr(c0, imag_i(gel(ro,k)));
-    c0 = invr( absr(c0) ); tnf = mkvec2(pol, c0);
+    GEN ro, c0;
+    long k,l;
+    if (!bnf)
+    {
+      bnf = Buchall(pol, nf_FORCE, DEFAULTPREC);
+      if (flag) (void)bnfcertify(bnf);
+    }
+    ro = nf_get_roots(bnf_get_nf(bnf));
+    l = lg(ro);
+    c0 = imag_i(gel(ro,1));
+    for (k = 2; k < l; k++) c0 = mulrr(c0, imag_i(gel(ro,k)));
+    c0 = invr(sqrr(c0)); tnf = mkvec3(pol,bnf,c0);
   }
   gel(tnf,1) = mkvec3(gel(tnf,1), C, L);
   return gerepilecopy(av,tnf);
 }
 
+/* arg(t^2) / 2Pi; arg(t^2) = arg(t/conj(t)) */
+static GEN
+argsqr(GEN t, GEN Pi)
+{
+  GEN v, u = divrr(garg(t,0), Pi); /* in -1 < u <= 1 */
+  /* reduce mod Z to -1/2 < u <= 1/2 */
+  if (signe(u) > 0)
+  {
+    v = subrs(u,1); /* ]-1,0] */
+    if (absr_cmp(v,u) < 0) u = v;
+  }
+  else
+  {
+    v = addrs(u,1);/* ]0,1] */
+    if (absr_cmp(v,u) <= 0) u = v;
+  }
+  return u;
+}
+/* i1 != i2 */
 static void
-init_get_B(long i1, long i2, GEN Delta, GEN Lambda, GEN eps5, baker_s *BS,
+init_get_B(long i1, long i2, GEN Delta2, GEN Lambda, GEN Deps5, baker_s *BS,
            long prec)
 {
-  GEN delta, lambda, inverrdelta;
+  GEN delta, lambda;
   if (BS->r > 1)
   {
-    delta = divrr(gel(Delta,i2),gel(Delta,i1));
-    lambda = gdiv(gsub(gmul(gel(Delta,i2),gel(Lambda,i1)),
-                       gmul(gel(Delta,i1),gel(Lambda,i2))),
-                  gel(Delta,i1));
-    inverrdelta = divrr(subrr(mpabs(gel(Delta,i1)),eps5),
-                        mulrr(addsr(1,delta),eps5));
+    delta = gel(Delta2,i2);
+    lambda = gsub(gmul(delta,gel(Lambda,i1)), gel(Lambda,i2));
+    if (Deps5) BS->inverrdelta = divrr(Deps5, addsr(1,delta));
   }
   else
-  { /* r == 1, single fundamental unit (i1 = s = t = 1) */
-    GEN p1, Pi2 = Pi2n(1, prec);
-    GEN fu = gel(BS->MatFU,1), ro = BS->ro;
+  { /* r == 1: i1 = s = t = 1; i2 = 2 */
+    GEN fu = gel(BS->MatFU,1), ro = BS->ro, t;
 
-    p1 = gdiv(gel(fu,2), gel(fu,3));
-    delta = divrr(garg(p1,prec), Pi2);
+    t = gel(fu,2);
+    delta = argsqr(t, BS->Pi);
+    if (Deps5) BS->inverrdelta = shiftr(gabs(t,prec), prec2nbits(prec)-1);
 
-    p1 = gmul(gdiv(gsub(gel(ro,1), gel(ro,2)),
-                   gsub(gel(ro,1), gel(ro,3))),
-              gdiv(gel(BS->NE,3), gel(BS->NE,2)));
-    lambda = divrr(garg(p1,prec), Pi2);
-
-    inverrdelta = shiftr(gabs(gel(fu,2),prec), prec2nbits(prec)-1);
+    t = gmul(gsub(gel(ro,1), gel(ro,2)), gel(BS->NE,3));
+    lambda = argsqr(t, BS->Pi);
   }
-  if (DEBUGLEVEL>1) err_printf("  inverrdelta = %Ps\n",inverrdelta);
   BS->delta = delta;
   BS->lambda = lambda;
-  BS->inverrdelta = inverrdelta;
 }
 
 static GEN
-get_B0(long i1, GEN Delta, GEN Lambda, GEN eps5, long prec, baker_s *BS)
+get_B0(long i1, GEN Delta2, GEN Lambda, GEN Deps5, long prec, baker_s *BS)
 {
   GEN B0 = Baker(BS);
   long step = 0, i2 = (i1 == 1)? 2: 1;
   for(;;) /* i2 from 1 to r unless r = 1 [then i2 = 2] */
   {
-    init_get_B(i1,i2, Delta,Lambda,eps5, BS, prec);
-    if (DEBUGLEVEL>1) err_printf("  Entering CF...\n");
+    init_get_B(i1,i2, Delta2,Lambda,Deps5, BS, prec);
     /* Reduce B0 as long as we make progress: newB0 < oldB0 - 0.1 */
     for (;;)
     {
@@ -782,13 +943,13 @@ get_B0(long i1, GEN Delta, GEN Lambda, GEN eps5, long prec, baker_s *BS)
 }
 
 static GEN
-get_Bx_LLL(long i1, GEN Delta, GEN Lambda, GEN eps5, long prec, baker_s *BS)
+get_Bx_LLL(long i1, GEN Delta2, GEN Lambda, long prec, baker_s *BS)
 {
   GEN B0 = Baker(BS), Bx = NULL;
   long step = 0, i2 = (i1 == 1)? 2: 1;
   for(;;) /* i2 from 1 to r unless r = 1 [then i2 = 2] */
   {
-    init_get_B(i1,i2, Delta,Lambda,eps5, BS, prec);
+    init_get_B(i1,i2, Delta2,Lambda,NULL, BS, prec);
     if (DEBUGLEVEL>1) err_printf("  Entering LLL...\n");
     /* Reduce B0 as long as we make progress: newB0 < oldB0 - 0.1 */
     for (;;)
@@ -800,6 +961,7 @@ get_Bx_LLL(long i1, GEN Delta, GEN Lambda, GEN eps5, long prec, baker_s *BS)
       for (cf = 0; cf < cfMAX; cf++, kappa = muliu(kappa,10))
       {
         int res = LLL_1stPass(&B0, kappa, BS, &Bx);
+        if (res < 0) return NULL;
         if (res) break;
         if (DEBUGLEVEL>1) err_printf("LLL failed. Increasing kappa\n");
       }
@@ -811,7 +973,7 @@ get_Bx_LLL(long i1, GEN Delta, GEN Lambda, GEN eps5, long prec, baker_s *BS)
 
         if (! (Q = GuessQi(BS->delta, BS->lambda, &ep)) ) break;
 
-        /* Beware Q[2]] = gen_0 */
+        /* Q[2] != 0 */
         denbound = gadd(mulri(B0, absi(gel(Q,1))),
                         mulii(BS->Ind, absi(gel(Q,2))));
         q = denom( bestappr(BS->delta, denbound) );
@@ -833,30 +995,36 @@ get_Bx_LLL(long i1, GEN Delta, GEN Lambda, GEN eps5, long prec, baker_s *BS)
 }
 
 static GEN
-LargeSols(GEN P, GEN tnf, GEN rhs, GEN ne, GEN *pS)
+LargeSols(GEN P, GEN tnf, GEN rhs, GEN ne)
 {
-  GEN Vect, ro, bnf, MatFU, A, csts, dP, vecdP, Bx;
-  GEN c1,c2,c3,c4,c11,c14,c15, x0, x1, x2, x3, b, zp1, tmp, eps5;
-  long iroot, ine, n, i, r, upb, bi1, Prec, prec, s,t;
+  GEN S = NULL, Delta0, ro, ALH, bnf, nf, MatFU, A, csts, dP, Bx;
+  GEN c1,c2,c3,c4,c90,c91,c14, x0, x1, x2, x3, tmp, eps5, prinfo;
+  long iroot, ine, n, r, Prec, prec, s,t;
   baker_s BS;
   pari_sp av = avma;
 
-  bnf  = gel(tnf,2);
-  csts = gel(tnf,7);
-  if (!ne)
+  prec = 0; /*-Wall*/
+  bnf = NULL; /*-Wall*/
+  iroot = 1;
+  ine = 1;
+
+START:
+  if (S) /* restart from precision problems */
   {
-    ne = bnfisintnorm(bnf, rhs);
-    if (DEBUGLEVEL)
-      if (!is_pm1(gel(csts, 7)) && !is_pm1(bnf_get_no(bnf)) && !is_pm1(rhs))
-        pari_warn(warner, "The result returned by 'thue' is conditional on the GRH");
+    S = gerepilecopy(av, S);
+    prec = precdbl(prec);
+    if (DEBUGLEVEL) pari_warn(warnprec,"thue",prec);
+    tnf = inithue(P, bnf, 0, prec);
   }
-  else if (typ(ne) != t_VEC) pari_err_TYPE("thue",ne);
-  if (lg(ne)==1) return NULL;
-
-  nf_get_sign(bnf_get_nf(bnf), &s, &t);
+  else
+    S = cgetg(1, t_VEC);
+  bnf= gel(tnf,2);
+  nf = bnf_get_nf(bnf);
+  csts = gel(tnf,7);
+  nf_get_sign(nf, &s, &t);
   BS.r = r = s+t-1; n = degpol(P);
   ro     = gel(tnf,3);
-  BS.ALH = gel(tnf,4);
+  ALH    = gel(tnf,4);
   MatFU  = gel(tnf,5);
   A      = gel(tnf,6);
   c1     = gel(csts,1); c1 = gmul(absi(rhs), c1);
@@ -864,44 +1032,40 @@ LargeSols(GEN P, GEN tnf, GEN rhs, GEN ne, GEN *pS)
   BS.hal = gel(csts,3);
   x0     = gel(csts,4);
   eps5   = gel(csts,5);
-  Prec = gtolong(gel(csts,6));
+  Prec = itos(gel(csts,6));
   BS.Ind = gel(csts,7);
   BS.MatFU = MatFU;
-  BS.bak = mulss(n, (n-1)*(n-2)); /* safe */
+  BS.bak = muluu(n, (n-1)*(n-2)); /* safe */
   BS.deg = n;
+  prinfo = gel(csts,8);
 
   if (t) x0 = gmul(x0, absisqrtn(rhs, n, Prec));
   tmp = divrr(c1,c2);
   c3 = mulrr(dbltor(1.39), tmp);
   c4 = mulur(n-1, c3);
-  x1 = gmax(x0, sqrtnr(shiftr(tmp,1),n));
+  c14 = mulrr(c4, vecmax_shallow(RgM_sumcol(gabs(A,DEFAULTPREC))));
 
-  Vect = gmul(gabs(A,DEFAULTPREC), const_col(r, gen_1));
-  c14 = mulrr(c4, vecmax_shallow(Vect));
+  x1 = gmax(x0, sqrtnr(shiftr(tmp,1),n));
   x2 = gmax(x1, sqrtnr(mulur(10,c14), n));
-  if (DEBUGLEVEL>1) {
-    err_printf("x1 -> %Ps\n",x1);
-    err_printf("x2 -> %Ps\n",x2);
-    err_printf("c14 = %Ps\n",c14);
-  }
-
-  dP = ZX_deriv(P); vecdP = cgetg(s+1, t_VEC);
-  for (i=1; i<=s; i++) gel(vecdP,i) = poleval(dP, gel(ro,i));
+  x3 = gmax(x2, sqrtnr(shiftr(c14, EXPO1+1),n));
+  c90 = gmul(shiftr(mulur(18,mppi(DEFAULTPREC)), 5*(4+r)),
+                    gmul(gmul(mpfact(r+3), powiu(muliu(BS.bak,r+2), r+3)),
+                         glog(muliu(BS.bak,2*(r+2)),DEFAULTPREC)));
 
-  zp1 = dbltor(0.01);
-  x3 = gmax(x2, sqrtnr(shiftr(divrr(c14,zp1),1),n));
+  dP = ZX_deriv(P);
+  Delta0 = RgM_sumcol(A);
 
-  b = cgetg(r+1,t_COL);
-  for (iroot=1; iroot<=s; iroot++)
+  for (; iroot<=s; iroot++)
   {
-    GEN Delta, MatNE, Hmu, c5, c7;
+    GEN Delta = Delta0, Delta2, D, Deps5, MatNE, Hmu, diffRo, c5, c7, ro0;
+    long i1, iroot1, iroot2, k;
 
-    Vect = const_col(r, gen_1);
-    if (iroot <= r) gel(Vect,iroot) = stoi(1-n);
-    Delta = RgM_RgC_mul(A,Vect);
-
-    c5 = vecmax_shallow(gabs(Delta,Prec));
+    if (iroot <= r) Delta = RgC_add(Delta, RgC_Rg_mul(gel(A,iroot), stoi(-n)));
+    D = gabs(Delta,Prec); i1 = vecindexmax(D);
+    c5 = gel(D, i1);
+    Delta2 = RgC_Rg_div(Delta, gel(Delta, i1));
     c5  = myround(gprec_w(c5,DEFAULTPREC), 1);
+    Deps5 = divrr(subrr(c5,eps5), eps5);
     c7  = mulur(r,c5);
     BS.c10 = divur(n,c7);
     BS.c13 = divur(n,c5);
@@ -919,92 +1083,80 @@ LargeSols(GEN P, GEN tnf, GEN rhs, GEN ne, GEN *pS)
       if (DEBUGLEVEL>1) pari_warn(warnprec,"thue",prec);
       ro = tnf_get_roots(P, prec, s, t);
     }
+    ro0 = gel(ro,iroot);
     BS.ro    = ro;
     BS.iroot = iroot;
+    BS.Pi  = mppi(prec);
+    BS.Pi2 = Pi2n(1,prec);
+    diffRo = cgetg(r+1, t_VEC);
+    for (k=1; k<=r; k++)
+    {
+      GEN z = gel(ro,k);
+      z = (k == iroot)? gdiv(rhs, poleval(dP, z)): gsub(ro0, z);
+      gel(diffRo,k) = gabs(z, prec);
+    }
+    other_roots(iroot, &iroot1,&iroot2);
+    BS.divro = gdiv(gsub(ro0, gel(ro,iroot2)), gsub(ro0, gel(ro,iroot1)));
+    /* Compute h_1....h_r */
+    c91 = c90;
+    for (k=1; k<=r; k++)
+    {
+      GEN z = gdiv(gcoeff(MatFU,iroot1,k), gcoeff(MatFU,iroot2,k));
+      z = gmax(gen_1, abslog(z));
+      c91 = gmul(c91, gmax(gel(ALH,k), gdiv(z, BS.bak)));
+    }
+    BS.c91 = c91;
 
-    for (ine=1; ine<lg(ne); ine++)
+    for (; ine<lg(ne); ine++)
     {
       pari_sp av2 = avma;
+      long lS = lg(S);
       GEN Lambda, B0, c6, c8;
-      GEN NE = gel(MatNE,ine), Vect2 = cgetg(r+1,t_COL);
-      long k, i1;
+      GEN NE = gel(MatNE,ine), v = cgetg(r+1,t_COL);
 
       if (DEBUGLEVEL>1) err_printf("  - norm sol. no %ld/%ld\n",ine,lg(ne)-1);
       for (k=1; k<=r; k++)
       {
-        if (k == iroot)
-          tmp = gdiv(rhs, gmul(gel(vecdP,k), gel(NE,k)));
-        else
-          tmp = gdiv(gsub(gel(ro,iroot),gel(ro,k)), gel(NE,k));
-        gel(Vect2,k) = glog(gabs(tmp,prec), prec);
+        GEN z = gdiv(gel(diffRo,k), gabs(gel(NE,k), prec));
+        gel(v,k) = glog(z, prec);
       }
-      Lambda = RgM_RgC_mul(A,Vect2);
+      Lambda = RgM_RgC_mul(A,v);
 
       c6 = addrr(dbltor(0.1), vecmax_shallow(gabs(Lambda,DEFAULTPREC)));
       c6 = myround(c6, 1);
       c8 = addrr(dbltor(1.23), mulur(r,c6));
-      c11= mulrr(shiftr(c3,1) , mpexp(divrr(mulur(n,c8),c7)));
-      c15= mulrr(shiftr(c14,1), mpexp(divrr(mulur(n,c6),c5)));
-
-      if (DEBUGLEVEL>1) {
-        err_printf("  c6  = %Ps\n",c6);
-        err_printf("  c8  = %Ps\n",c8);
-        err_printf("  c11 = %Ps\n",c11);
-        err_printf("  c15 = %Ps\n",c15);
-      }
-      BS.c11 = c11;
-      BS.c15 = c15;
+      BS.c11= mulrr(shiftr(c3,1) , mpexp(divrr(mulur(n,c8),c7)));
+      BS.c15= mulrr(shiftr(c14,1), mpexp(divrr(mulur(n,c6),c5)));
       BS.NE = NE;
       BS.Hmu = gel(Hmu,ine);
-
-      i1 = vecindexmax(gabs(Delta,prec));
       if (is_pm1(BS.Ind))
       {
-        if (! (B0 = get_B0(i1, Delta, Lambda, eps5, prec, &BS)) ) goto PRECPB;
+        GEN mu = gel(ne,ine), Lmu = cgetg(lg(prinfo),t_VEC);
+        long i, j;
+
+        for (i = 1; i < lg(prinfo); i++)
+        {
+          GEN v = gel(prinfo,i), PR = gel(v,3), L = cgetg(4, t_VECSMALL);
+          for (j = 1; j <= 3; j++) L[j] = itou(nf_to_Fq(nf, mu, gel(PR,j)));
+          gel(Lmu, i) = L;
+        }
+        if (! (B0 = get_B0(i1, Delta2, Lambda, Deps5, prec, &BS)) ||
+            !TrySol(&S, B0, i1, Delta2, Lambda, ro, Lmu, NE,MatFU,prinfo,
+                    P,rhs))
+          goto START;
+        if (lg(S) == lS) avma = av2;
       }
       else
       {
-        if (! (Bx = get_Bx_LLL(i1, Delta, Lambda, eps5, prec, &BS)) ) goto PRECPB;
+        if (! (Bx = get_Bx_LLL(i1, Delta2, Lambda, prec, &BS)) )
+           goto START;
         x3 = gerepileupto(av2, gmax(Bx, x3));
-        continue;
-      }
-     /* For each possible value of b_i1, compute the b_i's
-      * and 2 conjugates of z = x - alpha y. Then check. */
-      upb = gtolong(gceil(B0));
-      for (bi1=-upb; bi1<=upb; bi1++)
-      {
-        GEN z1, z2;
-        for (i=1; i<=r; i++)
-        {
-          gel(b,i) = gdiv(gsub(gmul(gel(Delta,i), stoi(bi1)),
-                               gsub(gmul(gel(Delta,i),gel(Lambda,i1)),
-                                    gmul(gel(Delta,i1),gel(Lambda,i)))),
-                          gel(Delta,i1));
-          if (gcmp(distoZ(gel(b,i)), zp1) > 0) break;
-        }
-        if (i <= r) continue;
-
-        z1 = z2 = gen_1;
-        for(i=1; i<=r; i++)
-        {
-          GEN c = ground(gel(b,i));
-          z1 = gmul(z1, powgi(gcoeff(MatFU,1,i), c));
-          z2 = gmul(z2, powgi(gcoeff(MatFU,2,i), c));
-        }
-        z1 = gmul(z1, gel(NE,1));
-        z2 = gmul(z2, gel(NE,2));
-        if (!CheckSol(pS, z1,z2,P,rhs,ro)) goto PRECPB;
       }
     }
+    ine = 1;
   }
-  return gmax(x0, MiddleSols(pS, x3, ro, P, rhs, s, c1));
-
-PRECPB:
-  ne = gerepilecopy(av, ne);
-  prec += 5 * (DEFAULTPREC-2);
-  if (DEBUGLEVEL>1) pari_warn(warnprec,"thue",prec);
-  tnf = inithue(P, bnf, 0, prec);
-  return LargeSols(P, tnf, rhs, ne, pS);
+  x3 = gmax(x0, MiddleSols(&S, x3, ro, P, rhs, s, c1));
+  return SmallSols(S, x3, P, rhs);
 }
 
 /* restrict to solutions (x,y) with L | x, replacing each by (x/L, y) */
@@ -1023,10 +1175,66 @@ filter_sol_x(GEN S, GEN L)
   setlg(S, k); return S;
 }
 
+static GEN bnfisintnorm_i(GEN bnf, GEN a, long s, GEN z);
+static GEN
+tnf_get_Ind(GEN tnf) { return gmael(tnf,7,7); }
 static GEN
-sol_0(void)
-{ GEN S = cgetg(2, t_VEC); gel(S,1) = mkvec2(gen_0,gen_0); return S; }
+tnf_get_bnf(GEN tnf) { return gel(tnf,2); }
 
+static void
+maybe_warn(GEN bnf, GEN a, GEN Ind)
+{
+  if (!is_pm1(Ind) && !is_pm1(bnf_get_no(bnf)) && !is_pm1(a))
+    pari_warn(warner, "The result returned by 'thue' is conditional on the GRH");
+}
+/* return solutions of Norm(x) = a mod U(K)^+ */
+static GEN
+get_ne(GEN bnf, GEN a, GEN Ind)
+{
+  if (DEBUGLEVEL) maybe_warn(bnf,a,Ind);
+  return bnfisintnorm(bnf, a);
+}
+/* return solutions of |Norm(x)| = |a| mod U(K) */
+static GEN
+get_neabs(GEN bnf, GEN a, GEN Ind)
+{
+  if (DEBUGLEVEL) maybe_warn(bnf,a,Ind);
+  return bnfisintnormabs(bnf, a);
+}
+
+/* Let P(z)=z^2+Bz+C, convert t=u+v*z (mod P) solution of norm equation N(t)=A
+ * to [x,y] = [u,-v] form: y^2P(x/y) = A */
+static GEN
+ne2_to_xy(GEN t)
+{
+  GEN u,v;
+  switch(degpol(t))
+  {
+    case -1: u = v = gen_0; break;
+    case 0: u = gel(t,2); v = gen_0; break;
+    default: u = gel(t,2); v = gel(t,3);
+  }
+  return mkvec2(u, gneg(v));
+}
+static GEN
+ne2V_to_xyV(GEN v)
+{
+  long i, l;
+  GEN w = cgetg_copy(v,&l);
+  for (i=1; i<l; i++) gel(w,i) = ne2_to_xy(gel(v,i));
+  return w;
+}
+
+static GEN
+sol_0(void) { retmkvec( mkvec2(gen_0,gen_0) ); }
+static void
+sols_from_R(GEN Rab, GEN *pS, GEN P, GEN POL, GEN rhs)
+{
+  GEN ry = nfrootsQ(Rab);
+  long k, l = lg(ry);
+  for (k = 1; k < l; k++)
+    if (typ(gel(ry,k)) == t_INT) check_y(pS, P, POL, gel(ry,k), rhs);
+}
 /* Given a tnf structure as returned by thueinit, a RHS and
  * optionally the solutions to the norm equation, returns the solutions to
  * the Thue equation F(x,y)=a */
@@ -1039,73 +1247,109 @@ thue(GEN tnf, GEN rhs, GEN ne)
   if (typ(tnf) == t_POL) tnf = thueinit(tnf, 0, DEFAULTPREC);
   if (!checktnf(tnf)) pari_err_TYPE("thue [please apply thueinit()]", tnf);
   if (typ(rhs) != t_INT) pari_err_TYPE("thue",rhs);
+  if (ne && typ(ne) != t_VEC) pari_err_TYPE("thue",ne);
 
   /* solve P(x,y) = rhs <=> POL(L x, y) = C rhs, with POL monic in Z[X] */
   POL = gel(tnf,1);
   C = gel(POL,2); rhs = gmul(C, rhs);
   if (typ(rhs) != t_INT) { avma = av; return cgetg(1, t_VEC); }
+  if (!signe(rhs))
+  {
+    GEN v = gel(tnf,2);
+    avma = av;
+    /* at least 2 irreducible factors, one of which has degree 1 */
+    if (typ(v) == t_VECSMALL && v[1] ==1)
+      pari_err_DOMAIN("thue","#sols","=",strtoGENstr("oo"),rhs);
+    return sol_0();
+  }
   L = gel(POL,3);
   POL = gel(POL,1);
-
-  S = cgetg(1,t_VEC);
   if (lg(tnf) == 8)
   {
-    if (!signe(rhs)) { avma = av; return sol_0(); }
-    x3 = LargeSols(POL, tnf, rhs, ne, &S);
-    if (!x3) { avma = (pari_sp)S; return S; }
-    S = SmallSols(S, x3, POL, rhs);
+    if (!ne) ne = get_ne(tnf_get_bnf(tnf), rhs, tnf_get_Ind(tnf));
+    if (lg(ne) == 1) { avma = av; return cgetg(1, t_VEC); }
+    S = LargeSols(POL, tnf, rhs, ne);
   }
-  else if (typ(gel(tnf,2)) == t_REAL)
+  else if (typ(gel(tnf,3)) == t_REAL)
   { /* Case s=0. All solutions are "small". */
-    GEN c0 = gel(tnf,2); /* t_REAL */
-    if (!signe(rhs)) { avma = av; return sol_0(); }
+    GEN bnf = tnf_get_bnf(tnf);
+    GEN c0 = gel(tnf,3), F;
     x3 = sqrtnr(mulir(absi(rhs),c0), degpol(POL));
     x3 = addrr(x3, dbltor(0.1)); /* guard from round-off errors */
-    S = SmallSols(S, x3, POL, rhs);
+    S = cgetg(1,t_VEC);
+    if (!ne && expo(x3) > 10)
+    {
+      long l;
+      GEN P;
+      if (expi(rhs) < 150) F = Z_factor(rhs);
+      else
+      {
+        F = Z_factor_limit(rhs, 500000);
+        P = gel(F,1); l = lg(P);
+        if (!is_pm1(rhs) && !BPSW_psp(gel(P,l-1))) F = NULL;
+      }
+      if (F) ne = get_ne(bnf, F, gen_1);
+    }
+    if (ne)
+    {
+      if (lg(ne) == 1) { avma = av; return cgetg(1,t_VEC); }
+      if (degpol(POL) == 2) /* quadratic imaginary */
+      {
+        GEN u = bnf_get_tuU(bnf);
+        long w =  bnf_get_tuN(bnf);
+        if (w == 4) /* u = I */
+          ne = shallowconcat(ne, RgXQV_RgXQ_mul(ne,u,POL));
+        else if (w == 6) /* u = j */
+        {
+          GEN u2 = RgXQ_sqr(u,POL);
+          ne = shallowconcat1(mkvec3(ne, RgXQV_RgXQ_mul(ne,u,POL),
+                                         RgXQV_RgXQ_mul(ne,u2,POL)));
+        }
+        ne = ne2V_to_xyV(ne);
+        S = shallowconcat(ne, RgV_neg(ne));
+      }
+    }
+    if (lg(S) == 1) S = SmallSols(S, x3, POL, rhs);
   }
-  else if (typ(gmael(tnf,2,1)) == t_VEC) /* reducible case, pure power*/
+  else if (typ(gel(tnf,3)) == t_INT) /* reducible case, pure power*/
   {
-    long e;
-    tnf = gel(tnf,2);
-    e = itos( gel(tnf,2) );
-    if (!signe(rhs)) { avma = av; return sol_0(); }
-
+    GEN bnf, ne1 = NULL, ne2 = NULL;
+    long e = itos( gel(tnf,3) );
     if (!Z_ispowerall(rhs, e, &rhs)) { avma = av; return cgetg(1, t_VEC); }
-    tnf = gel(tnf,1);
-    S = thue(tnf, rhs, NULL);
-    if (odd(e)) S = shallowconcat(S, thue(tnf, negi(rhs), NULL));
+    tnf = gel(tnf,2);
+    bnf = tnf_get_bnf(tnf);
+    ne = get_neabs(bnf, rhs, lg(tnf)==8?tnf_get_Ind(tnf): gen_1);
+    ne1= bnfisintnorm_i(bnf,rhs,1,ne);
+    S = thue(tnf, rhs, ne1);
+    if (!odd(e) && lg(tnf)==8) /* if s=0, norms are positive */
+    {
+      ne2 = bnfisintnorm_i(bnf,rhs,-1,ne);
+      S = shallowconcat(S, thue(tnf, negi(rhs), ne2));
+    }
   }
-  else if (typ(gel(tnf,2)) == t_VEC) /* other reducible cases */
+  else /* other reducible cases */
   { /* solve f^e * g = rhs, f irreducible factor of smallest degree */
-    GEN P, D, v = gmael(tnf, 2, 1), R = gmael(tnf, 2, 2);
-    long i, l, degf = v[1], e = v[2], va = v[3], vb = v[4];
-    if (!signe(rhs)) {
-      if (degf == 1) pari_err_DOMAIN("thue","#sols","=",strtoGENstr("oo"),rhs);
-      avma = av; return cgetg(1, t_VEC);
-    }
+    GEN P, D, v = gel(tnf, 2), R = gel(tnf, 3);
+    long i, l, e = v[2], va = v[3], vb = v[4];
     P = cgetg(lg(POL), t_POL); P[1] = POL[1];
     D = divisors(rhs); l = lg(D);
+    S = cgetg(1,t_VEC);
     for (i = 1; i < l; i++)
     {
-      GEN Rab, ry, df = gel(D,i), dg = diviiexact(rhs, df);
-      long k;
-
+      GEN Rab, df = gel(D,i), dg = gel(D,l-i); /* df*dg=|rhs| */
       if (e > 1 && !Z_ispowerall(df, e, &df)) continue;
       /* Rab: univariate polynomial in Z[Y], whose roots are the possible y. */
       /* Here and below, Rab != 0 */
+      if (signe(rhs) < 0) dg = negi(dg); /* df*dg=rhs */
       Rab = gsubst(gsubst(R, va, df), vb, dg);
-      ry = nfrootsQ(Rab);
-      for (k = 1; k < lg(ry); k++)
-        if (typ(gel(ry,k)) == t_INT) check_y(&S, P, POL, gel(ry,k), rhs);
-      if (odd(e)) {
-        Rab = gsubst(gsubst(R, va, negi(df)), vb, negi(dg));
-        ry = nfrootsQ(Rab);
-        for (k = 1; k < lg(ry); k++)
-          if (typ(gel(ry,k)) == t_INT) check_y(&S, P, POL, gel(ry,k), rhs);
-      }
+      sols_from_R(Rab, &S,P,POL,rhs);
+      Rab = gsubst(gsubst(R, va, negi(df)), vb, odd(e)? negi(dg): dg);
+      sols_from_R(Rab, &S,P,POL,rhs);
     }
   }
-  return gerepilecopy(av, filter_sol_x(S, L));
+  S = filter_sol_x(S, L);
+  S = gen_sort_uniq(S, (void*)lexcmp, cmp_nodata);
+  return gerepileupto(av, S);
 }
 
 /********************************************************************/
@@ -1227,10 +1471,10 @@ isintnorm_loop(struct sol_abs *T, long i)
 }
 
 static int
-get_sol_abs(struct sol_abs *T, GEN bnf, GEN a, GEN *ptPR)
+get_sol_abs(struct sol_abs *T, GEN bnf, GEN fact, GEN *ptPR)
 {
   GEN nf = bnf_get_nf(bnf);
-  GEN fact = absi_factor(a), P = gel(fact,1), E = gel(fact,2), PR;
+  GEN P = gel(fact,1), E = gel(fact,2), PR;
   long N = nf_get_degree(nf), nP = lg(P)-1, Ngen, max, nPR, i, j;
 
   max = nP*N; /* upper bound for T->nPR */
@@ -1328,15 +1572,19 @@ GEN
 bnfisintnormabs(GEN bnf, GEN a)
 {
   struct sol_abs T;
-  GEN nf, res, PR;
+  GEN nf, res, PR, F;
   long i;
 
-  if (typ(a) != t_INT) pari_err_TYPE("bnfisintnormabs",a);
+  if ((F = check_arith_all(a,"bnfisintnormabs")))
+  {
+    a = typ(a) == t_VEC? gel(a,1): factorback(F);
+    if (signe(a) < 0) F = clean_Z_factor(F);
+  }
   bnf = checkbnf(bnf); nf = bnf_get_nf(bnf);
   if (!signe(a)) return mkvec(gen_0);
   if (is_pm1(a)) return mkvec(gen_1);
-
-  if (!get_sol_abs(&T, bnf, a, &PR)) return cgetg(1, t_VEC);
+  if (!F) F = absi_factor(a);
+  if (!get_sol_abs(&T, bnf, F, &PR)) return cgetg(1, t_VEC);
   /* |a| > 1 => T.nPR > 0 */
   res = cgetg(T.sindex+1, t_VEC);
   for (i=1; i<=T.sindex; i++)
@@ -1348,14 +1596,22 @@ bnfisintnormabs(GEN bnf, GEN a)
   return res;
 }
 
-GEN
-bnfisintnorm(GEN bnf, GEN a)
+/* z = bnfisintnormabs(bnf,a), sa = 1 or -1, return bnfisintnorm(bnf,sa*|a|) */
+static GEN
+bnfisintnorm_i(GEN bnf, GEN a, long sa, GEN z)
 {
-  pari_sp av = avma;
-  GEN nf = checknf(bnf), T = nf_get_pol(nf), unit = NULL;
-  GEN z = bnfisintnormabs(bnf, a);
-  long sNx, i, j, N = degpol(T), l = lg(z), sa = signe(a);
+  GEN nf = checknf(bnf), T = nf_get_pol(nf), f = nf_get_index(nf), unit = NULL;
+  GEN Tp, A = signe(a) == sa? a: negi(a);
+  long sNx, i, j, N = degpol(T), l = lg(z);
   long norm_1 = 0; /* gcc -Wall */
+  ulong p, Ap = 0; /* gcc -Wall */
+  forprime_t S;
+  if (!signe(a)) return z;
+  u_forprime_init(&S,3,ULONG_MAX);
+  while((p = u_forprime_next(&S)))
+    if (umodiu(f,p)) { Ap = umodiu(A,p); if (Ap) break; }
+  Tp = ZX_to_Flx(T,p);
+  /* p > 2 doesn't divide A nor Q_denom(z in Z_K)*/
 
   /* update z in place to get correct signs: multiply by unit of norm -1 if
    * it exists, otherwise delete solution with wrong sign */
@@ -1364,8 +1620,16 @@ bnfisintnorm(GEN bnf, GEN a)
     GEN x = gel(z,i);
     int xpol = (typ(x) == t_POL);
 
-    if (xpol) sNx = signe(ZX_resultant(T, Q_primpart(x)));
-    else      sNx = gsigne(x) < 0 && odd(N) ? -1 : 1;
+    if (xpol)
+    {
+      GEN dx, y = Q_remove_denom(x,&dx);
+      ulong Np = Flx_resultant(Tp, ZX_to_Flx(y,p), p);
+      ulong dA = dx? Fl_mul(Ap, Fl_powu(umodiu(dx,p), N, p), p): Ap;
+      /* Nx = Res(T,y) / dx^N = A or -A. Check mod p */
+      sNx = dA == Np? sa: -sa;
+    }
+    else
+      sNx = gsigne(x) < 0 && odd(N) ? -1 : 1;
     if (sNx != sa)
     {
       if (! unit) norm_1 = get_unit_1(bnf, &unit);
@@ -1379,6 +1643,17 @@ bnfisintnorm(GEN bnf, GEN a)
     }
     gel(z,j++) = x;
   }
-  setlg(z, j);
-  return gerepilecopy(av, z);
+  setlg(z, j); return z;
+}
+GEN
+bnfisintnorm(GEN bnf, GEN a)
+{
+  pari_sp av = avma;
+  GEN ne = bnfisintnormabs(bnf,a);
+  switch(typ(a))
+  {
+    case t_VEC: a = gel(a,1); break;
+    case t_MAT: a = factorback(a); break;
+  }
+  return gerepilecopy(av, bnfisintnorm_i(bnf,a,signe(a), ne));
 }
diff --git a/src/mt/mpi.c b/src/mt/mpi.c
index d40d407..c9091bc 100644
--- a/src/mt/mpi.c
+++ b/src/mt/mpi.c
@@ -18,8 +18,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 static THREAD int pari_MPI_size, pari_MPI_rank;
 static THREAD long nbreq = 0;
 
-enum PMPI_cmd { PMPI_close, PMPI_worker, PMPI_work, PMPI_parisize,
-                PMPI_precreal, PMPI_eval };
+enum PMPI_cmd { PMPI_close, PMPI_worker, PMPI_work, PMPI_parisizemax,
+                PMPI_parisize, PMPI_precreal, PMPI_eval };
 
 struct mt_mstate
 {
@@ -145,10 +145,9 @@ static void
 pari_MPI_child(void)
 {
   pari_sp av = avma;
-  long size;
+  ulong rsize = 0, vsize = 0;
   GEN worker = NULL, work, done;
   struct gp_context rec;
-  if (!diffptr) initprimetable(500000);
   gp_context_save(&rec);
   if (setjmp(child_env))
   {
@@ -159,7 +158,8 @@ pari_MPI_child(void)
     switch (recvfrom_request(0))
     {
     case PMPI_worker:
-      avma = top;
+      paristack_setsize(rsize, vsize);
+      gp_context_save(&rec);
       worker = recvfrom_GEN(0);
       av = avma;
       break;
@@ -169,10 +169,11 @@ pari_MPI_child(void)
       send_GEN(done, 0);
       avma = av;
       break;
+    case PMPI_parisizemax:
+      vsize = recvfrom_long(0);
+      break;
     case PMPI_parisize:
-      size = recvfrom_long(0);
-      pari_init_stack(size,top-bot);
-      gp_context_save(&rec);
+      rsize = recvfrom_long(0);
       break;
     case PMPI_precreal:
       precreal = recvfrom_long(0);
@@ -255,12 +256,18 @@ mtmpi_queue_get(struct mt_state *junk, long *workid, long *pending)
 {
   struct mt_mstate *mt = pari_mt;
   GEN done;
+  (void) junk;
   if (mt->nbint<=mt->n) { mt->source=mt->nbint; *pending = nbreq; return NULL; }
   done = recvany_GEN(&mt->source);
   nbreq--; *pending = nbreq;
   if (workid) *workid = mt->workid[mt->source];
   if (typ(done) == t_ERROR)
-    pari_err(0,done);
+  {
+    if (err_get_num(done)==e_STACK)
+      pari_err(e_STACKTHREAD);
+    else
+      pari_err(0,done);
+  }
   return done;
 }
 
@@ -268,6 +275,7 @@ static void
 mtmpi_queue_submit(struct mt_state *junk, long workid, GEN work)
 {
   struct mt_mstate *mt = pari_mt;
+  (void) junk;
   if (!work) { mt->nbint=mt->n+1; return; }
   if (mt->nbint<=mt->n) mt->nbint++;
   nbreq++;
@@ -290,18 +298,20 @@ void
 mt_queue_start(struct pari_mt *pt, GEN worker)
 {
   if (pari_mt || pari_MPI_size <= 2 || pari_mt_nbthreads <= 1)
-    return mtsingle_queue_start(pt, worker);
+    mtsingle_queue_start(pt, worker);
   else
   {
     struct mt_mstate *mt = &pari_mt_data;
     long i, n = minss(pari_mt_nbthreads, pari_MPI_size-1);
-    long mtparisize = GP_DATA->threadsize? GP_DATA->threadsize: top-bot;
+    long mtparisize = GP_DATA->threadsize? GP_DATA->threadsize: pari_mainstack->rsize;
+    long mtparisizemax = GP_DATA->threadsizemax;
     pari_mt = mt;
     mt->workid = (long*) pari_malloc(sizeof(long)*(n+1));
     for (i=1; i <= n; i++)
     {
       send_request_long(PMPI_parisize, mtparisize, i);
-      send_request_long(PMPI_precreal, precreal, i);
+      send_request_long(PMPI_parisizemax, mtparisizemax, i);
+      send_request_long(PMPI_precreal, get_localprec(), i);
       send_request_GEN(PMPI_worker, worker, i);
     }
     mt->n = n;
diff --git a/src/mt/pthread.c b/src/mt/pthread.c
index 455ab8d..8eeeb53 100644
--- a/src/mt/pthread.c
+++ b/src/mt/pthread.c
@@ -18,11 +18,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 struct mt_queue
 {
   long no;
+  pari_sp avma;
   GEN input, output;
   GEN worker;
   long workid;
-  pthread_cond_t cond, cond1, cond2;
-  pthread_mutex_t mut, mut1, mut2;
+  pthread_cond_t cond;
+  pthread_mutex_t mut;
   pthread_cond_t *pcond;
   pthread_mutex_t *pmut;
 };
@@ -114,6 +115,11 @@ mt_queue_run(void *arg)
   pari_sp av = avma;
   struct mt_queue *mq = (struct mt_queue *) args;
   mt_thread_no = mq->no;
+  LOCK(mq->pmut)
+  {
+    mq->avma = av;
+    pthread_cond_signal(mq->pcond);
+  } UNLOCK(mq->pmut);
   for(;;)
   {
     GEN work, done;
@@ -122,28 +128,19 @@ mt_queue_run(void *arg)
       while(!mq->input)
         pthread_cond_wait(&mq->cond, &mq->mut);
     } UNLOCK(&mq->mut);
-    work = gcopy(mq->input);
-    LOCK(&mq->mut1)
-    {
-      mq->input = NULL;
-      pthread_cond_signal(&mq->cond1);
-    } UNLOCK(&mq->mut1);
+    avma = mq->avma;
+    work = mq->input;
     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
     done = closure_callgenvec(mq->worker,work);
     pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);
     LOCK(mq->pmut)
     {
+      mq->avma = av;
+      mq->input = NULL;
       mq->output = done;
       pthread_cond_signal(mq->pcond);
     } UNLOCK(mq->pmut);
-    LOCK(&mq->mut2)
-    {
-      while(mq->output)
-        pthread_cond_wait(&mq->cond2, &mq->mut2);
-    } UNLOCK(&mq->mut2);
-    avma = av;
   }
-  return NULL;
 }
 
 static long
@@ -167,39 +164,36 @@ mtpthread_queue_get(struct mt_state *junk, long *workid, long *pending)
   long last;
   (void) junk;
   if (mt->nbint<mt->n) { mt->last = mt->nbint; *pending = mt->pending; return NULL; }
-  BLOCK_SIGINT_START
-  LOCK(&mt->pmut)
+  if ((last = mt_queue_check(mt)) < 0)
   {
-    while ((last = mt_queue_check(mt)) < 0)
+    BLOCK_SIGINT_START
+    LOCK(&mt->pmut)
     {
-      pthread_cond_wait(&mt->pcond, &mt->pmut);
-      if (PARI_SIGINT_pending)
+      while ((last = mt_queue_check(mt)) < 0)
       {
-        int sig = PARI_SIGINT_pending;
-        PARI_SIGINT_pending = 0;
-        pthread_mutex_unlock(&mt->pmut);
-        PARI_SIGINT_block = 0;
-        raise(sig);
-        PARI_SIGINT_block = 1;
-        pthread_mutex_lock(&mt->pmut);
+        pthread_cond_wait(&mt->pcond, &mt->pmut);
+        if (PARI_SIGINT_pending)
+        {
+          int sig = PARI_SIGINT_pending;
+          PARI_SIGINT_pending = 0;
+          pthread_mutex_unlock(&mt->pmut);
+          PARI_SIGINT_block = 0;
+          raise(sig);
+          PARI_SIGINT_block = 1;
+          pthread_mutex_lock(&mt->pmut);
+        }
       }
-    }
-  } UNLOCK(&mt->pmut);
-  BLOCK_SIGINT_END
+    } UNLOCK(&mt->pmut);
+    BLOCK_SIGINT_END
+  }
   mq = mt->mq+last;
-  if (mq->output==err_e_STACK) pari_err(e_STACK);
+  if (mq->output==err_e_STACK) pari_err(e_STACKTHREAD);
   done = gcopy(mq->output);
+  mq->output = NULL;
   if (workid) *workid = mq->workid;
   if (typ(done)==t_ERROR) pari_err(0,done);
-  BLOCK_SIGINT_START
-  LOCK(&mq->mut2)
-  {
-    mq->output = NULL;
-    pthread_cond_signal(&mq->cond2);
-  } UNLOCK(&mq->mut2);
   mt->last = last;
   mt->pending--;
-  BLOCK_SIGINT_END
   *pending = mt->pending;
   return done;
 }
@@ -212,19 +206,26 @@ mtpthread_queue_submit(struct mt_state *junk, long workid, GEN work)
   (void) junk;
   if (!work) { mt->nbint=mt->n; return; }
   BLOCK_SIGINT_START
-  if (mt->nbint<mt->n) mt->nbint++;
+  if (mt->nbint<mt->n)
+  {
+    mt->nbint++;
+    if (!mq->avma)
+    {
+      LOCK(mq->pmut)
+      {
+        while(!mq->avma)
+          pthread_cond_wait(mq->pcond, mq->pmut);
+      } UNLOCK(mq->pmut);
+    }
+  }
   LOCK(&mq->mut)
   {
-    mq->input = work;
+    mq->output = NULL;
     mq->workid = workid;
+    mq->input = gcopy_avma(work, &mq->avma);
     pthread_cond_signal(&mq->cond);
   } UNLOCK(&mq->mut);
   mt->pending++;
-  LOCK(&mq->mut1)
-  {
-    while (mq->input)
-      pthread_cond_wait(&mq->cond1, &mq->mut1);
-  } UNLOCK(&mq->mut1);
   BLOCK_SIGINT_END
 }
 
@@ -243,11 +244,7 @@ mt_queue_reset(void)
   {
     struct mt_queue *mq = mt->mq+i;
     pthread_cond_destroy(&mq->cond);
-    pthread_cond_destroy(&mq->cond1);
-    pthread_cond_destroy(&mq->cond2);
     pthread_mutex_destroy(&mq->mut);
-    pthread_mutex_destroy(&mq->mut1);
-    pthread_mutex_destroy(&mq->mut2);
     pari_thread_free(&mt->pth[i]);
   }
   pari_free(mt->mq);
@@ -260,13 +257,14 @@ void
 mt_queue_start(struct pari_mt *pt, GEN worker)
 {
   if (pari_mt)
-    return mtsingle_queue_start(pt, worker);
+    mtsingle_queue_start(pt, worker);
   else
   {
     long NBT = pari_mt_nbthreads;
     struct mt_pstate *mt =
            (struct mt_pstate*) pari_malloc(sizeof(struct mt_pstate));
-    long mtparisize = GP_DATA->threadsize? GP_DATA->threadsize: top-bot;
+    long mtparisize = GP_DATA->threadsize? GP_DATA->threadsize: pari_mainstack->rsize;
+    long mtparisizemax = GP_DATA->threadsizemax;
     long i;
     mt->mq  = (struct mt_queue *) pari_malloc(sizeof(*mt->mq)*NBT);
     mt->th  = (pthread_t *) pari_malloc(sizeof(*mt->th)*NBT);
@@ -282,18 +280,18 @@ mt_queue_start(struct pari_mt *pt, GEN worker)
     {
       struct mt_queue *mq = mt->mq+i;
       mq->no     = i;
+      mq->avma   = 0;
       mq->worker = worker;
       mq->input  = NULL;
       mq->output = NULL;
       mq->pcond  = &mt->pcond;
       mq->pmut   = &mt->pmut;
       pthread_cond_init(&mq->cond,NULL);
-      pthread_cond_init(&mq->cond1,NULL);
-      pthread_cond_init(&mq->cond2,NULL);
       pthread_mutex_init(&mq->mut,NULL);
-      pthread_mutex_init(&mq->mut1,NULL);
-      pthread_mutex_init(&mq->mut2,NULL);
-      pari_thread_alloc(&mt->pth[i],mtparisize,(GEN)mq);
+      if (mtparisizemax)
+        pari_thread_valloc(&mt->pth[i],mtparisize,mtparisizemax,(GEN)mq);
+      else
+        pari_thread_alloc(&mt->pth[i],mtparisize,(GEN)mq);
     }
     if (DEBUGLEVEL) pari_warn(warner,"start threads");
     for (i=0;i<NBT;i++)
diff --git a/src/mt/single.c b/src/mt/single.c
index e3da91b..6174031 100644
--- a/src/mt/single.c
+++ b/src/mt/single.c
@@ -45,5 +45,5 @@ pari_mt_init(void)
 void
 mt_queue_start(struct pari_mt *pt, GEN worker)
 {
-  return mtsingle_queue_start(pt, worker);
+  mtsingle_queue_start(pt, worker);
 }
diff --git a/src/systems/mingw/mingw.c b/src/systems/mingw/mingw.c
index edd7156..adae588 100644
--- a/src/systems/mingw/mingw.c
+++ b/src/systems/mingw/mingw.c
@@ -156,3 +156,33 @@ win32_set_pdf_viewer(void)
     putenv(buf);
   }
 }
+
+extern int win32ctrlc, win32alrm;
+static HANDLE hTimerQueue = NULL;
+
+static void CALLBACK
+win32_cb_alarm(void *lpParam, BOOLEAN TimerOrWaitFired)
+{
+  (void) lpParam; (void) TimerOrWaitFired;
+  win32ctrlc++;
+  win32alrm = 1;
+}
+
+void
+win32_alarm(unsigned int s)
+{
+  if (hTimerQueue)
+  {
+    HANDLE oldhTimerQueue = hTimerQueue;
+    hTimerQueue = NULL;
+    DeleteTimerQueue(oldhTimerQueue);
+  }
+  if (s)
+  {
+    void *arg = NULL;
+    HANDLE hTimer = NULL;
+    hTimerQueue = CreateTimerQueue();
+    CreateTimerQueueTimer( &hTimer, hTimerQueue,
+        (WAITORTIMERCALLBACK)win32_cb_alarm, &arg , s*1000, 0, 0);
+  }
+}
diff --git a/src/systems/mingw/mingw.h b/src/systems/mingw/mingw.h
index e108465..9fb189d 100644
--- a/src/systems/mingw/mingw.h
+++ b/src/systems/mingw/mingw.h
@@ -17,3 +17,4 @@ void win32_ansi_fputs(const char* s, void* f);
 int win32_terminal_width(void);
 int win32_terminal_height(void);
 void win32_set_pdf_viewer(void);
+void win32_alarm(unsigned int s);
diff --git a/src/test/32/agm b/src/test/32/agm
index e69de29..3e665e0 100644
--- a/src/test/32/agm
+++ b/src/test/32/agm
@@ -0,0 +1,4 @@
+  ***   at top-level: agm(1,2+O(5))
+  ***                 ^-------------
+  *** agm: not an n-th power residue in Qp_sqrt: 3 + O(5).
+Total time spent: 16
diff --git a/src/test/32/algebras b/src/test/32/algebras
new file mode 100644
index 0000000..618fd37
--- /dev/null
+++ b/src/test/32/algebras
@@ -0,0 +1,3261 @@
+  ***   Warning: new stack size = 100000000 (95.367 Mbytes).
+contains nfabs: 1
+[[x^4 + x^3 + x^2 + x + 1, [[1], 1], [Mat(125), 5], 1, [], [], [[1, x, x^2, 
+x^3], [1, 1, 1, 1]], [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], 1, [y
+, [1, 0], 1, 1, [Mat(1), Mat(1), Mat(1), Mat(1), 1, Mat(1), [1, 0], []], [0.
+E-57], [1], Mat(1), Mat(1)], [x^4 + x^3 + x^2 + x + 1, 0, -1, y, x^4 + x^3 +
+ x^2 + x + 1], [0]], [x^2, -x^3 - x^2 - x - 1, x^3], Mod(3, y), Vecsmall([0]
+), [[[3, [3]~, 1, 1, 1], [5, [5]~, 1, 1, 1]], Vecsmall([3, 1])], 0, [1, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 
+0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0
+, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 
+0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
+, [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0
+, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 1], [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 
+0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0
+; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 
+0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, -1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0; 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0,
+ 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0
+, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0
+, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 
+0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 
+0, 0, -1, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0,
+ 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0; 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, -1, 0, 1; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0; 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0], [0, 0, -1, 1, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0; 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0
+, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 
+0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0; 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0
+, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0
+, 0, 1, -1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -
+1; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1; 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 1, 0, -1; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1], [
+0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0; 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, -1
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0
+, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0
+, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 
+0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0,
+ 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, -1, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0
+; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1; 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, -1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0; 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 3, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3; 1, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 
+0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0
+, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -
+3, 3, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 3; 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, -3, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -3, 0,
+ 0; 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0, 0, -1, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0
+, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, -1, 1, 0, 
+0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 
+0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0,
+ 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0
+, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, -3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, -3; 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 3, -3; 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0; 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0, -1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0,
+ 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 0, 1, 0, 0, 0
+, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0
+, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 
+0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 
+0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0,
+ 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0; 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, -3, 0, 3, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0,
+ 0, 3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0; 0, -1, 1, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+; 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, -1, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 
+0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0
+, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0,
+ 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 3, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0
+; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0; 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, -3, 
+3, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 3, 0, 0, 0, 0, 0; 0, 0, 
+0, 0, 0, 0, 0, 0, -3, 0, 0, 3, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0,
+ 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0; 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -3, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -3, 0, 0; 0, 0, 0, -1, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0; 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, -1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0;
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, -1, 0, 0
+, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0,
+ 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, -3
+, 0, 3, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, 0; 0, 0, 0
+, 0, 0, 0, 0, 0, 3, -3, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, -3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, -3; 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, -3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 3, -3; 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, -1, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0; 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 1, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 
+0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, 0, 0; 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 
+-3, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -3, 0, 0, 0, 0, 0; 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -3, 0, 3, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 3; 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0; 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0; 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0; 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, -1
+, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0; 0
+, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 
+0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0
+, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 
+0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 3, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0; 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 3; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0
+, -3, 3, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, 0, 0, 
+0, 0; 0, 0, 0, 0, 3, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 3, -3,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, 0, 0, 0, 0;
+ 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 3, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -3
+, 0, 0, 3, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, 0, 0; 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, -3, 0, 3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0; 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -3, 0, 0; 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0; 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, -1, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0], [0, 0, 0, 0, -3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -3, 0
+, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -3, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0
+, 0; 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0
+, 0, -3, 3, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 3, 0, 0, 0, 0; 
+0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 3, 
+-3, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3; 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, -3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, -3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -3; 0, 0, -1, 
+1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0; 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, 
+0, 0, 0; 0, 0, 0, 0, 3, 0, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 3, 
+0, -3, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 3, -3, 0, 0, 0, 0, 0, 0, 0,
+ 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -3, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, -3, 0, 0, 0, 0, 0; 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 3, -3, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, -3, 3, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 3, 0; 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, -3, 0, 0, 0; 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 0, 1
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0; 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], 0, [16, -4, -4
+, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
+Suite: all
+Suite: get
+degree: 1
+center: 1
+splitting: 1
+automorphism: 1
+b: 1
+trivial hasse invariants: 1
+charac: 1
+dim: 1
+absdim: 1
+basis: 1
+invbasis: 1
+basis*invbasis: 1
+iscyclic: 1
+radical: 1
+Suite: operations
+radical: 1
+addition: 1
+negation: 1
+soustraction: 1
+multiplication: 1
+non-commutativity: 0
+left division: 1
+right division: 1
+noncommutative left division: 1
+noncommutative right division: 1
+division by non-invertible: error("impossible inverse in algdivl: [Mod(Mod(-
+1, i^2 + 1)*s, s^2 + 2), Mod(Mod(i - 1, i^2 + 1), s^2 + 2)]~.")
+nilpotent: 1
+square: 1
+square j: 1
+inverse: 1
+powers: 1
+negative powers: 1
+multiplication table j: 1
+multiplication table: 1
+characteristic polynomial: 1
+characteristic polynomial j: 1
+trace zero: 1
+trace commutator: 1
+trace: 1
+norm zero: 1
+norm one: 1
+norm j: 1
+norm is multiplicative a*b: 1
+norm is multiplicative b*a: 1
+poleval: 1
+poleval b: 1
+Suite: hasse sum to 0
+cyclo construction: [[x^2 + x + 1, [[1], 1], [Mat(3), -3], 1, [], [], [[1, x
+], [1, 1]], [1, 0; 0, 1], 1, [y, [1, 0], 1, 1, [Mat(1), Mat(1), Mat(1), Mat(
+1), 1, Mat(1), [1, 0], []], [0.E-57], [1], Mat(1), Mat(1)], [x^2 + x + 1, 0,
+ -1, y, x^2 + x + 1], [[x^2 + x + 1, [0, 1], -3, 1, [Mat([1, -0.500000000000
+00000000000000000000000000 + 0.86602540378443864676372317075293618347*I]), [
+1, 0.36602540378443864676372317075293618347; 1, -1.3660254037844386467637231
+707529361835], [1, 0; 1, -1], [2, -1; -1, -1], [3, 2; 0, 1], [1, -1; -1, -2]
+, [3, [2, -1; 1, 1]], []], [-0.50000000000000000000000000000000000000 + 0.86
+602540378443864676372317075293618347*I], [1, x], [1, 0; 0, 1], [1, 0, 0, -1;
+ 0, 1, 1, -1]]]], [-x - 1], Mod(-175624635, y), Vecsmall([1]), [[[5, [5]~, 1
+, 1, 1], [11708309, [11708309]~, 1, 1, 1], [3, [3]~, 1, 1, 1]], Vecsmall([1,
+ 1, 1])], 0, [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 2/3; 0, 0, 0, 1/3], [1, 0, 0,
+ 0; 0, 1, 0, 0; 0, 0, 1, -2; 0, 0, 0, 3], [[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1,
+ 0; 0, 0, 0, 1], [0, -1, 0, 0; 1, -1, 0, 0; 0, 0, 1, 1; 0, 0, -3, -2], [0, 0
+, -175624635, -117083090; 0, 0, 0, -58541545; 1, -2, 0, 0; 0, 3, 0, 0], [0, 
+0, -58541545, -58541545; 0, 0, 58541545, 0; 0, -1, 0, 0; 1, 1, 0, 0]], 0, [4
+, -2, 0, 0]]
+cyclo ramified at infinity: 1
+cyclo unramified at infinity: 1
+cyclo 5: 1
+cyclo 5 bis: 1
+cyclo 7 bis no mo: 1
+cyclo 11 no mo: 1
+quat -1,-1 over Q: 1
+quat -1,-1 over Q(sqrt(2)): 1
+quat -1,-1 over Q(sqrt(60)): 1
+Suite: compositum of relative extensions
+compositum of degrees 2 and 3 over quadratic field: 1
+compositum of degrees 2 and 4 over quadratic field: 1
+compositum of degrees 5 and 7 over quadratic field: 1
+compositum of degrees 2 and 3 over degree 5 field: 1
+compositum of degrees 2 and 4 over degree 5 field: 1
+compositum of degrees 5 and 4 over degree 5 field: 1
+Suite: tensor product of cyclic algebras
+radical 1: 1
+radical 2: 1
+radical 3: 1
+tensor of degree 2 and 3 no mo: 1
+Suite: Grunwald-Wang
+A quadratic over Q, 2 large inert, imaginary: 1
+A quartic over Q, 2 large inert, imaginary: error("sorry, nfgrunwaldwang for
+ non-prime degree is not yet implemented.")
+A : degree 4 over Q(i), local degrees [4,1,1]: 1
+A degree 3 over Q(j), local degrees [3,3] larger primes: 1
+A : degree 3 over Q(sqrt(5)), local degrees [3,3] [0,0], larger primes: 1
+A : degree 5 over Q(sqrt(7)), local degrees [5,5,5,5,5,5,5] [0,0]: 1
+A : degree 9 over Q(zeta_9), local degrees [9,9,9,9]: 1
+A degree 2 over totally real sextic, local degrees [2,2] [2,2,2,2,2,2], larg
+er primes: 1
+A degree 2 over totally real sextic, local degrees [] [2,2,2,2,2,2]: 1
+Suite: algebra from Hasse invariants
+matrix algebra invariants: 1
+algebra 1 invariants: 1
+algebra 2 invariants: 1
+test: [[J^2 + 8, [[1], 1], [Mat(8), -2], Mat(2), [], [], [[1, J], [1, Mat(1/
+2)]], [1, 0; 0, 1], 2, [y, [1, 0], 1, 1, [Mat(1), Mat(1), Mat(1), Mat(1), 1,
+ Mat(1), [1, 0], []], [0.E-57], [1], Mat(1), Mat(1)], [J^2 + 8, 0, -1, y, J^
+2 + 8], [[J^2 + 8, [0, 1], -8, 2, [Mat([1, 0.E-77 + 1.4142135623730950488016
+887242096980786*I]), [1, 1.4142135623730950488016887242096980786; 1, -1.4142
+135623730950488016887242096980786], [1, 1; 1, -1], [2, 0; 0, -4], [4, 0; 0, 
+2], [2, 0; 0, -1], [2, [0, -2; 1, 0]], []], [0.E-77 + 2.82842712474619009760
+33774484193961571*I], [1, 1/2*J], [1, 0; 0, 2], [1, 0, 0, -2; 0, 1, 1, 0]]]]
+, [-J], Mod(-39, y), Vecsmall([1]), [[[13, [13]~, 1, 1, 1], [2, [2]~, 1, 1, 
+1], [3, [3]~, 1, 1, 1]], Vecsmall([1, 0, 0])], 0, [1, 0, 1/2, 1/2; 0, 1, 0, 
+1/4; 0, 0, 1/2, 1/6; 0, 0, 0, 1/12], [1, 0, -1, -4; 0, 1, 0, -3; 0, 0, 2, -4
+; 0, 0, 0, 12], [[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [0, -2, 2
+, 0; 1, 0, 2, 1; 0, 0, 2, 1; 0, 0, -6, -2], [0, -2, -10, -4; 0, -1, 0, -2; 1
+, -2, 1, 0; 0, 6, 0, 2], [0, -1, -3, -2; 0, 0, 2, 0; 0, -1, 1, 0; 1, 2, -1, 
+1]], 0, [4, 0, 2, 2]]
+degree 6 algebra over Q: 1
+trivial finite conditions: [Vecsmall([1, 1]), [[[3, [3, 0]~, 1, 2, 1], [5, [
+1, 2]~, 2, 1, [1, 2; 2, -1]]], Vecsmall([0, 0])]]
+Suite: more operations
+construct algebra: [[x^3 - 21*x + 7, [[1], 1], [Mat(49), 1], Mat(27), [], []
+, [[1, x + 1, x^2 - x - 2], [1, 1/3, Mat(1/9)]], [1, -1, 1; 0, 1, 1; 0, 0, 1
+], 27, [y, [1, 0], 1, 1, [Mat(1), Mat(1), Mat(1), Mat(1), 1, Mat(1), [1, 0],
+ []], [0.E-57], [1], Mat(1), Mat(1)], [x^3 - 21*x + 7, 0, -1, y, x^3 - 21*x 
++ 7], [[x^3 - 21*x + 7, [3, 0], 49, 27, [[1, -1.2469796037174670610500097680
+084796213, 1.8019377358048382524722046390148901023; 1, 0.4450418679126288085
+7780512899358951893, -1.2469796037174670610500097680084796213; 1, 1.80193773
+58048382524722046390148901023, 0.44504186791262880857780512899358951893], [1
+, -1.2469796037174670610500097680084796213, 1.801937735804838252472204639014
+8901023; 1, 0.44504186791262880857780512899358951893, -1.2469796037174670610
+500097680084796213; 1, 1.8019377358048382524722046390148901023, 0.4450418679
+1262880857780512899358951893], [1, -1, 2; 1, 0, -1; 1, 2, 0], [3, 1, 1; 1, 5
+, -2; 1, -2, 5], [7, 0, 5; 0, 7, 5; 0, 0, 1], [3, -1, -1; -1, 2, 1; -1, 1, 2
+], [7, [2, 1, -1; 1, 3, 1; 0, 1, 2]], []], [-4.74093881115240118315002930402
+54388638, 0.33512560373788642573341538698076855680, 4.4058132074145147574166
+139170446703070], [1, 1/3*x + 1/3, 1/9*x^2 - 1/9*x - 11/9], [1, -1, 10; 0, 3
+, 3; 0, 0, 9], [1, 0, 0, 0, 1, -1, 0, -1, 2; 0, 1, 0, 1, 1, 1, 0, 1, -1; 0, 
+0, 1, 0, 1, 0, 1, 0, 0]]]], [-1/3*x^2 - 2/3*x + 14/3, 1/3*x^2 - 1/3*x - 14/3
+], Mod(-6, y), Vecsmall([0]), [[[2, [2]~, 1, 1, 1], [3, [3]~, 1, 1, 1], [7, 
+[7]~, 1, 1, 1]], Vecsmall([1, 2, 0])], 0, [1, 0, 0, 0, 0, 1/7, 0, 2/7, 5/7; 
+0, 1, 0, 0, 0, 1/7, 0, 1/7, 5/7; 0, 0, 1, 0, 0, 3/7, 0, 0, 1/7; 0, 0, 0, 1, 
+0, 5/7, 0, 2/7, 5/7; 0, 0, 0, 0, 1, 5/7, 0, 1/7, 5/7; 0, 0, 0, 0, 0, 1/7, 0,
+ 0, 1/7; 0, 0, 0, 0, 0, 0, 1, 2/7, 5/7; 0, 0, 0, 0, 0, 0, 0, 1/7, 5/7; 0, 0,
+ 0, 0, 0, 0, 0, 0, 1/7], [1, 0, 0, 0, 0, -1, 0, -2, 6; 0, 1, 0, 0, 0, -1, 0,
+ -1, 1; 0, 0, 1, 0, 0, -3, 0, 0, 2; 0, 0, 0, 1, 0, -5, 0, -2, 10; 0, 0, 0, 0
+, 1, -5, 0, -1, 5; 0, 0, 0, 0, 0, 7, 0, 0, -7; 0, 0, 0, 0, 0, 0, 1, -2, 5; 0
+, 0, 0, 0, 0, 0, 0, 7, -35; 0, 0, 0, 0, 0, 0, 0, 0, 7], [[1, 0, 0, 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, 0, 0, 1, 0
+, 0, 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, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1], [0
+, 1, -1, 1, 1, 1, 6, 2, 5; 1, 1, 1, 1, 1, 2, 1, 1, 3; 0, 1, 0, 3, 3, 4, 2, 2
+, 6; 0, 0, 0, 6, 5, 7, 10, 5, 13; 0, 0, 0, 4, 4, 5, 5, 3, 8; 0, 0, 0, -7, -7
+, -9, -7, -5, -14; 0, 0, 0, 0, 0, 0, 5, 1, 2; 0, 0, 0, 0, 0, 0, -35, -9, -21
+; 0, 0, 0, 0, 0, 0, 7, 2, 5], [0, -1, 2, 0, -1, 0, -4, -2, -6; 0, 1, -1, 0, 
+-1, -1, 0, 0, 0; 1, 0, 0, 0, -3, -2, -2, -1, -4; 0, 0, 0, 0, -4, -3, -8, -4,
+ -13; 0, 0, 0, 1, -4, -2, -4, -2, -7; 0, 0, 0, 0, 7, 5, 7, 4, 14; 0, 0, 0, 0
+, 0, 0, -2, -1, -3; 0, 0, 0, 0, 0, 0, 28, 12, 35; 0, 0, 0, 0, 0, 0, -7, -3, 
+-9], [0, 0, -1, 0, -2, -1, -6, -2, -5; 0, 0, -1, 0, -1, -1, 0, -1, -5; 0, 0,
+ -3, 0, 0, -1, 0, 0, -1; 1, 0, -5, 0, -2, -2, 0, 0, 0; 0, 1, -5, 0, -1, -2, 
+0, 0, 0; 0, 0, 7, 0, 0, 2, 0, 0, 0; 0, 0, 0, 1, -2, 0, 0, 0, 0; 0, 0, 0, 0, 
+7, 0, 0, 1, 0; 0, 0, 0, 0, 0, 1, 0, 0, 1], [0, -1, 0, -4, -4, -5, 0, -1, -3;
+ 0, -1, 0, 0, 0, 0, 0, -1, -4; 0, -3, 0, -2, -2, -3, -6, -3, -9; 0, -4, -1, 
+-8, -8, -11, 0, -4, -13; 1, -4, 1, -4, -4, -5, 0, -2, -7; 0, 7, 0, 7, 7, 10,
+ 0, 4, 14; 0, 0, 0, -2, -3, -3, 0, -1, -3; 0, 0, 0, 28, 28, 35, 0, 12, 35; 0
+, 0, 0, -7, -7, -9, 0, -3, -9], [0, -1, 0, -3, -4, -4, -6, -3, -8; 0, 0, -1,
+ 0, -1, -1, 1, -1, -5; 0, -2, -2, -1, -2, -3, -4, -2, -7; 0, -3, -4, -5, -7,
+ -9, -2, -4, -13; 0, -2, -3, -2, -4, -5, -1, -2, -7; 1, 5, 5, 4, 6, 9, 2, 4,
+ 14; 0, 0, 0, -1, -3, -2, 0, -1, -3; 0, 0, 0, 21, 21, 23, 7, 13, 35; 0, 0, 0
+, -5, -4, -5, -2, -3, -8], [0, -2, 6, -6, 0, -2, 0, -2, -4; 0, -1, 1, 0, -6,
+ -4, 0, -1, -4; 0, 0, 2, 0, 0, 0, 0, 0, 2; 0, -2, 10, 0, 0, 4, -6, -2, 0; 0,
+ -1, 5, 0, 0, 2, 0, -1, 0; 0, 0, -7, 0, 0, -3, 0, 0, -7; 1, -2, 5, 0, 0, 2, 
+0, 0, 0; 0, 7, -35, 0, 0, -14, 0, 1, 0; 0, 0, 7, 0, 0, 3, 0, 0, 1], [0, 0, 1
+, -3, -1, -2, 0, -1, -2; 0, 0, 0, 1, -1, 0, 1, 0, -1; 0, 0, 0, 1, 1, 1, 2, 1
+, 3; 0, 0, 1, 0, -1, 0, 4, 1, 4; 0, 0, 0, 0, 0, 0, 5, 1, 3; 0, 0, 0, 0, 0, 0
+, -7, -2, -7; 0, 0, 1, 0, -1, 0, 1, 0, 0; 1, -2, -9, 4, 6, 1, -5, 1, 0; 0, 1
+, 2, -1, -1, 0, 1, 0, 1], [0, 1, 2, -11, -4, -8, 2, -3, -6; 0, 0, 0, 4, -1, 
+2, 5, 1, 0; 0, 0, 0, 5, 4, 5, 8, 4, 11; 0, 1, 2, -1, -3, -1, 18, 4, 13; 0, 0
+, 0, 0, 0, 0, 21, 4, 10; 0, 0, 0, 0, 0, 0, -28, -7, -21; 0, 1, 2, -1, -3, -1
+, 4, 0, 0; 0, -14, -21, 21, 21, 12, -21, 3, 0; 1, 5, 5, -5, -4, -2, 4, 0, 3]
+], 0, [9, 3, 3, 0, 0, 3, 0, 3, 9]]
+norm(u): 1
+norm(t): 1
+trace(u): 1
+trace(t): 1
+u+t: 1
+u*t: 1
+u^3: 1
+w^-1 L: 1
+w^-1 R: 1
+w^-1*u: [Mod(0, x^3 - 21*x + 7), Mod(Mod(1, y), x^3 - 21*x + 7), Mod(0, x^3 
+- 21*x + 7)]~
+u*w^-1: [Mod(0, x^3 - 21*x + 7), Mod(Mod(1, y), x^3 - 21*x + 7), Mod(0, x^3 
+- 21*x + 7)]~
+charpol(w): Y^3 - 21*Y^2 + 1179*Y + 9447301/28
+eval charpol: 1
+trace(w): 1
+norm(w): 1
+dim: 1
+absdim: 1
+iscommutative: 1
+issemisimple: 1
+issimple: 1
+algmultable w+ww: 1
+algmultable w*ww: 1
+alg(basis(w)): 1
+alg(basis(ww)): 1
+basis(w)+ww: 1
+basis(w)-ww: 1
+w+basis(ww): 1
+w-basis(ww): 1
+basis(w)*ww: 1
+w*basis(ww): 1
+basis(w)^2: 1
+basis(ww)^2: 1
+basis(w)ww: 1
+wbasis(ww): 1
+basis(ww)w: 1
+wwbasis(w): 1
+basis(w)^-1: 1
+basis(ww)^-1: 1
+basis(w)/ww: 1
+w/basis(ww): 1
+basis(ww)/w: 1
+ww/basis(w): 1
+trace(basis(w)): 1
+trace(basis(ww)): 1
+alg(basis(w)) 2: 1
+alg(basis(ww)) 2: 1
+basis(w)+ww 2: 1
+basis(w)-ww 2: 1
+w+basis(ww) 2: 1
+w-basis(ww) 2: 1
+basis(w)*ww 2: 1
+w*basis(ww) 2: 1
+basis(w)^2 2: 1
+basis(ww)^2 2: 1
+basis(w)ww 2: 1
+wbasis(ww) 2: 1
+basis(ww)w 2: 1
+wwbasis(w) 2: 1
+basis(w)^-1 2: 1
+basis(ww)^-1 2: 1
+basis(w)/ww 2: 1
+w/basis(ww) 2: 1
+basis(ww)/w 2: 1
+ww/basis(w) 2: 1
+trace(basis(w)) 2: 1
+trace(basis(ww)) 2: 1
+alg(basis(w)) 3: 1
+alg(basis(ww)) 3: 1
+basis(w)+ww 3: 1
+basis(w)-ww 3: 1
+w+basis(ww) 3: 1
+w-basis(ww) 3: 1
+basis(w)*ww 3: 1
+w*basis(ww) 3: 1
+basis(w)^2 3: 1
+basis(ww)^2 3: 1
+basis(w)ww 3: 1
+wbasis(ww) 3: 1
+basis(ww)w 3: 1
+wwbasis(w) 3: 1
+basis(w)^-1 3: 1
+basis(ww)^-1 3: 1
+basis(w)/ww 3: 1
+w/basis(ww) 3: 1
+basis(ww)/w 3: 1
+ww/basis(w) 3: 1
+trace(basis(w)) 3: 1
+trace(basis(ww)) 3: 1
+radical: 1
+iscommutative cyc 3: 1
+issemisimple cyc 3: 1
+issimple cyc 3: 1
+algmultable/Q w+ww: 1
+algmultable/Q w*ww: 1
+alg(basis(w))/Q: 1
+alg(basis(ww))/Q: 1
+basis(w)+ww/Q: 1
+basis(w)-ww/Q: 1
+w+basis(ww)/Q: 1
+w-basis(ww)/Q: 1
+basis(w)*ww/Q: 1
+w*basis(ww)/Q: 1
+basis(w)^2/Q: 1
+basis(ww)^2/Q: 1
+basis(w)ww/Q: 1
+wbasis(ww)/Q: 1
+basis(ww)w/Q: 1
+wwbasis(w)/Q: 1
+basis(w)^-1/Q: 1
+basis(ww)^-1/Q: 1
+basis(w)/ww/Q: 1
+w/basis(ww)/Q: 1
+basis(ww)/w/Q: 1
+ww/basis(w)/Q: 1
+trace(basis(w))/Q: 1
+trace(basis(ww))/Q: 1
+radical/Q: 1
+iscommutative /Q: 1
+issemisimple /Q: 1
+issimple /Q: 1
+Suite: table algebra
+algisassociative 0.0: 1
+algisassociative 0.1: error("incorrect type in algisassociative (mult. table
+) (t_VEC).")
+algisassociative 0.2: 1
+algisassociative 0.3: error("incorrect type in algisassociative (mult. table
+) (t_POL).")
+construction 0: [0, 0, 0, 0, 0, 0, [1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 0, 0; 0,
+ 1, 0; 0, 0, 1], [[1, 0, 0; 0, 1, 0; 0, 0, 1], [0, 0, 0; 1, 0, 1; 0, 0, 0], 
+[0, 0, 0; 0, 0, 0; 1, 0, 1]], 0, [3, 0, 1]]
+iscyclic 0: 1
+dim 0: 1
+dim 0b: 1
+char 0: 1
+a+b 0: 1
+a-b 0: 1
+a*b 0: 1
+b*a 0: 1
+a^2 0: 1
+b^2 0: 1
+e^691691 0: 1
+d^101 0: 1
+multable(a) 0: 1
+multable(b) 0: 1
+divl(d,a) 0: 1
+divl(d,b) 0: 1
+d^-1 0: 1
+divr(a,d) 0: 1
+divr(b,d) 0: 1
+rad(al) 0: 1
+ss(al) 0: 1
+proj(a) idem 0: 1
+idemproj 0: [[0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 0, [1]], [0, 0, 0,
+ 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 0, [1]]]
+simple components 0: 1
+center al 0: 1
+center ss 0: 1
+primesubalg ss 0: error("domain error in algprimesubalg: characteristic = 0"
+)
+x^3 - 2*x^2 + x
+charpol annihil(a) 0: 1
+x^3 - x^2
+charpol annihil(b) 0: 1
+x^3
+charpol annihil(c) 0: 1
+x^3 - 4*x^2 + 5*x - 2
+charpol annihil(d) 0: 1
+x^3 - 3*x^2 + 3*x - 1
+charpol annihil(e) 0: 1
+random 0: [1, 0, 0]~
+algsimpledec 0: 1
+alg_decomposition 0: 1
+iscommutative 0: 1
+issemisimple 0: 1
+issimple 0: 1
+issimple ss 0: 1
+isdivision 0: 1
+algisassociative 2: 1
+construction 2: [0, 0, 0, 0, 0, 0, [1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 0, 0; 0,
+ 1, 0; 0, 0, 1], [[1, 0, 0; 0, 1, 0; 0, 0, 1], [0, 0, 0; 1, 0, 1; 0, 0, 0], 
+[0, 0, 0; 0, 0, 0; 1, 0, 1]], 2, [1, 0, 1]]
+iscyclic 2: 1
+dim 2: 1
+char 2: 1
+a+b 2: 1
+a-b 2: 1
+a*b 2: 1
+b*a 2: 1
+a^2 2: 1
+b^2 2: 1
+multable(a) 2: 1
+multable(b) 2: 1
+divl(un,a) 2: 1
+divl(un,b) 2: 1
+un^-1 2: 1
+divr(a,un) 2: 1
+divr(b,un) 2: 1
+rad(al) 2: 1
+ss(al) 2: 1
+proj(a) idem 2: 1
+idemproj 2: [[0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 2, [1]], [0, 0, 0,
+ 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 2, [1]]]
+simple components 2: 1
+center al 2: 1
+center ss 2: 1
+primesubalg ss 2: 1
+x^3 + x
+charpol annihil(a) 2: 1
+x^3 + x^2
+charpol annihil(b) 2: 1
+x^3
+charpol annihil(c) 2: 1
+random 2: [1, 0, 0]~
+algsimpledec 2: 1
+alg_decomposition 2: 1
+iscommutative 2: 1
+issemisimple 2: 1
+issimple 2: 1
+issimple ss 2: 1
+matrix trace 2: 1
+matrix norm 2: 1
+norm 2: 1
+construction 3: [0, 0, 0, 0, 0, 0, [1, 0; 0, 1], [1, 0; 0, 1], [[1, 0; 0, 1]
+, [0, 0; 1, 0]], 3, [2, 0]]
+iscyclic 3: 1
+dim 3: 1
+char 3: 1
+a+b 3: 1
+a-b 3: 1
+a*b 3: 1
+b*a 3: 1
+a^2 3: 1
+b^2 3: 1
+a^691691 3: 1
+multable(a) 3: 1
+multable(b) 3: 1
+algdivl(a,b) 3: 1
+a^-1 3: 1
+algdivr(b,a) 3: 1
+rad(al) 3: 1
+ss(al) 3: 1
+center al 3: 1
+center ss 3: 1
+primesubalg ss 3: 1
+x^2 + x + 1
+charpol annihil(a) 3: 1
+x^2
+charpol annihil(b) 3: 1
+random 3: [1, 0]~
+algsimpledec 3: 1
+alg_decomposition 3: 1
+iscommutative 3: 1
+issemisimple 3: 1
+issemisimple ss 3: 1
+issimple 3: 1
+issimple ss 3: 1
+construction 3c: [0, 0, 0, 0, 0, 0, [1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 0, 0; 0
+, 1, 0; 0, 0, 1], [[1, 0, 0; 0, 1, 0; 0, 0, 1], [0, 0, 0; 1, 0, 0; 0, 1, 0],
+ [0, 0, 0; 0, 0, 0; 1, 0, 0]], 3, [0, 0, 0]]
+iscyclic 3c: 1
+dim 3c: 1
+char 3c: 1
+a+b 3c: 1
+a-b 3c: 1
+a*b 3c: 1
+b*a 3c: 1
+a^2 3c: 1
+b^2 3c: 1
+a^691691 3c: 1
+multable(a) 3c: 1
+multable(b) 3c: 1
+algdivl(a,b) 3c: 1
+a^-1 3c: 1
+algdivr(b,a) 3c: 1
+rad(al) 3c: 1
+ss(al) 3c: 1
+center al 3c: 1
+center ss 3c: 1
+primesubalg ss 3c: 1
+x^3 + 2
+charpol annihil(a) 3c: 1
+x^3
+charpol annihil(b) 3c: 1
+random 3c: [1, 0, 0]~
+algsimpledec 3c: 1
+alg_decomposition 3c: 1
+iscommutative 3c: 1
+issemisimple 3c: 1
+issemisimple ss 3c: 1
+issimple 3c: 1
+issimple ss 3c: 1
+construction 2b: [0, 0, 0, 0, 0, 0, [1, 0; 0, 1], [1, 0; 0, 1], [[1, 0; 0, 1
+], [0, 1; 1, 1]], 2, [0, 1]]
+iscyclic 2b: 1
+dim 2b: 1
+char 2b: 1
+a+b 2b: 1
+a-b 2b: 1
+a*b 2b: 1
+b*a 2b: 1
+a^2 2b: 1
+b^2 2b: 1
+a^691691 2b: 1
+multable(a) 2b: 1
+multable(b) 2b: 1
+divl(a,b) 2b: 1
+a^-1 2b: 1
+divr(b,a) 2b: 1
+rad(al) 2b: 1
+center al 2b: 1
+primesubalg al 2b: 1
+x^2 + x + 1
+charpol annihil(a) 2b: 1
+x^2 + x + 1
+charpol annihil(b) 2b: 1
+random 2b: [1, 0]~
+algsimpledec 2b: 1
+alg_decomposition 2b: 1
+iscommutative 2b: 1
+issemisimple 2b: 1
+issimple 2b: 1
+issimple,1 2b: 1
+construction 3b: [0, 0, 0, 0, 0, 0, [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 
+0, 0, 1], [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [[1, 0, 0, 0; 0,
+ 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [0, 1, 0, 0; 1, 0, 0, 0; 0, 0, 1, 0; 0, 0
+, 0, 2], [0, 0, 0, 2; 0, 0, 0, 2; 1, 2, 0, 0; 0, 0, 0, 0], [0, 0, 2, 0; 0, 0
+, 1, 0; 0, 0, 0, 0; 1, 1, 0, 0]], 3, [1, 0, 0, 0]]
+iscyclic 3b: 1
+dim 3b: 1
+char 3b: 1
+a+b 3b: 1
+a-b 3b: 1
+a*b 3b: 1
+b*a 3b: 1
+a^2 3b: 1
+b^2 3b: 1
+a^691691 3b: 1
+b^691691 3b: 1
+multable(a) 3b: 1
+multable(b) 3b: 1
+divl(a,b) 3b: 1
+a^-1 3b: 1
+divr(b,a) 3b: 1
+rad(al) 3b: 1
+center al 3b: 1
+primesubalg al 3b: 1
+x^4 + x^2 + 1
+charpol annihil(a) 3b: 1
+x^4 + 2*x^3 + x^2
+charpol annihil(b) 3b: 1
+x^4
+charpol annihil(c) 3b: 1
+random 3b: [1, 0, 0, 1]~
+algsimpledec 3b: 1
+alg_decomposition 3b: 1
+iscommutative 3b: 1
+issemisimple 3b: 1
+issimple 3b: 1
+construction 2c: [0, 0, 0, 0, 0, 0, [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 
+0, 0, 1], [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [[1, 0, 0, 0; 0,
+ 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [0, 0, 1, 0; 1, 0, 0, 1; 0, 0, 0, 0; 0, 0
+, 1, 0], [0, 0, 0, 0; 0, 0, 0, 0; 1, 0, 0, 0; 0, 1, 0, 0], [0, 0, 0, 0; 0, 0
+, 0, 0; 0, 0, 1, 0; 1, 0, 0, 1]], 2, [0, 0, 0, 0]]
+iscyclic 2c: 1
+dim 2c: 1
+char 2c: 1
+a+b 2c: 1
+a-b 2c: 1
+a*b 2c: 1
+b*a 2c: 1
+a^2 2c: 1
+b^2 2c: 1
+a^691691 2c: 1
+b^691691 2c: 1
+c^691691 2c: 1
+multable(a) 2c: 1
+multable(b) 2c: 1
+divl(c,a) 2c: 1
+divl(c,b) 2c: 1
+c^-1 2c: 1
+divr(a,c) 2c: 1
+divr(b,c) 2c: 1
+rad(al) 2c: 1
+center al 2c: 1
+primesubalg al 2c: 1
+x^4
+charpol annihil(a) 2c: 1
+x^4 + x^2
+charpol annihil(b) 2c: 1
+x^4 + x^2 + 1
+charpol annihil(c) 2c: 1
+random 2c: [1, 0, 0, 1]~
+algsimpledec 2c: 1
+alg_decomposition 2c: 1
+iscommutative 2c: 1
+issemisimple 2c: 1
+issimple 2c: 1
+construction 5: [0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 5, [1]]
+iscyclic 5: 1
+dim 5: 1
+char 5: 1
+a+b 5: 1
+a-b 5: 1
+a*b 5: 1
+b*a 5: 1
+a^2 5: 1
+b^2 5: 1
+a^691691 5: 1
+multable(a) 5: 1
+multable(b) 5: 1
+divl(a,b) 5: 1
+a^-1 5: 1
+divr(a,b) 5: 1
+rad(al) 5: 1
+center al 5: 1
+primesubalg al 5: 1
+x + 3
+charpol annihil(a) 5: 1
+x + 2
+charpol annihil(b) 5: 1
+random 5: [1]~
+algsimpledec 5: 1
+alg_decomposition 5: 1
+iscommutative 5: 1
+issemisimple 5: 1
+issimple 5: 1
+construction 0b: [0, 0, 0, 0, 0, 0, [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], [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], [[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], [0, 0, 1, 0, 0; 1, 0, 0, 1, 0; 0, 0,
+ 0, 0, 0; 0, 0, -1, 0, 0; 0, 1, -1, -1, 1], [0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 1
+, 0, 0, 0, 0; 0, 1, 0, 0, 0; 0, 0, 0, 0, 0], [0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 
+0, 0, 1, 0, 0; 1, 0, 0, 1, 0; 0, 0, 0, 0, 0], [0, 0, 0, 0, 0; 0, 0, 0, 0, 0;
+ 0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 1, 1, 0, 0, 1]], 0, [5, 1, 0, 2, 1]]
+iscyclic 0b: 1
+dim 0b: 1
+char 0b: 1
+a+b 0b: 1
+a-b 0b: 1
+a*b 0b: 1
+b*a 0b: 1
+a^2 0b: 1
+b^2 0b: 1
+a^691691 0b: 1
+b^691 0b: 1
+multable(a) 0b: 1
+multable(b) 0b: 1
+divl(b,a) 0b: 1
+b^-1 0b: 1
+divr(a,b) 0b: 1
+rad(al) 0b: 1
+idemproj 0b: [[0, 0, 0, 0, 0, 0, [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 
+0, 1], [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [[1, 0, 0, 0; 0, 1,
+ 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [0, 0, 1, 0; 1, 0, 0, 1; 0, 0, 0, 0; 0, 0, -
+1, 0], [0, 0, 0, 0; 0, 0, 0, 0; 1, 0, 0, 0; 0, 1, 0, 0], [0, 0, 0, 0; 0, 0, 
+0, 0; 0, 0, 1, 0; 1, 0, 0, 1]], 0, [4, 0, 0, 2]], [0, 0, 0, 0, 0, 0, Mat(1),
+ Mat(1), [Mat(1)], 0, [1]]]
+simple components 0b: 1
+mt M2 component 0b: 1
+center al 0b: 1
+primesubalg al 0b: error("domain error in algprimesubalg: characteristic = 0
+")
+x^5 - 4*x^4 + 6*x^3 - 4*x^2 + x
+charpol annihil(a) 0b: 1
+x^5 - 6*x^4 + 14*x^3 - 16*x^2 + 9*x - 2
+charpol annihil(b) 0b: 1
+random 0b: [1, 0, 0, 1, 1]~
+algsimpledec 0b: 1
+alg_decomposition 0b: 1
+subalg M2(Q): 1
+iscommutative 0b: 1
+issemisimple 0b: 1
+issimple 0b: 1
+construction 3d: [0, 0, 0, 0, 0, 0, [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], [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], [[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], [0, 0, 1, 0, 0; 1, 0, 0, 1, 0; 0, 0,
+ 0, 0, 0; 0, 0, 2, 0, 0; 0, 1, 2, 2, 1], [0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 1, 0
+, 0, 0, 0; 0, 1, 0, 0, 0; 0, 0, 0, 0, 0], [0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 0, 
+0, 1, 0, 0; 1, 0, 0, 1, 0; 0, 0, 0, 0, 0], [0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 0,
+ 0, 0, 0, 0; 0, 0, 0, 0, 0; 1, 1, 0, 0, 1]], 3, [2, 1, 0, 2, 1]]
+iscyclic 3d: 1
+dim 3d: 1
+char 3d: 1
+a+b 3d: 1
+a-b 3d: 1
+a*b 3d: 1
+b*a 3d: 1
+a^2 3d: 1
+b^2 3d: 1
+a^691691 3d: 1
+b^691 3d: 1
+multable(a) 3d: 1
+multable(b) 3d: 1
+divl(b,a) 3d: 1
+b^-1 3d: 1
+divr(a,b) 3d: 1
+rad(al) 3d: 1
+idemproj 3d: [[0, 0, 0, 0, 0, 0, [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 
+0, 1], [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [[1, 0, 0, 0; 0, 1,
+ 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [0, 0, 1, 0; 1, 0, 0, 1; 0, 0, 0, 0; 0, 0, 2
+, 0], [0, 0, 0, 0; 0, 0, 0, 0; 1, 0, 0, 0; 0, 1, 0, 0], [0, 0, 0, 0; 0, 0, 0
+, 0; 0, 0, 1, 0; 1, 0, 0, 1]], 3, [1, 0, 0, 2]], [0, 0, 0, 0, 0, 0, Mat(1), 
+Mat(1), [Mat(1)], 3, [1]]]
+simple components 3d: 1
+mt M2 component 3d: 1
+center al 3d: 1
+primesubalg al 3d: 1
+x^5 + 2*x^4 + 2*x^2 + x
+charpol annihil(a) 3d: 1
+x^5 + 2*x^3 + 2*x^2 + 1
+charpol annihil(b) 3d: 1
+random 3d: [1, 0, 0, 1, 1]~
+algsimpledec 3d: 1
+alg_decomposition 3d: 1
+subalg M2(F3): 1
+iscommutative 3d: 1
+issemisimple 3d: 1
+issimple 3d: 1
+issimple,1 3d: 1
+maxorder assoc: 1
+natorder assoc: 1
+spl(1): 1
+spl(i): 1
+spl(j): 1
+spl(k): 1
+spl(basis(1)): 1
+spl(basis(i)): 1
+spl(basis(j)): 1
+spl(basis(k)): 1
+spl(a*1): 1
+spl(a*i): 1
+spl(a*j): 1
+spl(a*k): 1
+spl(b*1): 1
+spl(b*i): 1
+spl(b*j): 1
+spl(b*k): 1
+nattomax 1: 1
+nattomax 2: 1
+ord*invord=id: 1
+spl additive: 1
+spl multiplicative: 1
+changebasis bug 1: 1
+changebasis bug 2: 1
+changebasis bug 3: 1
+changebasis bug 4: 1
+algtableinit segfault bug: 
+1
+center of CSA: 1
+radical of CSA: 1
+decomposition of CSA: 1
+alg_decomposition of CSA: 1
+alsimple bug
+0
+tests for al_CSA: 
+1
+1
+should fail:
+  ***   at top-level: alfail=alginit(nf,[0,0],'x)
+  ***                        ^--------------------
+  *** alginit: domain error in idealfactor: ideal = 0
+  ***   at top-level: algb(al)
+  ***                 ^--------
+  *** algb: incorrect type in alg_get_b [non-cyclic algebra] (t_VEC).
+  ***   at top-level: algaut(al)
+  ***                 ^----------
+  *** algaut: incorrect type in alg_get_aut [non-cyclic algebra] (t_VEC).
+algebra:
+csa getcenter: 1
+csa getsplitting: 1
+getrelmultable: 1
+getsplittingdata:
+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
+hasse invariants:
+  ***   at top-level: print(alghassei(al)==0)
+  ***                       ^-----------------
+  *** alghassei: sorry, computation of Hasse invariants over table CSA is not yet implemented.
+  ***   at top-level: print(alghassef(al)==0)
+  ***                       ^-----------------
+  *** alghassef: sorry, computation of Hasse invariants over table CSA is not yet implemented.
+  ***   at top-level: print(alghasse(al,1)==0)
+  ***                       ^------------------
+  *** alghasse: sorry, computation of Hasse invariants over table CSA is not yet implemented.
+csa splitting pol: 1
+csa basis: 1
+csa invbasis: 1
+csa absdim: 1
+csa char: 1
+csa deg: 1
+csa dim: 1
+csa absdim: 1
+csa type: 1
+csa iscommutative: 1
+csa issemisimple: 1
+elements:
+[0, Mod(y, y^3 - y + 1), 0, 0]~
+[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]~
+csa add: 1
+csa neg: 1
+csa neg 2: 1
+csa sub: 1
+csa mul: 1
+csa mul 2: 1
+csa sqr: 1
+csa sqr 2: 1
+csa mt: 1
+csa inv: 1
+csa inv 2: 1
+csa divl: 1
+csa pow: 1
+csa mul 3: 1
+csa mul 4: 1
+csa pow 2: 1
+csa sub 2: 1
+csa sub 3: 1
+csa inv 3: 1
+csa inv 4: 1
+csa inv 5: 1
+csa trace: 1
+csa trace 2: 1
+1
+testcharpol
+1
+1
+1
+testcharpol2
+1
+1
+1
+testnorm
+1
+1
+1
+testnorm2
+1
+1
+1
+examples from docu
+0
+[2, 2]~
+0
+1
+[Mod(Mod(-1/3, y), x^2 + 1), Mod(Mod(2/3, y), x^2 + 1)]~
+0
+1
+1
+[Mod(-2/5*x - 1/5, x^2 + 1), 0]~
+[0, 2, -1, -1, 2, 0, 0, 0]~
+[Mod(Mod(y, y^2 - 5), x^2 - 2), 1]~
+[Mod(Mod(1/2*y - 1, y^2 - 5)*x + Mod(-1/4*y + 5/4, y^2 - 5), x^2 - 2), Mod(M
+od(-3/4*y + 7/4, y^2 - 5), x^2 - 2)]~
+[0, 1, 0, 0, 2, -3, 0, 0]~
+[[0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 2, [1]], [0, 0, 0, 0, 0, 0, [1
+, 0; 0, 1], [1, 0; 0, 1], [[1, 0; 0, 1], [0, 1; 1, 1]], 2, [0, 1]]]
+
+[1 0]
+
+[0 1]
+
+[0 0]
+
+[0, 0, 0, 0, 0, 0, [1, 0; 0, 1], [1, 0; 0, 1], [[1, 0; 0, 1], [0, 1; 1, 1]],
+ 2, [0, 1]]
+[0, 0, 0, 0, 0, 0, [1, 0; 0, 1], [1, 0; 0, 1], [[1, 0; 0, 1], [0, 1; 1, 1]],
+ 2, [0, 1]]
+1
+0
+0
+0
+0
+1
+[[[2, [2, 0]~, 1, 2, 1], [3, [3, 0]~, 1, 2, 1]], Vecsmall([0, 1])]
+12960000
+12960000
+12
+y^3 - y + 1
+2
+4
+-1/3*x^2 + 1/3*x + 26/3
+Mod(-77, y)
+13
+1
+[[[19, [10, 2]~, 1, 1, [-8, 2; 2, -10]], [2, [2, 0]~, 1, 2, 1]], Vecsmall([1
+, 0])]
+Vecsmall([1, 0])
+1/2
+0
+1/2
+0
+  ***   at top-level: algindex(1,1)
+  ***                 ^-------------
+  *** algindex: incorrect type in checkalg [please apply alginit()] (t_INT).
+2
+1
+2
+1
+2
+1
+0
+1
+0
+1
+0
+1
+0
+1
+0
+1
+0
+1
+0
+1
+[1, [2, [2, 0]~, 1, 2, 1]]
+x^2 + Mod(-3/2*y + 13/2, y^2 - 5)
+
+[1 0 0 -1]
+
+[0 1 0 -1]
+
+[0 0 1 -1]
+
+[0 0 0  2]
+
+
+[1 0 0 1/2]
+
+[0 1 0 1/2]
+
+[0 0 1 1/2]
+
+[0 0 0 1/2]
+
+[[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [0, -1, 1, 0; 1, 0, 1, 1;
+ 0, 0, 1, 1; 0, 0, -2, -1], [0, -1, -1, -1; 0, -1, 0, -1; 1, -1, 0, 0; 0, 2,
+ 0, 1], [0, -1, 0, -1; 0, 0, 1, 0; 0, -1, 1, 0; 1, 1, -1, 1]]
+[1/2, -1/2, 0, 0]~
+[2, 3, 5, -4]~
+
+[0 -1  1  0]
+
+[1  0  1  1]
+
+[0  0  1  1]
+
+[0  0 -2 -1]
+
+[-1, -1, 0, 0]~
+
+[Mod(x + 1, x^2 + 1) Mod(Mod(1, y)*x + Mod(-1, y), x^2 + 1)]
+
+[Mod(x + 1, x^2 + 1)                   Mod(-x + 1, x^2 + 1)]
+
+[8, -8, 0, 0]~
+[0, 1, -1, 0]~
+11
+3
+[[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [0, y, 0, 0; 1, 0, 0, 0; 
+0, 0, 0, y; 0, 0, 1, 0], [0, 0, y^2, 0; 0, 0, 0, -y^2; 1, 0, 0, 0; 0, -1, 0,
+ 0], [0, 0, 0, -y^3; 0, 0, y^2, 0; 0, -y, 0, 0; 1, 0, 0, 0]]
+x^2 - y
+[[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]~, [1, 0; 0, -4; 0, 0; 0, 0; 0, 0; 0, 0
+; 0, 1; 0, 0; 0, 0; 0, 0; 0, 0; 0, 0], [Mod(1, x^6 - 5), Mod(x^2, x^6 - 5), 
+Mod(x^4, x^6 - 5), Mod(x, x^6 - 5), Mod(x^3, x^6 - 5), Mod(1/2*x^5 + 1/2*x^4
+ + 1/2*x^3 + 1/2*x^2 + 1/2*x + 1/2, x^6 - 5), Mod(4*x^2, x^6 - 5), Mod(5/2*x
+^4 + 5/2*x^2, x^6 - 5), Mod(5/2*x^2 + 5/2, x^6 - 5), Mod(-3/2*x^3 + 21/2, x^
+6 - 5), Mod(1/2*x^4 + 1/2*x^3 + 3*x^2 + 1/2*x + 1/2, x^6 - 5), Mod(5/2*x^4 +
+ 5*x^2 - 3/2*x, x^6 - 5); Mod(0, x^6 - 5), Mod(0, x^6 - 5), Mod(0, x^6 - 5),
+ Mod(0, x^6 - 5), Mod(0, x^6 - 5), Mod(0, x^6 - 5), Mod(1, x^6 - 5), Mod(1/2
+*x^2 + 1/2, x^6 - 5), Mod(1/10*x^4 + 1/2, x^6 - 5), Mod(1/2*x^4 - 1/2*x, x^6
+ - 5), Mod(-1/10*x^3 + 1/2, x^6 - 5), Mod(-1/10*x^5 + 1/2*x^2 + 1, x^6 - 5)]
+]
+2
+18
+18
+1
+1
+1
+2
+x^3 - 21*x + 7
+matrices over algebras
+
+[[2, 2, 2, 0, -2, -2, -1, 1]~  [0, -1, -2, -1, 1, 1, 2, 0]~]
+
+[[-2, 2, 1, 2, 2, 2, -2, -2]~ [0, -2, 2, -1, 2, -2, 0, -2]~]
+
+
+[ [2, 0, 2, 0, -2, 0, 2, -1]~ [0, -2, -2, -1, -1, 0, 2, 0]~]
+
+[[-2, -1, 1, 1, -1, 0, 2, 0]~    [2, 0, 1, 0, 1, 2, -2, 1]~]
+
+mul alM: [[31, -29, 30, -19, 62, 60, -111, 61]~, [3, -75, -9, -50, -19, 17, 
+-54, 97]~; [29, -1, 2, -7, 6, 20, -27, -2]~, [26, 28, 22, 21, 4, -5, 6, -32]
+~]
+sqr alM: 1
+divl alM: 1
+divr alM: 1
+isinv alM: 1
+isinv alM 2: 1
+inv alM: 1
+inv alM 2: 1
+neg alM: 1
+sub alM: 1
+add alM: 1
+algtobasis basistoalg alM 1: 1
+algtobasis basistoalg alM 2: 1
+algmultable add alM: 1
+algmultable mul alM: 1
+algmultable sqr alM: 1
+algsplitm add alM: 1
+algsplitm mul alM: 1
+algsplitm sqr alM: 1
+algsplitm sqr alM 2: 1
+algtrace alM: 1
+algtrace alM 2: 1
+algtrace prod alM: 1
+algnorm alM: 1
+algnorm alM 2: 1
+algcharpoly alM: 1
+algcharpoly alM 2: 1
+pow alM: 1
+pow alM 2: 1
+pow 0 alM: 1
+
+[[Mod(Mod(1/4*y + 5/4, y^2 - 5)*x + Mod(y - 3/2, y^2 - 5), x^2 + 1), Mod(Mod
+(1/28*y - 5/4, y^2 - 5)*x - 33/14, x^2 + 1)]~ [Mod(Mod(-1/2*y + 1, y^2 - 5)*
+x + Mod(-1/2*y + 9/2, y^2 - 5), x^2 + 1), Mod(17/14*x + Mod(1/14*y + 5/2, y^
+2 - 5), x^2 + 1)]~]
+
+[[Mod(Mod(1/2*y - 1/2, y^2 - 5)*x + Mod(-1/2*y - 9/2, y^2 - 5), x^2 + 1), Mo
+d(Mod(-1/14*y + 1/14, y^2 - 5)*x + Mod(-1/7*y - 2/7, y^2 - 5), x^2 + 1)]~ [M
+od(Mod(-y - 4, y^2 - 5)*x + Mod(1/2*y - 5/2, y^2 - 5), x^2 + 1), Mod(Mod(-1/
+14*y - 17/14, y^2 - 5)*x + Mod(-1/14*y - 11/14, y^2 - 5), x^2 + 1)]~]
+
+
+[[Mod(Mod(-1/4*y + 1/4, y^2 - 5)*x + Mod(5/4*y + 7/4, y^2 - 5), x^2 + 1), Mo
+d(Mod(-1/28*y + 17/28, y^2 - 5)*x + Mod(1/28*y + 3/28, y^2 - 5), x^2 + 1)]~ 
+[Mod(Mod(-1/2*y - 1/2, y^2 - 5)*x + Mod(-1/2*y + 3, y^2 - 5), x^2 + 1), Mod(
+5/7*x + Mod(1/14*y + 1, y^2 - 5), x^2 + 1)]~]
+
+[[Mod(Mod(1/2*y - 1/2, y^2 - 5)*x + Mod(y - 1/2, y^2 - 5), x^2 + 1), Mod(5/7
+*x + Mod(1/14*y + 1, y^2 - 5), x^2 + 1)]~ [Mod(Mod(1/4*y + 3/4, y^2 - 5)*x +
+ Mod(1/4*y + 5/4, y^2 - 5), x^2 + 1), Mod(Mod(1/28*y + 11/28, y^2 - 5)*x + M
+od(-1/28*y + 11/28, y^2 - 5), x^2 + 1)]~]
+
+mul scalar alM: 1
+
+[    [0, 0, 1, 0]~    [1, 1, 0, 2]~]
+
+[[-1, -2, -1, -1]~ [-1, -1, 0, -2]~]
+
+
+[[-1, -1, 1, 0]~  [2, 2, 0, 0]~]
+
+[[2, -2, 2, -1]~ [-1, 2, 1, 2]~]
+
+mul alM t: [[5, -4, -2, 6]~, [-7, -1, 5, -1]~; [-6, 8, 2, -7]~, [9, -5, -7, 
+-1]~]
+sqr alM t: 1
+divl alM t: 1
+divr alM t: 1
+isinv alM t: 1
+isinv alM t 2: 1
+inv alM t: 1
+inv alM t 2: 1
+neg alM t: 1
+sub alM t: 1
+add alM t: 1
+algmultable add alM t: 1
+algmultable mul alM t: 1
+algmultable sqr alM t: 1
+algtrace alM t: 1
+algtrace alM t 2: 1
+algtrace prod alM t: 1
+algnorm alM t: 1
+algnorm alM t 2: 1
+algcharpoly alM t: 1
+algcharpoly alM t 2: 1
+pow alM t: 1
+pow alM 2 t: 1
+pow 0 alM t: 1
+csa al2
+al2 contains nfabs: 1
+[[x^2 + (-2*y^2 + 2*y)*x + (6*y^2 - 5*y + 5), [[292133, -1964*x^5 + 4725*x^4
+ - 14044*x^3 - 95698*x^2 - 164828*x - 456632, -1406*x^5 + 4870*x^4 - 7674*x^
+3 - 64939*x^2 - 119188*x + 52103], 1/292133], [[412, 92, 376; 0, 4, 0; 0, 0,
+ 4], [-7, -4, 2]~], 1, [], [], [[1, x], [1, 1]], [1, 0; 0, 1], 1, [y^3 - y +
+ 1, [1, 1], -23, 1, [[1, 0.75487766624669276004950889635852869189, -1.324717
+9572447460259609088544780973407; 1, -0.8774388331233463800247544481792643459
+5 + 0.74486176661974423659317042860439236724*I, 0.66235897862237301298045442
+723904867037 + 0.56227951206230124389918214490937306150*I], [1, 0.7548776662
+4669276004950889635852869189, -1.3247179572447460259609088544780973407; 1, -
+0.13257706650360214343158401957487197871, 1.22463849068467425687963657214842
+17319; 1, -1.6223005997430906166179248767836567132, 0.1000794665600717690812
+7228232967560887], [1, 1, -1; 1, 0, 1; 1, -2, 0], [3, -1, 0; -1, 1, -3; 0, -
+3, 2], [23, 16, 10; 0, 1, 0; 0, 0, 1], [7, -2, -3; -2, -6, -9; -3, -9, -2], 
+[23, [-10, -1, 8; -7, -3, 1; 1, 7, -10]], [23]], [-1.32471795724474602596090
+88544780973407, 0.66235897862237301298045442723904867037 + 0.562279512062301
+24389918214490937306150*I], [1, y^2 - 1, y], [1, 0, 1; 0, 0, 1; 0, 1, 0], [1
+, 0, 0, 0, 0, -1, 0, -1, 1; 0, 1, 0, 1, -1, 0, 0, 0, 1; 0, 0, 1, 0, -1, 0, 1
+, 0, 0]], [x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191, -1406/29213
+3*x^5 + 4870/292133*x^4 - 7674/292133*x^3 - 64939/292133*x^2 - 119188/292133
+*x + 52103/292133, 0, y^3 - y + 1, x^2 + (-2*y^2 + 2*y)*x + (6*y^2 - 5*y + 5
+)], [0]], [[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [0, 0, 1, 0; 1,
+ 0, 0, 1; 0, 0, 0, 0; 0, 0, -1, 0], [0, 0, 0, 0; 0, 0, 0, 0; 1, 0, 0, 0; 0, 
+1, 0, 0], [0, 0, 0, 0; 0, 0, 0, 0; 0, 0, 1, 0; 1, 0, 0, 1]], [[0, 1, -1, -1,
+ -2, 2, 0, 0, -2, 2, 0, 0]~, [1, 0; 0, 0; 0, 0; 0, 0; 0, 0; 0, 0; 0, 1; 0, 0
+; 0, 0; 0, 0; 0, 0; 0, 0], [Mod(1, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 +
+ 36*x + 191), Mod(-1964/292133*x^5 + 4725/292133*x^4 - 14044/292133*x^3 - 95
+698/292133*x^2 - 164828/292133*x - 456632/292133, x^6 - 4*x^5 + 15*x^4 + 14*
+x^3 + 120*x^2 + 36*x + 191), Mod(-1406/292133*x^5 + 4870/292133*x^4 - 7674/2
+92133*x^3 - 64939/292133*x^2 - 119188/292133*x + 52103/292133, x^6 - 4*x^5 +
+ 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), Mod(-516/6719059*x^5 + 59549/67190
+59*x^4 - 144104/6719059*x^3 + 56369/6719059*x^2 + 2656099/6719059*x + 556383
+1/6719059, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), Mod(-54291
+/6719059*x^5 + 210489/6719059*x^4 - 786258/6719059*x^3 - 905381/6719059*x^2 
+- 6840464/6719059*x - 4510816/6719059, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x
+^2 + 36*x + 191), Mod(-48132/6719059*x^5 + 241931/6719059*x^4 - 785055/67190
+59*x^3 - 523468/6719059*x^2 - 1628025/6719059*x + 4121552/6719059, x^6 - 4*x
+^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), Mod(0, x^6 - 4*x^5 + 15*x^4 + 
+14*x^3 + 120*x^2 + 36*x + 191), Mod(0, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x
+^2 + 36*x + 191), Mod(0, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 19
+1), Mod(0, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), Mod(0, x^6
+ - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), Mod(0, x^6 - 4*x^5 + 15*
+x^4 + 14*x^3 + 120*x^2 + 36*x + 191); Mod(0, x^6 - 4*x^5 + 15*x^4 + 14*x^3 +
+ 120*x^2 + 36*x + 191), Mod(0, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*
+x + 191), Mod(0, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), Mod(
+-499864/154538357*x^5 - 232506/154538357*x^4 + 2075504/154538357*x^3 - 39252
+216/154538357*x^2 - 107292314/154538357*x - 129681996/154538357, x^6 - 4*x^5
+ + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), Mod(1153778/154538357*x^5 - 4109
+402/154538357*x^4 + 13244560/154538357*x^3 + 24564582/154538357*x^2 + 151883
+496/154538357*x - 10149974/154538357, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^
+2 + 36*x + 191), Mod(171940/154538357*x^5 - 3019052/154538357*x^4 + 13537158
+/154538357*x^3 - 30710744/154538357*x^2 - 25903390/154538357*x - 175396598/1
+54538357, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), Mod(1, x^6 
+- 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), Mod(-1964/292133*x^5 + 47
+25/292133*x^4 - 14044/292133*x^3 - 95698/292133*x^2 - 164828/292133*x - 4566
+32/292133, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), Mod(-1406/
+292133*x^5 + 4870/292133*x^4 - 7674/292133*x^3 - 64939/292133*x^2 - 119188/2
+92133*x + 52103/292133, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191
+), Mod(-516/6719059*x^5 + 59549/6719059*x^4 - 144104/6719059*x^3 + 56369/671
+9059*x^2 + 2656099/6719059*x + 5563831/6719059, x^6 - 4*x^5 + 15*x^4 + 14*x^
+3 + 120*x^2 + 36*x + 191), Mod(-54291/6719059*x^5 + 210489/6719059*x^4 - 786
+258/6719059*x^3 - 905381/6719059*x^2 - 6840464/6719059*x - 4510816/6719059, 
+x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), Mod(-48132/6719059*x^
+5 + 241931/6719059*x^4 - 785055/6719059*x^3 - 523468/6719059*x^2 - 1628025/6
+719059*x + 4121552/6719059, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x +
+ 191)]], 0, 0, 0, [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0
+, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 
+0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1
+, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 
+0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0
+, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [[1, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0
+, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 
+0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, -1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0,
+ 0, -1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -
+1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0; 0, 0, 0, 0, 0, 
+0, 1, -1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, -1; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0; 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, -1, 0], [0, -1, 1, 0, 0, 0, 0, 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, 0, 0, 0, 0; 0, 0, 0, 0, -1, 1, 0, 0
+, 0, 0, 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, 0; 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0; 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, -1,
+ 1; 0, 0, 0, 0, 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, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0; 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 1, 
+0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1; 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0,
+ 0, -1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0], [0, 0, 0, 0, 0, 0,
+ 0, 0, -1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0
+, -1, 0, 0, 0, 0; 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1; 1, -1, 0, 0, 0, 0, 0
+, 0, 0, 1, -1, 0; 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0; 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, -1, 1, 0, 
+0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, -1, 1, 0
+, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0; 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, -1, 1; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1
+; 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 
+0, 0, 0, 0, 0, 1, -1, 0, 0, 0; 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0
+, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 
+0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0; 0, 0, 0
+, 1, -1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 1, 0, 0, 0, 
+0, 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
+, 0, 0, 0, 0; 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 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, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 
+0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 1, 0, 0
+, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, -1,
+ 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0; 0, 0, -1, 0, 0, 0, 0, 0, 0
+, 0, 0, -1; 1, -1, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0; 0, -1, 0, 0, 0, 0, 0, 0, 0
+, 0, -1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+; 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 0
+, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, -1, 1; 0, 
+0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]], 0, [1
+2, -4, 0, 0, 0, 0, 0, 0, 0, 6, -2, 0]]
+csa al3
+al3 contains nfabs: 1
+[[x^3 + (3*y^2 - 4)*x^2 + (-5*y^2 - 2*y + 4)*x + (2*y^2 + 3*y - 1), [[175, 8
+8*x^8 - 401*x^7 + 384*x^6 + 1285*x^5 - 2326*x^4 + 1534*x^3 - 1207*x^2 - 275*
+x + 1004, -161*x^8 + 762*x^7 - 793*x^6 - 2355*x^5 + 4657*x^4 - 2938*x^3 + 24
+39*x^2 + 80*x - 2218], 1/175], [[351425, 326042, 160047; 0, 1, 0; 0, 0, 1], 
+[44, -37, -41]~], 1, [], [], [[1, x, x^2], [1, 1, 1]], [1, 0, 0; 0, 1, 0; 0,
+ 0, 1], 1, [y^3 - y + 1, [1, 1], -23, 1, [[1, 0.7548776662466927600495088963
+5852869189, -1.3247179572447460259609088544780973407; 1, -0.8774388331233463
+8002475444817926434595 + 0.74486176661974423659317042860439236724*I, 0.66235
+897862237301298045442723904867037 + 0.56227951206230124389918214490937306150
+*I], [1, 0.75487766624669276004950889635852869189, -1.3247179572447460259609
+088544780973407; 1, -0.13257706650360214343158401957487197871, 1.22463849068
+46742568796365721484217319; 1, -1.6223005997430906166179248767836567132, 0.1
+0007946656007176908127228232967560887], [1, 1, -1; 1, 0, 1; 1, -2, 0], [3, -
+1, 0; -1, 1, -3; 0, -3, 2], [23, 16, 10; 0, 1, 0; 0, 0, 1], [7, -2, -3; -2, 
+-6, -9; -3, -9, -2], [23, [-10, -1, 8; -7, -3, 1; 1, 7, -10]], [23]], [-1.32
+47179572447460259609088544780973407, 0.6623589786223730129804544272390486703
+7 + 0.56227951206230124389918214490937306150*I], [1, y^2 - 1, y], [1, 0, 1; 
+0, 0, 1; 0, 1, 0], [1, 0, 0, 0, 0, -1, 0, -1, 1; 0, 1, 0, 1, -1, 0, 0, 0, 1;
+ 0, 0, 1, 0, -1, 0, 1, 0, 0]], [x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x
+^4 - 41*x^3 + 21*x^2 + 13*x - 17, -23/25*x^8 + 762/175*x^7 - 793/175*x^6 - 4
+71/35*x^5 + 4657/175*x^4 - 2938/175*x^3 + 2439/175*x^2 + 16/35*x - 2218/175,
+ 0, y^3 - y + 1, x^3 + (3*y^2 - 4)*x^2 + (-5*y^2 - 2*y + 4)*x + (2*y^2 + 3*y
+ - 1)], [0]], [[1, 0, 0, 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, 0, 0, 1, 0, 0, 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, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1,
+ 0; 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 1, 0, 0, 0, 0, 0; 1, 0, 0, 0, 1, 0
+, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, -1
+, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0,
+ 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, -1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 
+0; 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
+, 0, 0; 0, 0, 0, 0, 0, 0, -1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0
+, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, -1, 0, 0], [0, 0,
+ 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 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; 0, 0, 1, 0, 0, 0, 0, 0
+, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0,
+ 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0
+, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0; 1, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0,
+ 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0; 
+0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0,
+ 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0; 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, 0, 0; 0, 0, 0, 0
+, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 
+0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0
+; 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 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; 0, 0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0
+, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0,
+ 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 
+0, 0, 1, 0, 0, 0, 0, 0; 1, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0
+], [0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 
+0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0
+, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0; 1, 0, 0,
+ 0, 0, 0, 0, 0, 1]], [[0, -1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0
+, 0, 0, 1, 0, 1, 0, 0, 0, 0]~, [1, 0, 0; 0, 0, 0; 0, 0, 0; 0, 0, 0; 0, 0, 0;
+ 0, 0, 0; 0, 0, 0; 0, 0, 0; 0, 0, 0; 0, 1, 0; 0, 0, 0; 0, 0, 0; 0, 0, 0; 0, 
+0, 0; 0, 0, 0; 0, 0, 0; 0, 0, 0; 0, 0, 0; 0, 0, 1; 0, 0, 0; 0, 0, 0; 0, 0, 0
+; 0, 0, 0; 0, 0, 0; 0, 0, 0; 0, 0, 0; 0, 0, 0], [Mod(1, x^9 - 6*x^8 + 11*x^7
+ + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(88/175*x^8 - 
+401/175*x^7 + 384/175*x^6 + 257/35*x^5 - 2326/175*x^4 + 1534/175*x^3 - 1207/
+175*x^2 - 11/7*x + 1004/175, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 
+- 41*x^3 + 21*x^2 + 13*x - 17), Mod(-23/25*x^8 + 762/175*x^7 - 793/175*x^6 -
+ 471/35*x^5 + 4657/175*x^4 - 2938/175*x^3 + 2439/175*x^2 + 16/35*x - 2218/17
+5, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x -
+ 17), Mod(-239/175*x^8 + 1128/175*x^7 - 1187/175*x^6 - 681/35*x^5 + 6793/175
+*x^4 - 4672/175*x^3 + 4096/175*x^2 - 38/35*x - 3027/175, x^9 - 6*x^8 + 11*x^
+7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(-14/25*x^8 +
+ 481/175*x^7 - 564/175*x^6 - 54/7*x^5 + 3091/175*x^4 - 2264/175*x^3 + 1812/1
+75*x^2 - 52/35*x - 1384/175, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 
+- 41*x^3 + 21*x^2 + 13*x - 17), Mod(173/175*x^8 - 816/175*x^7 + 869/175*x^6 
++ 488/35*x^5 - 4931/175*x^4 + 3499/175*x^3 - 2927/175*x^2 + 48/35*x + 297/25
+, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 
+17), Mod(-8/7*x^8 + 27/5*x^7 - 198/35*x^6 - 576/35*x^5 + 229/7*x^4 - 761/35*
+x^3 + 671/35*x^2 - 11/35*x - 542/35, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 +
+ 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(-4/175*x^8 + 33/175*x^7 - 11/25*
+x^6 - 6/35*x^5 + 353/175*x^4 - 51/25*x^3 + 106/175*x^2 - 2/5*x - 202/175, x^
+9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17),
+ Mod(88/175*x^8 - 401/175*x^7 + 384/175*x^6 + 257/35*x^5 - 2326/175*x^4 + 15
+34/175*x^3 - 1207/175*x^2 - 4/7*x + 1004/175, x^9 - 6*x^8 + 11*x^7 + 8*x^6 -
+ 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 + 11*x^7
+ + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^
+8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, 
+x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17
+), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 +
+ 13*x - 17), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 
++ 21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4
+ - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^
+5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x
+^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 + 11
+*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 
+6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod
+(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x 
+- 17), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x
+^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*
+x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56
+*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 4
+7*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 + 11*x^7 +
+ 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 
++ 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^
+9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17);
+ Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 1
+3*x - 17), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 
+21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 -
+ 41*x^3 + 21*x^2 + 13*x - 17), Mod(-346/175*x^8 + 1627/175*x^7 - 1678/175*x^
+6 - 1007/35*x^5 + 9837/175*x^4 - 6428/175*x^3 + 5309/175*x^2 + 33/35*x - 481
+8/175, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13
+*x - 17), Mod(-349/175*x^8 + 1628/175*x^7 - 236/25*x^6 - 202/7*x^5 + 9738/17
+5*x^4 - 921/25*x^3 + 5381/175*x^2 + 9/5*x - 4622/175, x^9 - 6*x^8 + 11*x^7 +
+ 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(596/175*x^8 - 4
+01/25*x^7 + 2918/175*x^6 + 1726/35*x^5 - 17057/175*x^4 + 11208/175*x^3 - 927
+9/175*x^2 - 11/7*x + 8178/175, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^
+4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(-26/25*x^8 + 849/175*x^7 - 871/175*x^6
+ - 521/35*x^5 + 5064/175*x^4 - 3441/175*x^3 + 2913/175*x^2 - 18/35*x - 2361/
+175, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x
+ - 17), Mod(-279/175*x^8 + 1313/175*x^7 - 196/25*x^6 - 160/7*x^5 + 7918/175*
+x^4 - 771/25*x^3 + 4576/175*x^2 + 2/5*x - 3607/175, x^9 - 6*x^8 + 11*x^7 + 8
+*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(404/175*x^8 - 192
+3/175*x^7 + 2057/175*x^6 + 1158/35*x^5 - 11803/175*x^4 + 7967/175*x^3 - 6641
+/175*x^2 + 36/35*x + 5447/175, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^
+4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(1, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x
+^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(88/175*x^8 - 401/175*x^7 + 3
+84/175*x^6 + 257/35*x^5 - 2326/175*x^4 + 1534/175*x^3 - 1207/175*x^2 - 11/7*
+x + 1004/175, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x
+^2 + 13*x - 17), Mod(-23/25*x^8 + 762/175*x^7 - 793/175*x^6 - 471/35*x^5 + 4
+657/175*x^4 - 2938/175*x^3 + 2439/175*x^2 + 16/35*x - 2218/175, x^9 - 6*x^8 
++ 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(-239/
+175*x^8 + 1128/175*x^7 - 1187/175*x^6 - 681/35*x^5 + 6793/175*x^4 - 4672/175
+*x^3 + 4096/175*x^2 - 38/35*x - 3027/175, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*
+x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(-14/25*x^8 + 481/175*x^7 - 
+564/175*x^6 - 54/7*x^5 + 3091/175*x^4 - 2264/175*x^3 + 1812/175*x^2 - 52/35*
+x - 1384/175, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x
+^2 + 13*x - 17), Mod(173/175*x^8 - 816/175*x^7 + 869/175*x^6 + 488/35*x^5 - 
+4931/175*x^4 + 3499/175*x^3 - 2927/175*x^2 + 48/35*x + 297/25, x^9 - 6*x^8 +
+ 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(-8/7*x
+^8 + 27/5*x^7 - 198/35*x^6 - 576/35*x^5 + 229/7*x^4 - 761/35*x^3 + 671/35*x^
+2 - 11/35*x - 542/35, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^
+3 + 21*x^2 + 13*x - 17), Mod(-4/175*x^8 + 33/175*x^7 - 11/25*x^6 - 6/35*x^5 
++ 353/175*x^4 - 51/25*x^3 + 106/175*x^2 - 2/5*x - 202/175, x^9 - 6*x^8 + 11*
+x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(88/175*x^8
+ - 401/175*x^7 + 384/175*x^6 + 257/35*x^5 - 2326/175*x^4 + 1534/175*x^3 - 12
+07/175*x^2 - 4/7*x + 1004/175, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^
+4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x
+^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*
+x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 + 1
+1*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 -
+ 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mo
+d(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x
+ - 17), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*
+x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41
+*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 5
+6*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 
+47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17); Mod(0, x^9 - 6*x^8 + 11*x^7 
++ 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8
+ + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x
+^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17)
+, Mod(-26/25*x^8 + 849/175*x^7 - 871/175*x^6 - 521/35*x^5 + 5064/175*x^4 - 3
+441/175*x^3 + 2913/175*x^2 - 18/35*x - 2361/175, x^9 - 6*x^8 + 11*x^7 + 8*x^
+6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(-279/175*x^8 + 1313/
+175*x^7 - 196/25*x^6 - 160/7*x^5 + 7918/175*x^4 - 771/25*x^3 + 4576/175*x^2 
++ 2/5*x - 3607/175, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 
++ 21*x^2 + 13*x - 17), Mod(404/175*x^8 - 1923/175*x^7 + 2057/175*x^6 + 1158/
+35*x^5 - 11803/175*x^4 + 7967/175*x^3 - 6641/175*x^2 + 36/35*x + 5447/175, x
+^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17)
+, Mod(-3/7*x^8 + 67/35*x^7 - 61/35*x^6 - 218/35*x^5 + 368/35*x^4 - 247/35*x^
+3 + 223/35*x^2 + 4/35*x - 174/35, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56
+*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(-36/25*x^8 + 1194/175*x^7 - 1266/17
+5*x^6 - 144/7*x^5 + 7279/175*x^4 - 4971/175*x^3 + 4188/175*x^2 + 13/35*x - 3
+336/175, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 
+13*x - 17), Mod(37/25*x^8 - 1243/175*x^7 + 1357/175*x^6 + 741/35*x^5 - 7748/
+175*x^4 + 5202/175*x^3 - 4251/175*x^2 + 36/35*x + 3602/175, x^9 - 6*x^8 + 11
+*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 
+6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod
+(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x 
+- 17), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x
+^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*
+x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56
+*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 4
+7*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 + 11*x^7 +
+ 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^9 - 6*x^8 
++ 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(0, x^
+9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17),
+ Mod(1, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 1
+3*x - 17), Mod(88/175*x^8 - 401/175*x^7 + 384/175*x^6 + 257/35*x^5 - 2326/17
+5*x^4 + 1534/175*x^3 - 1207/175*x^2 - 11/7*x + 1004/175, x^9 - 6*x^8 + 11*x^
+7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(-23/25*x^8 +
+ 762/175*x^7 - 793/175*x^6 - 471/35*x^5 + 4657/175*x^4 - 2938/175*x^3 + 2439
+/175*x^2 + 16/35*x - 2218/175, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^
+4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(-239/175*x^8 + 1128/175*x^7 - 1187/175
+*x^6 - 681/35*x^5 + 6793/175*x^4 - 4672/175*x^3 + 4096/175*x^2 - 38/35*x - 3
+027/175, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 
+13*x - 17), Mod(-14/25*x^8 + 481/175*x^7 - 564/175*x^6 - 54/7*x^5 + 3091/175
+*x^4 - 2264/175*x^3 + 1812/175*x^2 - 52/35*x - 1384/175, x^9 - 6*x^8 + 11*x^
+7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(173/175*x^8 
+- 816/175*x^7 + 869/175*x^6 + 488/35*x^5 - 4931/175*x^4 + 3499/175*x^3 - 292
+7/175*x^2 + 48/35*x + 297/25, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4
+ - 41*x^3 + 21*x^2 + 13*x - 17), Mod(-8/7*x^8 + 27/5*x^7 - 198/35*x^6 - 576/
+35*x^5 + 229/7*x^4 - 761/35*x^3 + 671/35*x^2 - 11/35*x - 542/35, x^9 - 6*x^8
+ + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17), Mod(-4/1
+75*x^8 + 33/175*x^7 - 11/25*x^6 - 6/35*x^5 + 353/175*x^4 - 51/25*x^3 + 106/1
+75*x^2 - 2/5*x - 202/175, x^9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 4
+1*x^3 + 21*x^2 + 13*x - 17), Mod(88/175*x^8 - 401/175*x^7 + 384/175*x^6 + 25
+7/35*x^5 - 2326/175*x^4 + 1534/175*x^3 - 1207/175*x^2 - 4/7*x + 1004/175, x^
+9 - 6*x^8 + 11*x^7 + 8*x^6 - 47*x^5 + 56*x^4 - 41*x^3 + 21*x^2 + 13*x - 17)]
+], 0, 0, 0, [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 
+0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 
+0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0
+, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [[1, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 
+1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0
+, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 
+0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0
+, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, -1, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0
+, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0
+, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0
+, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0,
+ 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0,
+ 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0,
+ 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, -1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 1, -1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0], [0, -1, 1, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 
+0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0,
+ 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 
+0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0
+, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -1, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0
+, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 
+0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0
+, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -
+1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, -1, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, -1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0,
+ -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0
+, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 1, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 
+0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 1, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 
+0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 1; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1
+, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0,
+ 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, -1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0; 0, 0, -1, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1; 1, -1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0;
+ 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0,
+ 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -1, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, -1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1; 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1
+, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, -1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, -1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0,
+ 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0,
+ 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 
+0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, -1, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, -1, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0
+, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0
+, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0; 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 
+0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0
+, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
+ 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
+; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 
+0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0
+, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1; 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0; 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0;
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0,
+ 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+-1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+1, -1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, -1, 0, 0, 0, 0; 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -1; 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0; 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0
+; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0
+, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+1, 0, 0, 0, 0, 0; 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, -1, 1; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 
+1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0
+, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0; 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0; 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0; 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, -1, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, -1
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0
+, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, -1, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 
+-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0; 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0
+, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -
+1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0
+, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 1, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 1, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, -1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 1, -1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0; 0, 0, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1; 1, -1, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0; 0, -1, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1,
+ 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, -1, 1, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1; 0, 0, 1, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]], 0, [27, -
+9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, -3,
+ 0]]
+trivial algebra over a quadratic field
+[[x, [[1, -x], 1], [[1, 0; 0, 1], 1], 1, [], [], [[1], [1]], Mat(1), 1, [y^2
+ + 1, [0, 1], -4, 1, [Mat([1, 0.E-57 + 1.00000000000000000000000000000000000
+00*I]), [1, 1.0000000000000000000000000000000000000; 1, -1.00000000000000000
+00000000000000000000], [1, 1; 1, -1], [2, 0; 0, -2], [2, 0; 0, 2], [1, 0; 0,
+ -1], [1, [0, -1; 1, 0]], [2]], [0.E-57 + 1.00000000000000000000000000000000
+00000*I], [1, y], [1, 0; 0, 1], [1, 0, 0, -1; 0, 1, 1, 0]], [x^2 + 1, -x, -1
+, y^2 + 1, x], [[x^2 + 1, [0, 1], -4, 1, [Mat([1, 0.E-77 - 1.000000000000000
+0000000000000000000000*I]), [1, -1.0000000000000000000000000000000000000; 1,
+ 1.0000000000000000000000000000000000000], [1, -1; 1, 1], [2, 0; 0, -2], [2,
+ 0; 0, 2], [1, 0; 0, -1], [1, [0, -1; 1, 0]], []], [0.E-77 + 1.0000000000000
+000000000000000000000000*I], [1, -x], [1, 0; 0, -1], [1, 0, 0, -1; 0, 1, 1, 
+0]]]], [Mod(y, y^2 + 1)], Mod(1, y^2 + 1), Vecsmall([]), [[], Vecsmall([])],
+ 0, [1, 0; 0, 1], [1, 0; 0, 1], [[1, 0; 0, 1], [0, -1; 1, 0]], 0, [2, 0]]
+[y]~
+[-2*y + 1]~
+[3, 1]~
+[-y + 1]~
+[3, 0]~
+[Mod(Mod(y + 2, y^2 + 1), x)]~
+[1/5, 7/5]~
+[1/5, 7/5]~
+[Mod(Mod(-y, y^2 + 1), x)]~
+[1, -2]~
+
+[Mod(Mod(y, y^2 + 1), x)]
+
+x + Mod(2*y - 1, y^2 + 1)
+Mod(y + 3, y^2 + 1)
+Mod(y + 3, y^2 + 1)
+1
+1
+1
+0
+0
+1
+1
+1
+0
+[]
+trivial algebra over Q
+[[x, [[1], 1], [Mat(1), 1], 1, [], [], [[1], [1]], Mat(1), 1, [y, [1, 0], 1,
+ 1, [Mat(1), Mat(1), Mat(1), Mat(1), 1, Mat(1), [1, 0], []], [0.E-57], [1], 
+Mat(1), Mat(1)], [x, 0, -1, y, x], [[x, [1, 0], 1, 1, [Mat(1), Mat(1), Mat(1
+), Mat(1), 1, Mat(1), [1, 0], []], [0.E-77], [1], Mat(1), Mat(1)]]], [0], Mo
+d(1, y), Vecsmall([0]), [[], Vecsmall([])], 0, Mat(1), Mat(1), [Mat(1)], 0, 
+[1]]
+[-2]~
+[1/3]~
+[-3]~
+[-5/3]~
+[-1]~
+[-2/3]~
+[-9]~
+[-9]~
+[-1/2]~
+[1/3]~
+
+[-2]
+
+x - 1/3
+-3
+-3
+1
+1
+1
+0
+0
+1
+1
+1
+0
+[]
+trivial CSA over Q
+[Mod(9, y)]~
+[4]~
+  ***   at top-level: algsqr(al,[Mod(1,y),
+  ***                 ^--------------------
+  *** algsqr: incorrect type in alg_model (t_COL).
+nontrivial CSA over Q
+[Mod(0, y), Mod(12, y), Mod(6, y), Mod(12, y)]~
+[-81, 27, 36, 45]~
+  ***   at top-level: algsqr(al,[Mod(1,y),
+  ***                 ^--------------------
+  *** algsqr: incorrect type in alg_model (t_COL).
+empty matrices
+-v: 1
+v^(-1): 1
+v^n: 1
+v^0: 1
+mt(v)1
+spl(v)1
+trace(v): 1
+norm(v): 1
+charpoly(v): 1
+v+v: 1
+v-v: 1
+v*v: 1
+v/v: 1
+v\v: 1
+v*nv: 1
+v*v 2: 1
+trace(v) char 2: 1
+[0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 0, [1]]
+[12]~
+[-1/7]~
+[83/7]~
+[85/7]~
+[-12/7]~
+[-12]~
+[1/12]~
+[1/49]~
+[-1/84]~
+12
+-1/7
+x - 12
+
+[-1/7]
+
+[1]~
+1
+1
+1
+1
+  ***   at top-level: algsplittingfield(al
+  ***                 ^--------------------
+  *** algsplittingfield: incorrect type in alg_get_splittingfield [use alginit] (t_VEC).
+  ***   at top-level: algdegree(almt)
+  ***                 ^---------------
+  *** algdegree: incorrect type in alg_get_degree [use alginit] (t_VEC).
+  ***   at top-level: alghassei(almt)
+  ***                 ^---------------
+  *** alghassei: incorrect type in alg_get_hasse_i [use alginit] (t_VEC).
+  ***   at top-level: alghassef(almt)
+  ***                 ^---------------
+  *** alghassef: incorrect type in alg_get_hasse_f [use alginit] (t_VEC).
+  ***   at top-level: algrandom(1,1)
+  ***                 ^--------------
+  *** algrandom: incorrect type in checkalg [please apply alginit()] (t_INT).
+  ***   at top-level: algrandom(1,I)
+  ***                 ^--------------
+  *** algrandom: incorrect type in algrandom (t_COMPLEX).
+0
+  ***   at top-level: algdim([1,[1],0,0,0,
+  ***                 ^--------------------
+  *** algdim: incorrect type in checkalg [please apply alginit()] (t_VEC).
+  ***   at top-level: algabsdim([1,[1],0,0
+  ***                 ^--------------------
+  *** algabsdim: incorrect type in checkalg [please apply alginit()] (t_VEC).
+  ***   at top-level: algtensor(al,al2)
+  ***                 ^-----------------
+  *** algtensor: sorry, tensor of non-cyclic algebras is not yet implemented.
+  ***   at top-level: algtensor(al2,al)
+  ***                 ^-----------------
+  *** algtensor: sorry, tensor of non-cyclic algebras is not yet implemented.
+  ***   at top-level: algtensor(1,z,1)
+  ***                 ^----------------
+  *** algtensor: incorrect type in checkalg [please apply alginit()] (t_INT).
+  ***   at top-level: algisassociative([1]
+  ***                 ^--------------------
+  *** algisassociative: incorrect type in algisassociative (mult. table) (t_VEC).
+  ***   at top-level: algisassociative([[1
+  ***                 ^--------------------
+  *** algisassociative: incorrect type in algisassociative (mult. table) (t_VEC).
+  ***   at top-level: algmul(almt,a,b)
+  ***                 ^----------------
+  *** algmul: incorrect type in alg_model (t_COL).
+  ***   at top-level: algmultable(almt,a)
+  ***                 ^-------------------
+  *** algmultable: incorrect type in alg_model (t_COL).
+  ***   at top-level: alginv(almt,a)
+  ***                 ^--------------
+  *** alginv: incorrect type in alg_model (t_COL).
+  ***   at top-level: algsplittingmatrix(a
+  ***                 ^--------------------
+  *** algsplittingmatrix: domain error in algsplittingmatrix: alg_type(al) = 1
+  ***   at top-level: algalgtobasis(almt,a
+  ***                 ^--------------------
+  *** algalgtobasis: incorrect type in algalgtobasis [use alginit] (t_VEC).
+  ***   at top-level: algbasistoalg(almt,[
+  ***                 ^--------------------
+  *** algbasistoalg: incorrect type in algbasistoalg [use alginit] (t_VEC).
+  ***   at top-level: algpoleval(almt,1,a)
+  ***                 ^--------------------
+  *** algpoleval: incorrect type in algpoleval (t_INT).
+  ***   at top-level: algadd(almt,[zero;ze
+  ***                 ^--------------------
+  *** algadd: inconsistent dimensions in alM_add (rows).
+  ***   at top-level: algadd(almt,[zero;ze
+  ***                 ^--------------------
+  *** algadd: inconsistent dimensions in alM_add (columns).
+  ***   at top-level: algsub(almt,[zero;ze
+  ***                 ^--------------------
+  *** algsub: inconsistent dimensions in alM_sub (rows).
+  ***   at top-level: algsub(almt,[zero;ze
+  ***                 ^--------------------
+  *** algsub: inconsistent dimensions in alM_sub (columns).
+  ***   at top-level: algmul(almt,m,[zero;
+  ***                 ^--------------------
+  *** algmul: inconsistent dimensions in alM_mul.
+  ***   at top-level: algsqr(almt,[zero;ze
+  ***                 ^--------------------
+  *** algsqr: inconsistent dimensions in alM_mul.
+  ***   at top-level: algdivl(almt,m,zero)
+  ***                 ^--------------------
+  *** algdivl: forbidden division t_MAT (1x2) \ t_COL (4 elts).
+  ***   at top-level: algdivl(almt,m,[zero
+  ***                 ^--------------------
+  *** algdivl: inconsistent dimensions in algdivl.
+  ***   at top-level: algdivl(almt,m,m)
+  ***                 ^-----------------
+  *** algdivl: inconsistent dimensions in algdivl (nonsquare).
+  ***   at top-level: alginv(almt,m)
+  ***                 ^--------------
+  *** alginv: inconsistent dimensions in alginv_i (nonsquare).
+  ***   at top-level: algmultable(almt,m)
+  ***                 ^-------------------
+  *** algmultable: inconsistent dimensions in algmultable_mat (nonsquare).
+  ***   at top-level: algpow(almt,m,3)
+  ***                 ^----------------
+  *** algpow: inconsistent dimensions in alM_mul.
+  ***   at top-level: algtrace(almt,m)
+  ***                 ^----------------
+  *** algtrace: inconsistent dimensions in algtrace_mat (nonsquare).
+  ***   at top-level: algcharpoly(almt,m)
+  ***                 ^-------------------
+  *** algcharpoly: inconsistent dimensions in algmultable_mat (nonsquare).
+  ***   at top-level: algcharpoly(alginit(
+  ***                 ^--------------------
+  *** algcharpoly: incorrect type in easychar (t_MAT).
+  ***   at top-level: algnorm(almt,m)
+  ***                 ^---------------
+  *** algnorm: inconsistent dimensions in algmultable_mat (nonsquare).
+  ***   at top-level: algnorm(alginit(nfin
+  ***                 ^--------------------
+  *** algnorm: inconsistent dimensions in det.
+  ***   at top-level: alginit(nfinit(y),[2
+  ***                 ^--------------------
+  *** alginit: incorrect type in Hasse invariant (t_POL).
+  ***   at top-level: alginit(nfinit(y),[2
+  ***                 ^--------------------
+  *** alginit: incorrect type in checkhasse [hf] (t_VECSMALL).
+  ***   at top-level: alginit(nfinit(y),[2
+  ***                 ^--------------------
+  *** alginit: domain error in checkhasse: sum(Hasse invariants) != 0
+  ***   at top-level: alginit(y,[2,[[],[]]
+  ***                 ^--------------------
+  *** alginit: incorrect type in alinit3 (t_POL).
+  ***   at top-level: alginit(nfinit(y),y)
+  ***                 ^--------------------
+  *** alginit: incorrect type in alinit1 (t_POL).
+  ***   at top-level: alginit(nfinit(y),[1
+  ***                 ^--------------------
+  *** alginit: incorrect type in alinit1 (t_VEC).
+  ***   at top-level: algtableinit(mt,y)
+  ***                 ^------------------
+  *** algtableinit: incorrect type in algtableinit (t_POL).
+  ***   at top-level: alginit(nfinit(x^2+1
+  ***                 ^--------------------
+  *** alginit: domain error in alg_matrix: n <= 0
+  ***   at top-level: ...t(nfinit(y^2-2),[-1,-1]);algrandom(al,-10)
+  ***                                             ^-----------------
+  *** algrandom: domain error in algrandom: b < 0
+  ***   at top-level: algrelmultable(al)
+  ***                 ^------------------
+  *** algrelmultable: incorrect type in alg_get_relmultable [algebra not given via mult. table] (t_VEC).
+  ***   at top-level: algsplittingdata(al)
+  ***                 ^--------------------
+  *** algsplittingdata: incorrect type in alg_get_splittingdata [algebra not given via mult. table] (t_VEC).
+  ***   at top-level: alghasse(almt,1)
+  ***                 ^----------------
+  *** alghasse: incorrect type in alghasse_0 [use alginit] (t_VEC).
+  ***   at top-level: algindex(almt,1)
+  ***                 ^----------------
+  *** algindex: incorrect type in algindex [use alginit] (t_VEC).
+  ***   at top-level: algisdivision(almt)
+  ***                 ^-------------------
+  *** algisdivision: sorry, algisdivision for table algebras is not yet implemented.
+  ***   at top-level: algissplit(almt)
+  ***                 ^----------------
+  *** algissplit: incorrect type in algissplit [use alginit] (t_VEC).
+  ***   at top-level: algisramified(almt)
+  ***                 ^-------------------
+  *** algisramified: incorrect type in algisramified [use alginit] (t_VEC).
+  ***   at top-level: algramifiedplaces(al
+  ***                 ^--------------------
+  *** algramifiedplaces: incorrect type in algramifiedplaces [use alginit] (t_VEC).
+  ***   at top-level: alghasse(al,-1)
+  ***                 ^---------------
+  *** alghasse: domain error in is_place_prid: pl <= 0
+  ***   at top-level: alghasse(al,3)
+  ***                 ^--------------
+  *** alghasse: domain error in is_place_prid: pl > 2
+  ***   at top-level: alghasse(al,2^100)
+  ***                 ^------------------
+  *** alghasse: domain error in is_place_prid: pl > 2
+  ***   at top-level: alghasse(al,[])
+  ***                 ^---------------
+  *** alghasse: incorrect type in is_place_prid (t_VEC).
+  ***   at top-level: alghasse(al,1/3)
+  ***                 ^----------------
+  *** alghasse: incorrect type in is_place_prid (t_FRAC).
+  ***   at top-level: algtableinit([matid(
+  ***                 ^--------------------
+  *** algtableinit: domain error in algtableinit: denominator(mt) != 1
+  ***   at top-level: alginit(Q,[matid(2),
+  ***                 ^--------------------
+  *** alginit: domain error in alg_csa_table: denominator(mt) != 1
+  ***   at top-level: alginit(Q,[-1/2,-1])
+  ***                 ^--------------------
+  *** alginit: domain error in alg_hilbert: denominator(a) != 1
+  ***   at top-level: alginit(Q,[-1,-1/2])
+  ***                 ^--------------------
+  *** alginit: domain error in alg_hilbert: denominator(b) != 1
+  ***   at top-level: alginit(rnfinit(Q,x^
+  ***                 ^--------------------
+  *** alginit: domain error in alg_cyclic: denominator(b) != 1
+  ***   at top-level: algsqr([0,0,0,0,0,0,
+  ***                 ^--------------------
+  *** algsqr: incorrect type in checkalg [please apply alginit()] (t_VEC).
+  ***   at top-level: algsqr([0,0,0,0,0,0,
+  ***                 ^--------------------
+  *** algsqr: incorrect type in checkalg [please apply alginit()] (t_VEC).
+  ***   at top-level: algsqr([0,0,0,0,0,0,
+  ***                 ^--------------------
+  *** algsqr: incorrect type in checkalg [please apply alginit()] (t_VEC).
+  ***   at top-level: algsqr([0,0,0,0,0,0,
+  ***                 ^--------------------
+  *** algsqr: incorrect type in alg_model (t_COL).
+  ***   at top-level: algsqr([[],0,0,0,0,0
+  ***                 ^--------------------
+  *** algsqr: incorrect type in checkalg [please apply alginit()] (t_VEC).
+  ***   at top-level: algsqr([[],[0],0,0,0
+  ***                 ^--------------------
+  *** algsqr: incorrect type in checkrnf (t_VEC).
+  ***   at top-level: algdim([[],[0],0,0,0
+  ***                 ^--------------------
+  *** algdim: incorrect type in checkrnf (t_VEC).
+  ***   at top-level: algdegree([[],[0],0,
+  ***                 ^--------------------
+  *** algdegree: incorrect type in checkrnf (t_VEC).
+  ***   at top-level: algdegree([rnfinit(n
+  ***                 ^--------------------
+  *** algdegree: incorrect type in alg_get_degree [use alginit] (t_VEC).
+  ***   at top-level: algcenter([rnfinit(n
+  ***                 ^--------------------
+  *** algcenter: incorrect type in alg_get_center [use alginit] (t_VEC).
+  ***   at top-level: algcentralproj(almt,
+  ***                 ^--------------------
+  *** algcentralproj: incorrect type in alcentralproj (t_INT).
+  ***   at top-level: algcentralproj(almt,
+  ***                 ^--------------------
+  *** algcentralproj: incorrect type in alcentralproj [z[i]'s not surjective] (t_VEC).
+  ***   at top-level: algsubalg(almt,0)
+  ***                 ^-----------------
+  *** algsubalg: incorrect type in algsubalg (t_INT).
+  ***   at top-level: algisassociative([])
+  ***                 ^--------------------
+  *** algisassociative: incorrect type in algisassociative (mult. table) (t_VEC).
+  ***   at top-level: algisassociative([ma
+  ***                 ^--------------------
+  *** algisassociative: incorrect type in algisassociative (mult. table) (t_VEC).
+  ***   at top-level: algisassociative([[1
+  ***                 ^--------------------
+  *** algisassociative: incorrect type in algisassociative (mult. table) (t_VEC).
+  ***   at top-level: algisassociative([ma
+  ***                 ^--------------------
+  *** algisassociative: incorrect type in algisassociative (t_VEC).
+  ***   at top-level: algsqr(algtableinit(
+  ***                 ^--------------------
+  *** algsqr: incorrect type in alg_model (t_COL).
+  ***   at top-level: algsqr(al,vector(691
+  ***                 ^--------------------
+  *** algsqr: incorrect type in alg_model (t_COL).
+  ***   at top-level: algsqr(al,[1,2,3,4,5
+  ***                 ^--------------------
+  *** algsqr: incorrect type in checkalgx (t_POL).
+  ***   at top-level: algsqr(al,[f^3,[]]~)
+  ***                 ^--------------------
+  *** algsqr: incorrect type in checkalgx (t_VEC).
+  ***   at top-level: algmul(al,[;],[1,2]~
+  ***                 ^--------------------
+  *** algmul: incorrect type in algmul (t_COL).
+  ***   at top-level: algdivl(al,[;],matid
+  ***                 ^--------------------
+  *** algdivl: impossible inverse in algdivl: [;].
+  ***   at top-level: algdivl(al,matid(1),
+  ***                 ^--------------------
+  *** algdivl: inconsistent dimensions in algdivl (nonsquare).
+  ***   at top-level: alginv(al,[0,0]~)
+  ***                 ^-----------------
+  *** alginv: impossible inverse in alginv: [0, 0]~.
+  ***   at top-level: algalgtobasis(al0mt,
+  ***                 ^--------------------
+  *** algalgtobasis: incorrect type in algalgtobasis [use alginit] (t_VEC).
+  ***   at top-level: algbasistoalg(al0mt,
+  ***                 ^--------------------
+  *** algbasistoalg: incorrect type in algbasistoalg [use alginit] (t_VEC).
+  ***   at top-level: nfgrunwaldwang(nfini
+  ***                 ^--------------------
+  *** nfgrunwaldwang: incorrect type in nfgrunwaldwang (t_INT).
+  ***   at top-level: alginit(rnfinit(nfin
+  ***                 ^--------------------
+  *** alginit: incorrect type in alinit2 (t_INT).
+  ***   at top-level: alginit(rnfinit(nfin
+  ***                 ^--------------------
+  *** alginit: incorrect type in alinit2 (t_VEC).
+  ***   at top-level: alginit(nfinit(y),[m
+  ***                 ^--------------------
+  *** alginit: incorrect type in alg_csa_table (t_VEC).
+  ***   at top-level: alginit(nfinit(y),[m
+  ***                 ^--------------------
+  *** alginit: domain error in alg_csa_table: (nonsquare) dimension != 1
+  ***   at top-level: nfgrunwaldwang(nfini
+  ***                 ^--------------------
+  *** nfgrunwaldwang: incorrect type in nfgrunwaldwang (t_INT).
+  ***   at top-level: nfgrunwaldwang(nfini
+  ***                 ^--------------------
+  *** nfgrunwaldwang: inconsistent dimensions in nfgrunwaldwang [#Lpr != #Ld].
+  ***   at top-level: nfgrunwaldwang(nfini
+  ***                 ^--------------------
+  *** nfgrunwaldwang: domain error in nfgrunwaldwang [pl should have r1 components]: #pl != 1
+  ***   at top-level: nfgrunwaldwang(nfini
+  ***                 ^--------------------
+  *** nfgrunwaldwang: sorry, nfgrunwaldwang for non prime-power local degrees (a) is not yet implemented.
+  ***   at top-level: nfgrunwaldwang(nfini
+  ***                 ^--------------------
+  *** nfgrunwaldwang: sorry, nfgrunwaldwang for non prime-power local degrees (b) is not yet implemented.
+  ***   at top-level: nfgrunwaldwang(nfini
+  ***                 ^--------------------
+  *** nfgrunwaldwang: sorry, nfgrunwaldwang for non prime-power local degrees (c) is not yet implemented.
+  ***   at top-level: nfgrunwaldwang(nfini
+  ***                 ^--------------------
+  *** nfgrunwaldwang: incorrect type in checkprid (t_COL).
+  ***   at top-level: nfgrunwaldwang(nfini
+  ***                 ^--------------------
+  *** nfgrunwaldwang: sorry, nfgrunwaldwang for non-prime degree is not yet implemented.
+  ***   at top-level: algdegree(A)
+  ***                 ^------------
+  *** algdegree: incorrect type in alg_get_degree [use alginit] (t_VEC).
+  ***   at top-level: algsub(A,1,1)
+  ***                 ^-------------
+  *** algsub: incorrect type in alg_model (t_INT).
+  ***   at top-level: algadd(A,1,1)
+  ***                 ^-------------
+  *** algadd: incorrect type in alg_model (t_INT).
+  ***   at top-level: algneg(A,1)
+  ***                 ^-----------
+  *** algneg: incorrect type in alg_model (t_INT).
+  ***   at top-level: algmul(A,1,1)
+  ***                 ^-------------
+  *** algmul: incorrect type in alg_model (t_INT).
+  ***   at top-level: algsqr(A,1)
+  ***                 ^-----------
+  *** algsqr: incorrect type in alg_model (t_INT).
+  ***   at top-level: algdivl(A,1,1)
+  ***                 ^--------------
+  *** algdivl: incorrect type in alg_model (t_INT).
+  ***   at top-level: algdivr(A,1,1)
+  ***                 ^--------------
+  *** algdivr: incorrect type in alg_model (t_INT).
+  ***   at top-level: alginv(A,1)
+  ***                 ^-----------
+  *** alginv: incorrect type in alg_model (t_INT).
+  ***   at top-level: ...;PR=idealprimedec(K,2);A=alginit(K,[3,[PR,[1]
+  ***                                             ^--------------------
+  *** alginit: domain error in checkhasse: Hasse invariant at real place [must be 0 or 1/2] != 0
+  ***   at top-level: ...;P3=idealprimedec(K,3);A=alginit(K,[3,[concat
+  ***                                             ^--------------------
+  *** alginit: domain error in checkhasse: Hasse invariant at real place [must be 0 or 1/2] != 0
+  ***   at top-level: algtensor(alginit(nf
+  ***                 ^--------------------
+  *** algtensor: inconsistent tensor product [not the same center] t_VEC (11 elts) , t_VEC (11 elts).
+  ***   at top-level: algtensor(alginit(nf
+  ***                 ^--------------------
+  *** algtensor: sorry, tensor of cylic algebras of non-coprime degrees is not yet implemented.
+  ***   at top-level: alginit(nf,[2,[[p2,p
+  ***                 ^--------------------
+  *** alginit: error in checkhasse [duplicate prime ideal].
+  ***   at top-level: alginit(nf,[2,[[p2,p
+  ***                 ^--------------------
+  *** alginit: domain error in checkhasse [hi should have r1 components]: #hi != 1
+  ***   at top-level: alginit(nf,[2,[[p2,p
+  ***                 ^--------------------
+  *** alginit: incorrect type in Hasse invariant (t_VEC).
+  ***   at top-level: alginit(nf,[2,[0,[1/
+  ***                 ^--------------------
+  *** alginit: incorrect type in Hasse invariant (t_VEC).
+  ***   at top-level: alginit(nf,[2,[[p2,p
+  ***                 ^--------------------
+  *** alginit: incorrect type in Hasse invariant (t_INT).
+  ***   at top-level: alginit(nf,[2,[[p2,p
+  ***                 ^--------------------
+  *** alginit: inconsistent dimensions in checkhasse [Lpr and Lh should have same length].
+  ***   at top-level: alginit(nf,[2,[[p2,p
+  ***                 ^--------------------
+  *** alginit: domain error in hasseconvert [degree should be a denominator of the invariant]: denom(h) ndiv 2
+1/2
+0
+3/4
+0
+1/4
+1/2
+2
+1
+4
+1
+4
+2
+4
+0
+0
+1
+0
+1
+0
+1
+0
+1
+0
+1
+0
+0
+0
+1
+0
+1
+0
+1
+1
+1
+[1, [2, [2, 0, 0]~, 1, 3, 1], [5, [2, 0, 1]~, 1, 1, [-1, 2, -3; 1, -2, -2; -
+2, -1, -1]], [5, [-1, 1, -2]~, 1, 2, [2, -1, 1; 0, 2, 1; 1, 0, 2]]]
+ 
+1/2
+0
+0
+1/2
+0
+2
+1
+1
+2
+1
+2
+0
+0
+0
+0
+0
+0
+0
+1
+1
+0
+1
+0
+1
+0
+0
+1
+0
+1
+[1, [5, [2, 0, 1]~, 1, 1, [-1, 2, -3; 1, -2, -2; -2, -1, -1]]]
+ 
+0
+0
+0
+0
+1
+1
+1
+1
+1
+0
+0
+0
+0
+0
+1
+1
+1
+1
+1
+0
+0
+0
+0
+0
+[]
+Hasse inv 0 bug
+3
+9
+1
+0
+[2, 0, 0, 2, 0, 0, 3, 0, 0]~
+[0, 0, 0, -2, 0, 0, -3, 0, 0]~
+[0, 0, 0, 0, 0, 0, 0, 0, 0]~
+trivial tensor product
+1
+1
+splitting a nasty commutative algebra
+1
+1
+1
+1
+non associative algebra
+0
+csa without maximal order
+nfgrunwaldwang SEGV #1669
+x^2 + Mod(-17, y)
+  ***   at top-level: nfgrunwaldwang(nfini
+  ***                 ^--------------------
+  *** nfgrunwaldwang: incorrect priority in nfgrunwaldwang: variable x >= x
+simplify bug #1671
+testing simplify: degree 1 cyclic over Q
+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
+testing simplify: degree 1 cyclic over Q(i)
+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
+testing simplify: degree 1 csa over Q
+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
+testing simplify: degree 1 csa over Q(i)
+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
+testing simplify: quatalg over Q(s5)
+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
+testing simplify: quatalg csa over Q
+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
+Total time spent: 7968
diff --git a/src/test/32/apply b/src/test/32/apply
index e822410..64bd29e 100644
--- a/src/test/32/apply
+++ b/src/test/32/apply
@@ -12,4 +12,8 @@ List([1, 2])
 [0, 1, 2]
 [2, 3]
 [2, 3]
+24
+[[[1, 2], 3], 4]
+256
+-9/19
 Total time spent: 0
diff --git a/src/test/32/bnr b/src/test/32/bnr
index ffc2f9a..de4ce69 100644
--- a/src/test/32/bnr
+++ b/src/test/32/bnr
@@ -2,11 +2,11 @@
 [[4, 0, 0; 0, 2, 0; 0, 0, 2], [4, 0, 2; 0, 2, 1; 0, 0, 1], [4, 2, 0; 0, 1, 0
 ; 0, 0, 2], [4, 0, 2; 0, 2, 0; 0, 0, 1], [2, 0, 0; 0, 2, 0; 0, 0, 2], [4, 0,
  0; 0, 2, 1; 0, 0, 1], [4, 0, 0; 0, 1, 0; 0, 0, 2], [4, 0, 0; 0, 2, 0; 0, 0,
- 1], [2, 0, 1; 0, 2, 1; 0, 0, 1], [2, 0, 1; 0, 2, 0; 0, 0, 1], [2, 0, 0; 0, 
+ 1], [2, 0, 1; 0, 2, 1; 0, 0, 1], [1, 0, 0; 0, 2, 0; 0, 0, 2], [2, 0, 0; 0, 
 2, 1; 0, 0, 1], [4, 0, 2; 0, 1, 0; 0, 0, 1], [4, 2, 2; 0, 1, 0; 0, 0, 1], [2
 , 0, 0; 0, 1, 0; 0, 0, 2], [4, 2, 0; 0, 1, 0; 0, 0, 1], [2, 0, 0; 0, 2, 0; 0
-, 0, 1], [4, 0, 0; 0, 1, 0; 0, 0, 1], [2, 0, 1; 0, 1, 0; 0, 0, 1]]
-[[2, 0, 1; 0, 1, 0; 0, 0, 1]]
+, 0, 1], [4, 0, 0; 0, 1, 0; 0, 0, 1], [1, 0, 0; 0, 2, 1; 0, 0, 1]]
+[[1, 0, 0; 0, 2, 1; 0, 0, 1]]
 [[1, 0, 0; 0, 2, 1; 0, 0, 1], [2, 0, 1; 0, 1, 0; 0, 0, 1], [2, 1, 1; 0, 1, 0
 ; 0, 0, 1], [1, 0, 0; 0, 1, 0; 0, 0, 2], [2, 1, 0; 0, 1, 0; 0, 0, 1], [1, 0,
  0; 0, 2, 0; 0, 0, 1], [2, 0, 0; 0, 1, 0; 0, 0, 1], [1, 0, 0; 0, 1, 0; 0, 0,
@@ -37,8 +37,8 @@
 [4, 4, 262205]
 [2, 2, [5, 3; 0, 1]]
 6
-0.99197791640852265169404803750682485962 - 0.1264112865127400184730959576238
-0269676*I
+0.99197791640852265169404803750682485966 + 0.1264112865127400184730959576238
+0269659*I
 [4, [2, 2], [[3, 1; 0, 1], [114, 1; 0, 1]]]
 [[1, 0, 0; 0, 1, 0; 0, 0, 1], [0]]
-Total time spent: 36
+Total time spent: 24
diff --git a/src/test/32/bnrL1 b/src/test/32/bnrL1
index e1691b4..a8ac0ed 100644
--- a/src/test/32/bnrL1
+++ b/src/test/32/bnrL1
@@ -1,33 +1,49 @@
 [[1, 0.38224508584003564132935849918485739404 + 0.E-38*I], [1, 0.38224508584
 003564132935849918485739404 + 0.E-38*I], [0, -3/2]]
-[[2, 2.9500952396964494033818838179661887250 - 0.788700989456330674320020455
-38518403783*I], [2, 1.9859006356377427761789576705596841597], [2, 2.95009523
-96964494033818838179661887250 + 0.78870098945633067432002045538518403783*I],
- [1, -0.65847894846240835431252317365398422201]]
-[[1, 1.5356246494250488796129024765168058300 + 1.753485276139541406647384954
-4183759911*I], [2, 2.9500952396964494033818838179661887250 - 0.7887009894563
-3067432002045538518403783*I], [1, 1.1816366573593674455773236880707753792 + 
-2.7350893332487963668865434012735333609*I], [2, 1.98590063563774277617895767
-05596841597], [1, 1.1816366573593674455773236880707753792 - 2.73508933324879
-63668865434012735333609*I], [2, 2.9500952396964494033818838179661887250 + 0.
-78870098945633067432002045538518403783*I], [1, 1.535624649425048879612902476
-5168058300 - 1.7534852761395414066473849544183759911*I], [1, -0.658478948462
-40835431252317365398422201]]
-[[1, 1.5356246494250488796129024765168058300 + 1.753485276139541406647384954
-4183759911*I], [2, 2.9500952396964494033818838179661887250 - 0.7887009894563
-3067432002045538518403783*I], [1, 1.1816366573593674455773236880707753793 + 
-2.7350893332487963668865434012735333609*I], [2, 1.98590063563774277617895767
-05596841597], [1, 1.1816366573593674455773236880707753793 - 2.73508933324879
-63668865434012735333609*I], [2, 2.9500952396964494033818838179661887250 + 0.
-78870098945633067432002045538518403783*I], [1, 1.535624649425048879612902476
-5168058300 - 1.7534852761395414066473849544183759911*I], [0, 4.0000000000000
-000000000000000000000000], [1, 1.5356246494250488796129024765168058300 + 1.7
-534852761395414066473849544183759911*I], [0, 1.60000000000000000000000000000
-00000000 + 0.79999999999999999999999999999999999999*I], [1, 1.18163665735936
-74455773236880707753793 + 2.7350893332487963668865434012735333609*I], [0, 0.
-16666666666666666666666666666666666670], [1, 1.18163665735936744557732368807
-07753793 - 2.7350893332487963668865434012735333609*I], [0, 1.600000000000000
-0000000000000000000000 - 0.79999999999999999999999999999999999999*I], [1, 1.
-5356246494250488796129024765168058300 - 1.7534852761395414066473849544183759
-911*I], [1, -0.65847894846240835431252317365398422201]]
-Total time spent: 264
+[[[1], 0.69082574035845153597174938200391860974 - 0.141771150359113754753792
+96778414429232*I], [[2], 0.45862410662771988186069579649547270634], [[3], 0.
+69082574035845153597174938200391860974 + 0.141771150359113754753792967784144
+29232*I]]
+[[[1], 0.74706478772303241588174336102451164905 + 0.396016528061576517014024
+73588976342837*I], [[2], 0.69082574035845153597174938200391860974 - 0.141771
+15035911375475379296778414429232*I], [[3], 0.8671551505768356258861689505475
+1987123 + 0.64513993724355847080454579289618230200*I], [[4], 0.4586241066277
+1988186069579649547270634], [[5], 0.86715515057683562588616895054751987123 -
+ 0.64513993724355847080454579289618230200*I], [[6], 0.6908257403584515359717
+4938200391860974 + 0.14177115035911375475379296778414429232*I], [[7], 0.7470
+6478772303241588174336102451164905 - 0.3960165280615765170140247358897634283
+7*I]]
+[[[1, 0], 0.74706478772303241588174336102451164905 + 0.396016528061576517014
+02473588976342836*I], [[2, 0], 0.69082574035845153597174938200391860974 - 0.
+14177115035911375475379296778414429232*I], [[3, 0], 0.8671551505768356258861
+6895054751987123 + 0.64513993724355847080454579289618230200*I], [[4, 0], 0.4
+5862410662771988186069579649547270634], [[5, 0], 0.8671551505768356258861689
+5054751987123 - 0.64513993724355847080454579289618230200*I], [[6, 0], 0.6908
+2574035845153597174938200391860974 + 0.1417711503591137547537929677841442923
+2*I], [[7, 0], 0.74706478772303241588174336102451164905 - 0.3960165280615765
+1701402473588976342836*I], [[0, 1], 2.2792875031056225486323963801897796381]
+, [[1, 1], 0.74706478772303241588174336102451164905 + 0.39601652806157651701
+402473588976342836*I], [[2, 1], 1.0193283594419870077704818539447783577 + 0.
+E-39*I], [[3, 1], 0.86715515057683562588616895054751987123 + 0.6451399372435
+5847080454579289618230200*I], [[4, 1], 0.47485156314700469763174924587287075
+804], [[5, 1], 0.86715515057683562588616895054751987123 - 0.6451399372435584
+7080454579289618230200*I], [[6, 1], 1.0193283594419870077704818539447783577 
++ 0.E-39*I], [[7, 1], 0.74706478772303241588174336102451164905 - 0.396016528
+06157651701402473588976342836*I]]
+[[[1, 0, 0], 0.83081832012833464173087318604481930961 + 0.514580721717982992
+96449819908970897243*I], [[2, 0, 0], 0.4261659362390829298602231389837827437
+9], [[3, 0, 0], 0.83081832012833464173087318604481930961 - 0.514580721717982
+99296449819908970897243*I], [[0, 1, 0], 1.5229130218886938349135426110563214
+049], [[1, 1, 0], 0.84199935117030392785882419071906079523 + 0.2208266434472
+5718899163157856471416929*I], [[2, 1, 0], 0.76145651094434691745677130552816
+070246], [[3, 1, 0], 0.84199935117030392785882419071906079523 - 0.2208266434
+4725718899163157856471416929*I], [[0, 0, 1], 0.97935756850988202871462966877
+232278323], [[1, 0, 1], 0.84199935117030392785882419071906079522 - 0.2208266
+4344725718899163157856471416929*I], [[2, 0, 1], 0.69093460574307742861689103
+633762202463], [[3, 0, 1], 0.84199935117030392785882419071906079522 + 0.2208
+2664344725718899163157856471416929*I], [[0, 1, 1], 1.01527534792579588994236
+17407042142699], [[1, 1, 1], 0.83081832012833464173087318604481930960 - 0.51
+458072171798299296449819908970897243*I], [[2, 1, 1], 1.522913021888693834913
+5426110563214049], [[3, 1, 1], 0.83081832012833464173087318604481930960 + 0.
+51458072171798299296449819908970897243*I]]
+Total time spent: 208
diff --git a/src/test/32/bnrisgalois b/src/test/32/bnrisgalois
new file mode 100644
index 0000000..9044371
--- /dev/null
+++ b/src/test/32/bnrisgalois
@@ -0,0 +1,9 @@
+[[1, 0, 0, 0; 0, 3, 2, 0; 0, 0, 1, 0; 0, 0, 0, 1], [3, 2, 1, 0; 0, 1, 0, 0; 
+0, 0, 1, 0; 0, 0, 0, 1], [3, 0, 0, 1; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [
+1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 3, 1; 0, 0, 0, 1]]
+[[3051, 4900, 7000, 2800; 8, 7, 0, 4; 1, 1, 5, 2; 1, 1, 1, 0], [7349, 3500, 
+7000, 2800; 0, 5, 8, 4; 3, 5, 5, 2; 0, 2, 1, 0]]
+[[1, 0, 0, 0; 0, 3, 2, 0; 0, 0, 1, 0; 0, 0, 0, 1], [3, 2, 1, 0; 0, 1, 0, 0; 
+0, 0, 1, 0; 0, 0, 0, 1], [3, 0, 0, 1; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [
+1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 3, 1; 0, 0, 0, 1]]
+Total time spent: 384
diff --git a/src/test/32/characteristic b/src/test/32/characteristic
index 53ed8c9..c4a3f3b 100644
--- a/src/test/32/characteristic
+++ b/src/test/32/characteristic
@@ -10,4 +10,8 @@
 2
 0
 0
+2
+  ***   at top-level: characteristic([ffge
+  ***                 ^--------------------
+  *** characteristic: inconsistent moduli in characteristic: 2 != 3
 Total time spent: 0
diff --git a/src/test/32/chinese b/src/test/32/chinese
index 5dd403a..04bdc41 100644
--- a/src/test/32/chinese
+++ b/src/test/32/chinese
@@ -2,4 +2,7 @@ Mod(x, x^2 + 1)
 Mod(x, x^4 - 1)
 Mod(2, 3)*x^2 + Mod(1, 6)*x + Mod(1, 6)
 [Mod(1, 4), Mod(1, 6)]
-Total time spent: 0
+  ***   at top-level: chinese(1)
+  ***                 ^----------
+  *** chinese: incorrect type in association (t_INT).
+Total time spent: 4
diff --git a/src/test/32/agm b/src/test/32/classpoly
similarity index 100%
copy from src/test/32/agm
copy to src/test/32/classpoly
diff --git a/src/test/32/cmp b/src/test/32/cmp
index af1e48b..53d3c0f 100644
--- a/src/test/32/cmp
+++ b/src/test/32/cmp
@@ -7,12 +7,21 @@
 [0, -1, 1]
 [0, -1, 1]
 [0, -1, 1]
-0
-0
-0
-1
   ***   at top-level: Mod(1,3)>0
   ***                         ^--
   *** _>_: forbidden comparison t_INTMOD , t_INT.
 -1
-Total time spent: 0
+[1, 1, 0]
+[0, 1, 1]
+1
+0
+  ***   at top-level: 1<='x
+  ***                  ^----
+  *** _<=_: forbidden comparison t_INT , t_POL.
+  ***   at top-level: 1.<='x
+  ***                   ^----
+  *** _<=_: forbidden comparison t_REAL , t_POL.
+  ***   at top-level: 1/2<='x
+  ***                    ^----
+  *** _<=_: forbidden comparison t_FRAC , t_POL.
+Total time spent: 4
diff --git a/src/test/32/compat b/src/test/32/compat
index 348144a..8351496 100644
--- a/src/test/32/compat
+++ b/src/test/32/compat
@@ -1,2594 +1,4577 @@
-   echo = 1 (on)
-? default(compatible,3)
-  *** default: Warning: user functions re-initialized.
-? +3
-3
-? -5
--5
-? 5+3
-8
-? 5-3
-2
-? 5/3
-5/3
-? 5\3
-1
-? 5\/3
-2
-? 5%3
-2
-? 5^3
-125
-? \precision=154
-   realprecision = 154 significant digits
-? pi
-3.14159265358979323846264338327950288419716939937510582097494459230781640628
-6208998628034825342117067982148086513282306647093844609550582231725359408128
-481
-? \precision=38
-   realprecision = 38 significant digits
-? o(x^12)
-O(x^12)
-? padicno=(5/3)*127+o(127^5)
-44*127 + 42*127^2 + 42*127^3 + 42*127^4 + O(127^5)
-? initrect(0,500,500)
-? abs(-0.01)
-0.010000000000000000000000000000000000000
-? acos(0.5)
-1.0471975511965977461542144610931676281
-? acosh(3)
-1.7627471740390860504652186499595846181
-? acurve=initell([0,0,1,-1,0])
-[0, 0, 1, -1, 0, 0, -2, 1, -1, 48, -216, 37, 110592/37, Vecsmall([1]), [Vecs
-mall([128, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]
-? apoint=[2,2]
-[2, 2]
-? isoncurve(acurve,apoint)
-1
-? addell(acurve,apoint,apoint)
-[21/25, -56/125]
-? addprimes([nextprime(10^9),nextprime(10^10)])
-[1000000007, 10000000019]
-? adj([1,2;3,4])
-
-[ 4 -2]
-
-[-3  1]
-
-? agm(1,2)
-1.4567910310469068691864323832650819750
-? agm(1+o(7^5),8+o(7^5))
-1 + 4*7 + 6*7^2 + 5*7^3 + 2*7^4 + O(7^5)
-? algdep(2*cos(2*pi/13),6)
-x^6 + x^5 - 5*x^4 - 4*x^3 + 6*x^2 + 3*x - 1
-? algdep2(2*cos(2*pi/13),6,15)
-x^6 + x^5 - 5*x^4 - 4*x^3 + 6*x^2 + 3*x - 1
-? akell(acurve,1000000007)
-43800
-? nfpol=x^5-5*x^3+5*x+25
-x^5 - 5*x^3 + 5*x + 25
-? nf=initalg(nfpol)
-[x^5 - 5*x^3 + 5*x + 25, [1, 2], 595125, 45, [[1, -1.08911514572050482502495
-27946671612684, -2.4285174907194186068992069565359418365, 0.7194669112891317
-8943997506477288225737, -2.5558200350691694950646071159426779972; 1, -0.1383
-8372073406036365047976417441696637 - 0.4918163765776864349975328551474152510
-7*I, 1.9647119211288133163138753392090569931 + 0.809714924188978951282940822
-19556466857*I, -0.072312766896812300380582649294307897074 + 2.19808037538462
-76641195195160383234878*I, -0.98796319352507039803950539735452837193 + 1.570
-1452385894131769052374806001981109*I; 1, 1.682941293594312776162956161507997
-6006 + 2.0500351226010726172974286983598602164*I, -0.75045317576910401286427
-186094108607489 + 1.3101462685358123283560773619310445916*I, -0.787420688747
-75359433940488309213323154 + 2.1336633893126618034168454610457936018*I, 1.26
-58732110596551455718089553258673705 - 2.716479010374315056657802803578983483
-5*I], [1, -1.0891151457205048250249527946671612684, -2.428517490719418606899
-2069565359418365, 0.71946691128913178943997506477288225737, -2.5558200350691
-694950646071159426779972; 1, -0.63020009731174679864801261932183221743, 2.77
-44268453177922675968161614046216617, 2.1257676084878153637389368667440155907
-, 0.58218204506434277886573208324566973897; 1, 0.353432655843626071347053090
-97299828470, 1.1549969969398343650309345170134923246, -2.2703931422814399645
-001021653326313849, -2.5581084321144835749447428779547264828; 1, 3.732976416
-1953853934603848598678578170, 0.55969309276670831549180550098995851667, 1.34
-62427005649082090774405779536603703, -1.450605799314659911085993848253116112
-9; 1, -0.36709382900675984113447253685186261580, -2.060599444304916341220349
-2228721306665, -2.9210840780604153977562503441379268334, 3.98235222143397020
-22296117589048508540], [1, -1, -2, 1, -3; 1, -1, 3, 2, 1; 1, 0, 1, -2, -3; 1
-, 4, 1, 1, -1; 1, 0, -2, -3, 4], [5, 2, 0, -1, -2; 2, -2, -5, -10, 20; 0, -5
-, 10, -10, 5; -1, -10, -10, -17, 1; -2, 20, 5, 1, -8], [345, 0, 200, 110, 17
-7; 0, 345, 95, 1, 145; 0, 0, 5, 4, 3; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], [63, 3,
- 0, -6, -9; 3, 8, -5, -1, 16; 0, -5, 22, -10, 0; -6, -1, -10, -14, -9; -9, 1
-6, 0, -9, -2], [345, [138, 117, 330, 288, -636; -172, -88, 65, 118, -116; 53
-, 1, 138, -173, 65; 1, -172, 54, 191, 106; 0, 118, 173, 225, -34]], [3, 5, 2
-3]], [-2.4285174907194186068992069565359418365, 1.96471192112881331631387533
-92090569931 + 0.80971492418897895128294082219556466857*I, -0.750453175769104
-01286427186094108607489 + 1.3101462685358123283560773619310445916*I], [1, 1/
-15*x^4 - 2/3*x^2 + 1/3*x + 4/3, x, 2/15*x^4 - 1/3*x^2 + 2/3*x - 1/3, -1/15*x
-^4 + 1/3*x^3 + 1/3*x^2 - 4/3*x - 2/3], [1, 0, 3, 1, 10; 0, 0, -2, 1, -5; 0, 
-1, 0, 3, -5; 0, 0, 1, 1, 10; 0, 0, 0, 3, 0], [1, 0, 0, 0, 0, 0, -1, -1, -2, 
-4, 0, -1, 3, -1, 1, 0, -2, -1, -3, -1, 0, 4, 1, -1, -1; 0, 1, 0, 0, 0, 1, 1,
- -1, -1, 1, 0, -1, -2, -1, 1, 0, -1, -1, -1, 3, 0, 1, 1, 3, -3; 0, 0, 1, 0, 
-0, 0, 0, 0, 1, -1, 1, 0, 0, 0, -2, 0, 1, 0, -1, -1, 0, -1, -2, -1, -1; 0, 0,
- 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 2, 1, 0, 1, 0, 0, 0, 0, 2, 0, -1; 0, 0,
- 0, 0, 1, 0, -1, -1, -1, 1, 0, -1, 0, 1, 0, 0, -1, 1, 0, 0, 1, 1, 0, 0, -1]]
-? ba=algtobasis(nf,mod(x^3+5,nfpol))
-[6, 1, 3, 1, 3]~
-? anell(acurve,100)
-[1, -2, -3, 2, -2, 6, -1, 0, 6, 4, -5, -6, -2, 2, 6, -4, 0, -12, 0, -4, 3, 1
-0, 2, 0, -1, 4, -9, -2, 6, -12, -4, 8, 15, 0, 2, 12, -1, 0, 6, 0, -9, -6, 2,
- -10, -12, -4, -9, 12, -6, 2, 0, -4, 1, 18, 10, 0, 0, -12, 8, 12, -8, 8, -6,
- -8, 4, -30, 8, 0, -6, -4, 9, 0, -1, 2, 3, 0, 5, -12, 4, 8, 9, 18, -15, 6, 0
-, -4, -18, 0, 4, 24, 2, 4, 12, 18, 0, -24, 4, 12, -30, -2]
-? apell(acurve,10007)
-66
-? apell2(acurve,10007)
-66
-? apol=x^3+5*x+1
-x^3 + 5*x + 1
-? apprpadic(apol,1+o(7^8))
-[1 + 6*7 + 4*7^2 + 4*7^3 + 3*7^4 + 4*7^5 + 6*7^7 + O(7^8)]~
-? apprpadic(x^3+5*x+1,mod(x*(1+o(7^8)),x^2+x-1))
-[mod((1 + 3*7 + 3*7^2 + 4*7^3 + 4*7^4 + 4*7^5 + 2*7^6 + 3*7^7 + O(7^8))*x + 
-(2*7 + 6*7^2 + 6*7^3 + 3*7^4 + 3*7^5 + 4*7^6 + 5*7^7 + O(7^8)), x^2 + x - 1)
-]~
-? 4*arg(3+3*i)
-3.1415926535897932384626433832795028842
-? 3*asin(sqrt(3)/2)
-3.1415926535897932384626433832795028842
-? asinh(0.5)
-0.48121182505960344749775891342436842314
-? assmat(x^5-12*x^3+0.0005)
-
-[0 0 0 0 -0.00050000000000000000000000000000000000000]
-
-[1 0 0 0                                            0]
-
-[0 1 0 0                                            0]
-
-[0 0 1 0                                           12]
-
-[0 0 0 1                                            0]
-
-? 3*atan(sqrt(3))
-3.1415926535897932384626433832795028842
-? atanh(0.5)
-0.54930614433405484569762261846126285232
-? basis(x^3+4*x+5)
-[1, x, 1/7*x^2 - 1/7*x - 2/7]
-? basis2(x^3+4*x+5)
-[1, x, 1/7*x^2 - 1/7*x - 2/7]
-? basistoalg(nf,ba)
-mod(x^3 + 5, x^5 - 5*x^3 + 5*x + 25)
-? bernreal(12)
--0.25311355311355311355311355311355311355
-? bernvec(6)
-[1, 1/6, -1/30, 1/42, -1/30, 5/66, -691/2730]
-? bestappr(pi,10000)
-355/113
-? bezout(123456789,987654321)
-[-8, 1, 9]
-? bigomega(12345678987654321)
-8
-? mcurve=initell([0,0,0,-17,0])
-[0, 0, 0, -17, 0, 0, -34, 0, -289, 816, 0, 314432, 1728, Vecsmall([1]), [Vec
-small([128, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]
-? mpoints=[[-1,4],[-4,2]]~
-[[-1, 4], [-4, 2]]~
-? mhbi=bilhell(mcurve,mpoints,[9,24])
-[-0.72448571035980184146215805860545027441, 1.307328627832055544492943428892
-1943056]~
-? bin(1.1,5)
--0.0045457500000000000000000000000000000000
-? binary(65537)
-[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
-? bittest(10^100,100)
-1
-? boundcf(pi,5)
-[3, 7, 15, 1, 292]
-? boundfact(40!+1,100000)
-
-[                                         41 1]
-
-[                                         59 1]
-
-[                                        277 1]
-
-[1217669507565553887239873369513188900554127 1]
-
-? move(0,0,0);box(0,500,500)
-? setrand(1);buchimag(1-10^7,1,1)
-[2416, [1208, 2], [qfi(277, 55, 9028), qfi(1700, 1249, 1700)], 1]
-? setrand(1);bnf=buchinitfu(x^2-x-57,0.2,0.2)
-[mat(3), mat([1, 1, 2]), [-2.7124653051843439746808795106061300699 + 3.14159
-26535897932384626433832795028842*I; 2.7124653051843439746808795106061300699]
-, [1.7903417566977293763292119206302198761, 1.289761953065273502503008607239
-5031018 + 3.1415926535897932384626433832795028842*I, 0.E-37, 0.5005798036324
-5587382620331339071677436; -1.7903417566977293763292119206302198761, -1.2897
-619530652735025030086072395031018, 0.E-38, -0.500579803632455873826203313390
-71677436 + 3.1415926535897932384626433832795028842*I], [[3, [-1, 1]~, 1, 1, 
-[0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 57; 1, 2]], [3, [0, 1]~, 1, 1, [-1, 
-57; 1, 0]], [5, [1, 1]~, 1, 1, [-2, 57; 1, -1]]], 0, [x^2 - x - 57, [2, 0], 
-229, 1, [[1, -7.0663729752107779635959310246705326059; 1, 8.0663729752107779
-635959310246705326058], [1, -7.0663729752107779635959310246705326059; 1, 8.0
-663729752107779635959310246705326058], [1, -7; 1, 8], [2, 1; 1, 115], [229, 
-114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]], [229]], [-7.06637297
-52107779635959310246705326059, 8.0663729752107779635959310246705326058], [1,
- x], [1, 0; 0, 1], [1, 0, 0, 57; 0, 1, 1, 1]], [[3, [3], [[3, 2; 0, 1]]], 2.
-7124653051843439746808795106061300699, 1, [2, -1], [x + 7]], [mat(1), [[0, 0
-]], [[1.7903417566977293763292119206302198761, -1.79034175669772937632921192
-06302198761]]], [0, 0]]
-? buchcertify(bnf)
-1
-? buchfu(bnf)
-[x + 7]
-? setrand(1);buchinitforcefu(x^2-x-100000)
-[mat(5), mat([3, 2, 1, 2, 0, 3, 4, 1, 3, 2, 0, 0, 2, 3, 3, 2, 2, 3]), [-129.
-82045011403975460991182396195022419 + 2.525227547 E-64*I; 129.82045011403975
-460991182396195022419 - 1.691398005 E-65*I], [-41.81126458912994339333950225
-8694361489 + 9.49556775 E-66*I, 9.2399004147902289816376260438840931575 + 3.
-1415926535897932384626433832795028842*I, -11.8746098810754067250973159974311
-61032 + 1.186945968 E-65*I, 129.82045011403975460991182396195022419 + 3.1415
-926535897932384626433832795028842*I, 78.769285110119582234934695659371769545
- + 3.1415926535897932384626433832795028842*I, 843.83292574125840496442685575
-267645724 + 3.1415926535897932384626433832795028842*I, 99.883795405985217941
-669637700687023734 + 1.780418952 E-66*I, -594.223846471886443404737098934077
-97533 + 2.373891936 E-65*I, 552.41258188275650001139759667538361384 + 6.2831
-853071795864769252867665590057684*I, -943.8166642091125376019420340412912927
-2 + 3.798227098 E-65*I, 512.54404927786333037886705989674625866 + 6.28318530
-71795864769252867665590057684*I, 47.668319071568233997332918482707687879 + 3
-.1415926535897932384626433832795028842*I, -1086.2319199838862708766275101783
-094814 + 3.798227098 E-65*I, 232.80982374359817890011490485449930607 + 6.283
-1853071795864769252867665590057684*I, 504.3016123515104053660165366585076775
-9 + 6.2831853071795864769252867665590057684*I, -541.386315978772896320497890
-27161711131 + 3.1415926535897932384626433832795028842*I, -1447.7317003209533
-662215189714163306131 + 3.1415926535897932384626433832795028842*I, 912.61944
-444475616477613125021268707696 + 6.2831853071795864769252867665590057684*I, 
--954.43070903388610816947075247138143845 + 1.899113549 E-65*I; 41.8112645891
-29943393339502258694361489 + 9.49556775 E-66*I, -9.2399004147902289816376260
-438840931575 + 6.2831853071795864769252867665590057684*I, 11.874609881075406
-725097315997431161032 + 3.1415926535897932384626433832795028842*I, -129.8204
-5011403975460991182396195022419 + 3.1415926535897932384626433832795028842*I,
- -78.769285110119582234934695659371769545 + 6.283185307179586476925286766559
-0057684*I, -843.83292574125840496442685575267645724 + 6.28318530717958647692
-52867665590057684*I, -99.883795405985217941669637700687023734 + 3.1415926535
-897932384626433832795028842*I, 594.22384647188644340473709893407797533 + 1.3
-88726783 E-64*I, -552.41258188275650001139759667538361384 + 6.28318530717958
-64769252867665590057684*I, 943.81666420911253760194203404129129272 + 3.14159
-26535897932384626433832795028842*I, -512.54404927786333037886705989674625866
- + 3.1415926535897932384626433832795028842*I, -47.66831907156823399733291848
-2707687879 + 3.1415926535897932384626433832795028842*I, 1086.231919983886270
-8766275101783094814 + 2.587542211 E-64*I, -232.80982374359817890011490485449
-930607 + 3.1415926535897932384626433832795028842*I, -504.3016123515104053660
-1653665850767759 + 3.1415926535897932384626433832795028842*I, 541.3863159787
-7289632049789027161711131 + 1.317510025 E-64*I, 1447.73170032095336622151897
-14163306131 + 3.418404388 E-64*I, -912.61944444475616477613125021268707696 +
- 6.2831853071795864769252867665590057684*I, 954.4307090338861081694707524713
-8143845 + 2.219588961 E-64*I], [[2, [1, 1]~, 1, 1, [0, 100000; 1, 1]], [5, [
-4, 1]~, 1, 1, [0, 100000; 1, 1]], [13, [-6, 1]~, 1, 1, [5, 100000; 1, 6]], [
-2, [2, 1]~, 1, 1, [1, 100000; 1, 2]], [5, [5, 1]~, 1, 1, [-1, 100000; 1, 0]]
-, [7, [3, 1]~, 2, 1, [3, 100000; 1, 4]], [13, [5, 1]~, 1, 1, [-6, 100000; 1,
- -5]], [29, [-14, 1]~, 1, 1, [13, 100000; 1, 14]], [29, [13, 1]~, 1, 1, [-14
-, 100000; 1, -13]], [17, [14, 1]~, 1, 1, [2, 100000; 1, 3]], [17, [19, 1]~, 
-1, 1, [-3, 100000; 1, -2]], [23, [-7, 1]~, 1, 1, [6, 100000; 1, 7]], [23, [6
-, 1]~, 1, 1, [-7, 100000; 1, -6]], [31, [23, 1]~, 1, 1, [7, 100000; 1, 8]], 
-[31, [38, 1]~, 1, 1, [-8, 100000; 1, -7]], [41, [-7, 1]~, 1, 1, [6, 100000; 
-1, 7]], [41, [6, 1]~, 1, 1, [-7, 100000; 1, -6]], [43, [-16, 1]~, 1, 1, [15,
- 100000; 1, 16]], [43, [15, 1]~, 1, 1, [-16, 100000; 1, -15]]], 0, [x^2 - x 
-- 100000, [2, 0], 400001, 1, [[1, -315.72816130129840161392089489603747004; 
-1, 316.72816130129840161392089489603747004], [1, -315.7281613012984016139208
-9489603747004; 1, 316.72816130129840161392089489603747004], [1, -316; 1, 317
-], [2, 1; 1, 200001], [400001, 200000; 0, 1], [200001, -1; -1, 2], [400001, 
-[200000, 100000; 1, 200001]], [7, 57143]], [-315.728161301298401613920894896
-03747004, 316.72816130129840161392089489603747004], [1, x], [1, 0; 0, 1], [1
-, 0, 0, 100000; 0, 1, 1, 1]], [[5, [5], [[2, 1; 0, 1]]], 129.820450114039754
-60991182396195022419, 1, [2, -1], [37955488401901378100630325489636915406833
-6082609238336*x + 119836165644250789990462835950022871665178127611316131167]
-], [mat(1), [[0, 0]], [[-41.811264589129943393339502258694361489 + 9.4955677
-5 E-66*I, 41.811264589129943393339502258694361489 + 9.49556775 E-66*I]]], [0
-, 0]]
-? setrand(1);bnf=buchinitfu(x^2-x-57,0.2,0.2)
-[mat(3), mat([1, 1, 2]), [-2.7124653051843439746808795106061300699 + 3.14159
-26535897932384626433832795028842*I; 2.7124653051843439746808795106061300699]
-, [1.7903417566977293763292119206302198761, 1.289761953065273502503008607239
-5031018 + 3.1415926535897932384626433832795028842*I, 0.E-37, 0.5005798036324
-5587382620331339071677436; -1.7903417566977293763292119206302198761, -1.2897
-619530652735025030086072395031018, 0.E-38, -0.500579803632455873826203313390
-71677436 + 3.1415926535897932384626433832795028842*I], [[3, [-1, 1]~, 1, 1, 
-[0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 57; 1, 2]], [3, [0, 1]~, 1, 1, [-1, 
-57; 1, 0]], [5, [1, 1]~, 1, 1, [-2, 57; 1, -1]]], 0, [x^2 - x - 57, [2, 0], 
-229, 1, [[1, -7.0663729752107779635959310246705326059; 1, 8.0663729752107779
-635959310246705326058], [1, -7.0663729752107779635959310246705326059; 1, 8.0
-663729752107779635959310246705326058], [1, -7; 1, 8], [2, 1; 1, 115], [229, 
-114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]], [229]], [-7.06637297
-52107779635959310246705326059, 8.0663729752107779635959310246705326058], [1,
- x], [1, 0; 0, 1], [1, 0, 0, 57; 0, 1, 1, 1]], [[3, [3], [[3, 2; 0, 1]]], 2.
-7124653051843439746808795106061300699, 1, [2, -1], [x + 7]], [mat(1), [[0, 0
-]], [[1.7903417566977293763292119206302198761, -1.79034175669772937632921192
-06302198761]]], [0, 0]]
-? setrand(1);buchreal(10^9-3,0,0.5,0.5)
-[4, [4], [qfr(199, 31533, -7123, 0.E-57)], 2800.6252519070160764863706217370
-745514]
-? setrand(1);buchgen(x^4-7,0.2,0.2)
-
-[                                                     x^4 - 7]
-
-[                                                      [2, 1]]
-
-[                                                 [-87808, 1]]
-
-[                                            [1, x, x^2, x^3]]
-
-[[2, [2], [[3, 2, 2, 2; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1]]]]
-
-[                     14.229975145405511722395637833443108790]
-
-[                                                           1]
-
-[                                                     [2, -1]]
-
-[                                  [x^2 - x - 1, x^2 + x - 1]]
-
-? setrand(1);buchgenfu(x^2-x-100000)
-
-[                       x^2 - x - 100000]
-
-[                                 [2, 0]]
-
-[                            [400001, 1]]
-
-[                                 [1, x]]
-
-[              [5, [5], [[13, 7; 0, 1]]]]
-
-[129.82045011403975460991182396195022417]
-
-[                                      1]
-
-[                                [2, -1]]
-
-[                                    [;]]
-
-? setrand(1);buchgenforcefu(x^2-x-100000)
-
-[x^2 - x - 100000]
-
-[[2, 0]]
-
-[[400001, 1]]
-
-[[1, x]]
-
-[[5, [5], [[2, 1; 0, 1]]]]
-
-[129.82045011403975460991182396195022419]
-
-[1]
-
-[[2, -1]]
-
-[[379554884019013781006303254896369154068336082609238336*x + 119836165644250
-789990462835950022871665178127611316131167]]
-
-? setrand(1);buchgenfu(x^4+24*x^2+585*x+1791,0.1,0.1)
-
-[x^4 + 24*x^2 + 585*x + 1791]
-
-[[0, 2]]
-
-[[18981, 3087]]
-
-[[1, -10/1029*x^3 + 13/343*x^2 - 165/343*x - 1135/343, 1/147*x^3 + 1/147*x^2
- - 8/49*x + 138/49, -26/1029*x^3 + 170/1029*x^2 - 429/343*x - 2951/343]]
-
-[[4, [4], [[7, 2, 0, 6; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1]]]]
-
-[3.7941269688216589341408274220859400303]
-
-[1]
-
-[[6, 10/1029*x^3 - 13/343*x^2 + 165/343*x + 1478/343]]
-
-[[1/147*x^3 + 1/147*x^2 - 8/49*x - 9/49]]
-
-? buchnarrow(bnf)
-[3, [3], [[3, 2; 0, 1]]]
-? buchray(bnf,[[5,3;0,1],[1,0]])
-[12, [12], [[3, 2; 0, 1]]]
-? bnr=buchrayinitgen(bnf,[[5,3;0,1],[1,0]])
-[[mat(3), mat([1, 1, 2]), [-2.7124653051843439746808795106061300699 + 3.1415
-926535897932384626433832795028842*I; 2.7124653051843439746808795106061300699
-], [1.7903417566977293763292119206302198761, 1.28976195306527350250300860723
-95031018 + 3.1415926535897932384626433832795028842*I, 0.E-37, 0.500579803632
-45587382620331339071677436; -1.7903417566977293763292119206302198761, -1.289
-7619530652735025030086072395031018, 0.E-38, -0.50057980363245587382620331339
-071677436 + 3.1415926535897932384626433832795028842*I], [[3, [-1, 1]~, 1, 1,
- [0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 57; 1, 2]], [3, [0, 1]~, 1, 1, [-1,
- 57; 1, 0]], [5, [1, 1]~, 1, 1, [-2, 57; 1, -1]]], 0, [x^2 - x - 57, [2, 0],
- 229, 1, [[1, -7.0663729752107779635959310246705326059; 1, 8.066372975210777
-9635959310246705326058], [1, -7.0663729752107779635959310246705326059; 1, 8.
-0663729752107779635959310246705326058], [1, -7; 1, 8], [2, 1; 1, 115], [229,
- 114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]], [229]], [-7.0663729
-752107779635959310246705326059, 8.0663729752107779635959310246705326058], [1
-, x], [1, 0; 0, 1], [1, 0, 0, 57; 0, 1, 1, 1]], [[3, [3], [[3, 2; 0, 1]]], 2
-.7124653051843439746808795106061300699, 1, [2, -1], [x + 7]], [mat(1), [[0, 
-0]], [[1.7903417566977293763292119206302198761, -1.7903417566977293763292119
-206302198761]]], [0, [mat([[5, 1]~, 1])]]], [[[5, 3; 0, 1], [1, 0]], [8, [4,
- 2], [2, [-4, 0]~]], mat([[5, [-2, 1]~, 1, 1, [1, 57; 1, 2]], 1]), [[[[4], [
-2], [2], [Vecsmall([0])], 1]], [[2], [-4], [Vecsmall([1])]]], [1, 0; 0, 1]],
- [1], mat([1, -3, -6]), [12, [12], [[3, 2; 0, 1]]], [[0, 1; 0, 0], [-1, -1; 
-1, -1], 1]]
-? bnr2=buchrayinitgen(bnf,[[25,13;0,1],[1,1]])
-[[mat(3), mat([1, 1, 2]), [-2.7124653051843439746808795106061300699 + 3.1415
-926535897932384626433832795028842*I; 2.7124653051843439746808795106061300699
-], [1.7903417566977293763292119206302198761, 1.28976195306527350250300860723
-95031018 + 3.1415926535897932384626433832795028842*I, 0.E-37, 0.500579803632
-45587382620331339071677436; -1.7903417566977293763292119206302198761, -1.289
-7619530652735025030086072395031018, 0.E-38, -0.50057980363245587382620331339
-071677436 + 3.1415926535897932384626433832795028842*I], [[3, [-1, 1]~, 1, 1,
- [0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 57; 1, 2]], [3, [0, 1]~, 1, 1, [-1,
- 57; 1, 0]], [5, [1, 1]~, 1, 1, [-2, 57; 1, -1]]], 0, [x^2 - x - 57, [2, 0],
- 229, 1, [[1, -7.0663729752107779635959310246705326059; 1, 8.066372975210777
-9635959310246705326058], [1, -7.0663729752107779635959310246705326059; 1, 8.
-0663729752107779635959310246705326058], [1, -7; 1, 8], [2, 1; 1, 115], [229,
- 114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]], [229]], [-7.0663729
-752107779635959310246705326059, 8.0663729752107779635959310246705326058], [1
-, x], [1, 0; 0, 1], [1, 0, 0, 57; 0, 1, 1, 1]], [[3, [3], [[3, 2; 0, 1]]], 2
-.7124653051843439746808795106061300699, 1, [2, -1], [x + 7]], [mat(1), [[0, 
-0]], [[1.7903417566977293763292119206302198761, -1.7903417566977293763292119
-206302198761]]], [0, [mat([[5, 1]~, 1])]]], [[[25, 13; 0, 1], [1, 1]], [80, 
-[20, 2, 2], [2, [-24, 0]~, [2, 2]~]], mat([[5, [-2, 1]~, 1, 1, [1, 57; 1, 2]
-], 2]), [[[[4], [2], [2], [Vecsmall([0, 0])], 1], [[5], [6], [6], [Vecsmall(
-[0, 0])], mat([1/5, -13/5])]], [[2, 2], [-24, [2, 2]~], [Vecsmall([0, 1]), V
-ecsmall([1, 1])]]], [1, -12, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1]], [1], mat([1, -3
-, -6, -6]), [12, [12], [[3, 2; 0, 1]]], [[0, 2, 0; -1, 10, 0], [-2, 0; 0, -1
-0], 2]]
-? bytesize(%)
-4768
-? ceil(-2.5)
--2
-? centerlift(mod(456,555))
--99
-? cf(pi)
-[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, 13, 1, 4, 2, 6, 6]
-? cf2([1,3,5,7,9],(exp(1)-1)/(exp(1)+1))
-[0, 6, 10, 42, 30]
-? changevar(x+y,[z,t])
-  ***   at top-level: changevar(x+y,[z,t])
-  ***                 ^--------------------
-  *** changevar: this function no longer exists.
-? char([1,2;3,4],z)
-z^2 - 5*z - 2
-? char(mod(x^2+x+1,x^3+5*x+1),z)
-z^3 + 7*z^2 + 16*z - 19
-? char1([1,2;3,4],z)
-z^2 - 5*z - 2
-? char2(mod(1,8191)*[1,2;3,4],z)
-z^2 + mod(8186, 8191)*z + mod(8189, 8191)
-? acurve=chell(acurve,[-1,1,2,3])
-[-4, -1, -7, -12, -12, 12, 4, 1, -1, 48, -216, 37, 110592/37, Vecsmall([1]),
- [Vecsmall([128, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]
-? chinese(mod(7,15),mod(13,21))
-mod(97, 105)
-? apoint=chptell(apoint,[-1,1,2,3])
-[1, 3]
-? isoncurve(acurve,apoint)
-1
-? classno(-12391)
-63
-? classno(1345)
-6
-? classno2(-12391)
-63
-? classno2(1345)
-6
-? coeff(sin(x),7)
--1/5040
-? compimag(qfi(2,1,3),qfi(2,1,3))
-qfi(2, -1, 3)
-? compo(1+o(7^4),3)
-1
-? compositum(x^4-4*x+2,x^3-x-1)
-[x^12 - 4*x^10 + 8*x^9 + 12*x^8 + 12*x^7 + 138*x^6 + 132*x^5 - 43*x^4 + 58*x
-^2 - 128*x - 5]
-? compositum2(x^4-4*x+2,x^3-x-1)
-[[x^12 - 4*x^10 + 8*x^9 + 12*x^8 + 12*x^7 + 138*x^6 + 132*x^5 - 43*x^4 + 58*
-x^2 - 128*x - 5, mod(-279140305176/29063006931199*x^11 + 129916611552/290630
-06931199*x^10 + 1272919322296/29063006931199*x^9 - 2813750209005/29063006931
-199*x^8 - 2859411937992/29063006931199*x^7 - 414533880536/29063006931199*x^6
- - 35713977492936/29063006931199*x^5 - 17432607267590/29063006931199*x^4 + 4
-9785595543672/29063006931199*x^3 + 9423768373204/29063006931199*x^2 - 427797
-76146743/29063006931199*x + 37962587857138/29063006931199, x^12 - 4*x^10 + 8
-*x^9 + 12*x^8 + 12*x^7 + 138*x^6 + 132*x^5 - 43*x^4 + 58*x^2 - 128*x - 5), m
-od(-279140305176/29063006931199*x^11 + 129916611552/29063006931199*x^10 + 12
-72919322296/29063006931199*x^9 - 2813750209005/29063006931199*x^8 - 28594119
-37992/29063006931199*x^7 - 414533880536/29063006931199*x^6 - 35713977492936/
-29063006931199*x^5 - 17432607267590/29063006931199*x^4 + 49785595543672/2906
-3006931199*x^3 + 9423768373204/29063006931199*x^2 - 13716769215544/290630069
-31199*x + 37962587857138/29063006931199, x^12 - 4*x^10 + 8*x^9 + 12*x^8 + 12
-*x^7 + 138*x^6 + 132*x^5 - 43*x^4 + 58*x^2 - 128*x - 5), -1]]
-? comprealraw(qfr(5,3,-1,0.),qfr(7,1,-1,0.))
-qfr(35, 43, 13, 0.E-38)
-? concat([1,2],[3,4])
-[1, 2, 3, 4]
-? conductor(bnf,[[25,13;0,1],[1,1]])
-[[[5, 3; 0, 1], [1, 0]], [12, [12], [[3, 2; 0, 1]]], mat(12)]
-? conductorofchar(bnr,[2])
-[[5, 3; 0, 1], [0, 0]]
-? conj(1+i)
-1 - I
-? conjvec(mod(x^2+x+1,x^3-x-1))
-[4.0795956234914387860104177508366260326, 0.46020218825428060699479112458168
-698369 + 0.18258225455744299269398828369501930574*I, 0.460202188254280606994
-79112458168698369 - 0.18258225455744299269398828369501930574*I]~
-? content([123,456,789,234])
-3
-? convol(sin(x),x*cos(x))
-x + 1/12*x^3 + 1/2880*x^5 + 1/3628800*x^7 + 1/14631321600*x^9 + 1/1448500838
-40000*x^11 + 1/2982752926433280000*x^13 + 1/114000816848279961600000*x^15 + 
-O(x^17)
-? core(54713282649239)
-5471
-? core2(54713282649239)
-[5471, 100003]
-? coredisc(54713282649239)
-21884
-? coredisc2(54713282649239)
-[21884, 100003/2]
-? cos(1)
-0.54030230586813971740093660744297660373
-? cosh(1)
-1.5430806348152437784779056207570616826
-? move(0,200,150)
-? cursor(0)
-? cvtoi(1.7)
-1
-? cyclo(105)
-x^48 + x^47 + x^46 - x^43 - x^42 - 2*x^41 - x^40 - x^39 + x^36 + x^35 + x^34
- + x^33 + x^32 + x^31 - x^28 - x^26 - x^24 - x^22 - x^20 + x^17 + x^16 + x^1
-5 + x^14 + x^13 + x^12 - x^9 - x^8 - 2*x^7 - x^6 - x^5 + x^2 + x + 1
-? degree(x^3/(x-1))
-2
-? denom(12345/54321)
-18107
-? deplin(mod(1,7)*[2,-1;1,3])
-[-3, 1]~
-? deriv((x+y)^5,y)
-5*x^4 + 20*y*x^3 + 30*y^2*x^2 + 20*y^3*x + 5*y^4
-? ((x+y)^5)'
-5*x^4 + 20*y*x^3 + 30*y^2*x^2 + 20*y^3*x + 5*y^4
-? det([1,2,3;1,5,6;9,8,7])
--30
-? det2([1,2,3;1,5,6;9,8,7])
--30
-? detint([1,2,3;4,5,6])
-3
-? diagonal([2,4,6])
-
-[2 0 0]
-
-[0 4 0]
-
-[0 0 6]
-
-? dilog(0.5)
-0.58224052646501250590265632015968010874
-? dz=vector(30,k,1);dd=vector(30,k,k==1);dm=dirdiv(dd,dz)
-[1, -1, -1, 0, -1, 1, -1, 0, 0, 1, -1, 0, -1, 1, 1, 0, -1, 0, -1, 0, 1, 1, -
-1, 0, 0, 1, 0, 0, -1, -1]
-? deu=direuler(p=2,100,1/(1-apell(acurve,p)*x+if(acurve[12]%p,p,0)*x^2))
-[1, -2, -3, 2, -2, 6, -1, 0, 6, 4, -5, -6, -2, 2, 6, -4, 0, -12, 0, -4, 3, 1
-0, 2, 0, -1, 4, -9, -2, 6, -12, -4, 8, 15, 0, 2, 12, -1, 0, 6, 0, -9, -6, 2,
- -10, -12, -4, -9, 12, -6, 2, 0, -4, 1, 18, 10, 0, 0, -12, 8, 12, -8, 8, -6,
- -8, 4, -30, 8, 0, -6, -4, 9, 0, -1, 2, 3, 0, 5, -12, 4, 8, 9, 18, -15, 6, 0
-, -4, -18, 0, 4, 24, 2, 4, 12, 18, 0, -24, 4, 12, -30, -2]
-? anell(acurve,100)==deu
-1
-? dirmul(abs(dm),dz)
-[1, 2, 2, 2, 2, 4, 2, 2, 2, 4, 2, 4, 2, 4, 4, 2, 2, 4, 2, 4, 4, 4, 2, 4, 2, 
-4, 2, 4, 2, 8]
-? dirzetak(initalg(x^3-10*x+8),30)
-[1, 2, 0, 3, 1, 0, 0, 4, 0, 2, 1, 0, 0, 0, 0, 5, 1, 0, 0, 3, 0, 2, 0, 0, 2, 
-0, 1, 0, 1, 0]
-? disc(x^3+4*x+12)
--4144
-? discf(x^3+4*x+12)
--1036
-? discrayabs(bnr,mat(6))
-[12, 12, 18026977100265125]
-? discrayabs(bnr)
-[24, 12, 40621487921685401825918161408203125]
-? discrayabscond(bnr2)
-0
-? lu=ideallistunitgen(bnf,55);discrayabslist(bnf,lu)
-[[[6, 6, mat([229, 3])]], [], [[], []], [[]], [[12, 12, [5, 3; 229, 6]], [12
-, 12, [5, 3; 229, 6]]], [], [], [], [[], [], []], [], [[], []], [[], []], []
-, [], [[24, 24, [3, 6; 5, 9; 229, 12]], [], [], [24, 24, [3, 6; 5, 9; 229, 1
-2]]], [[]], [[], []], [], [[18, 18, [19, 6; 229, 9]], [18, 18, [19, 6; 229, 
-9]]], [[], []], [], [], [], [], [[], [24, 24, [5, 12; 229, 12]], []], [], [[
-], [], [], []], [], [], [], [], [], [[], [12, 12, [3, 3; 11, 3; 229, 6]], [1
-2, 12, [3, 3; 11, 3; 229, 6]], []], [], [], [[18, 18, [2, 12; 3, 12; 229, 9]
-], [], [18, 18, [2, 12; 3, 12; 229, 9]]], [[12, 12, [37, 3; 229, 6]], [12, 1
-2, [37, 3; 229, 6]]], [], [], [], [], [], [[], []], [[], []], [[], [], [], [
-], [], []], [], [], [[12, 12, [2, 12; 3, 3; 229, 6]], [12, 12, [2, 12; 3, 3;
- 229, 6]]], [[18, 18, [7, 12; 229, 9]]], [], [[], [], [], []], [], [[], []],
- [], [[], [24, 24, [5, 9; 11, 6; 229, 12]], [24, 24, [5, 9; 11, 6; 229, 12]]
-, []]]
-? discrayabslistlong(bnf,20)
-[[[[matrix(0,2,j,k,0), 6, 6, mat([229, 3])]], [], [[mat([12, 1]), 0, 0, 0], 
-[mat([13, 1]), 0, 0, 0]], [[mat([10, 1]), 0, 0, 0]], [[mat([20, 1]), 12, 12,
- [5, 3; 229, 6]], [mat([21, 1]), 12, 12, [5, 3; 229, 6]]], [], [], [], [[mat
-([12, 2]), 0, 0, 0], [[12, 1; 13, 1], 0, 0, 0], [mat([13, 2]), 0, 0, 0]], []
-, [[mat([44, 1]), 0, 0, 0], [mat([45, 1]), 0, 0, 0]], [[[10, 1; 12, 1], 0, 0
-, 0], [[10, 1; 13, 1], 0, 0, 0]], [], [], [[[12, 1; 20, 1], 24, 24, [3, 6; 5
-, 9; 229, 12]], [[13, 1; 20, 1], 0, 0, 0], [[12, 1; 21, 1], 0, 0, 0], [[13, 
-1; 21, 1], 24, 24, [3, 6; 5, 9; 229, 12]]], [[mat([10, 2]), 0, 0, 0]], [[mat
-([68, 1]), 0, 0, 0], [mat([69, 1]), 0, 0, 0]], [], [[mat([76, 1]), 18, 18, [
-19, 6; 229, 9]], [mat([77, 1]), 18, 18, [19, 6; 229, 9]]], [[[10, 1; 20, 1],
- 0, 0, 0], [[10, 1; 21, 1], 0, 0, 0]]]]
-? discrayrel(bnr,mat(6))
-[6, 2, [125, 13; 0, 1]]
-? discrayrel(bnr)
-[12, 1, [1953125, 1160888; 0, 1]]
-? discrayrelcond(bnr2)
-0
-? divisors(8!)
-[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 24, 28, 30, 32, 
-35, 36, 40, 42, 45, 48, 56, 60, 63, 64, 70, 72, 80, 84, 90, 96, 105, 112, 12
-0, 126, 128, 140, 144, 160, 168, 180, 192, 210, 224, 240, 252, 280, 288, 315
-, 320, 336, 360, 384, 420, 448, 480, 504, 560, 576, 630, 640, 672, 720, 840,
- 896, 960, 1008, 1120, 1152, 1260, 1344, 1440, 1680, 1920, 2016, 2240, 2520,
- 2688, 2880, 3360, 4032, 4480, 5040, 5760, 6720, 8064, 10080, 13440, 20160, 
-40320]
-? divres(345,123)
-[2, 99]~
-? divres(x^7-1,x^5+1)
-[x^2, -x^2 - 1]~
-? divsum(8!,x,x)
-159120
-? postdraw([0,0,0])
-? eigen([1,2,3;4,5,6;7,8,9])
-
-[1 -1.2833494518006402717978106547571267252 0.283349451800640271797810654757
-12672521]
-
-[-2 -0.14167472590032013589890532737856336261 0.6416747259003201358989053273
-7856336260]
-
-[1 1 1]
-
-? eint1(2)
-0.048900510708061119567239835228049522315
-? erfc(2)
-0.0046777349810472658379307436327470713891
-? eta(q)
-1 - q - q^2 + q^5 + q^7 - q^12 - q^15 + O(q^17)
-? euler
-0.57721566490153286060651209008240243104
-? z=y;y=x;eval(z)
-x
-? exp(1)
-2.7182818284590452353602874713526624978
-? extract([1,2,3,4,5,6,7,8,9,10],1000)
-[4, 6, 7, 8, 9, 10]
-? 10!
-3628800
-? fact(10)
-3628800.0000000000000000000000000000000
-? factcantor(x^11+1,7)
-
-[mod(1, 7)*x + mod(1, 7) 1]
-
-[mod(1, 7)*x^10 + mod(6, 7)*x^9 + mod(1, 7)*x^8 + mod(6, 7)*x^7 + mod(1, 7)*
-x^6 + mod(6, 7)*x^5 + mod(1, 7)*x^4 + mod(6, 7)*x^3 + mod(1, 7)*x^2 + mod(6,
- 7)*x + mod(1, 7) 1]
-
-? centerlift(lift(factfq(x^3+x^2+x-1,3,t^3+t^2+t-1)))
-
-[            x - t 1]
-
-[x + (t^2 + t - 1) 1]
-
-[   x + (-t^2 - 1) 1]
-
-? factmod(x^11+1,7)
-
-[mod(1, 7)*x + mod(1, 7) 1]
-
-[mod(1, 7)*x^10 + mod(6, 7)*x^9 + mod(1, 7)*x^8 + mod(6, 7)*x^7 + mod(1, 7)*
-x^6 + mod(6, 7)*x^5 + mod(1, 7)*x^4 + mod(6, 7)*x^3 + mod(1, 7)*x^2 + mod(6,
- 7)*x + mod(1, 7) 1]
-
-? factor(17!+1)
-
-[    661 1]
-
-[ 537913 1]
-
-[1000357 1]
-
-? p=x^5+3021*x^4-786303*x^3-6826636057*x^2-546603588746*x+3853890514072057
-x^5 + 3021*x^4 - 786303*x^3 - 6826636057*x^2 - 546603588746*x + 385389051407
-2057
-? fa=[11699,6;2392997,2;4987333019653,2]
-
-[        11699 6]
-
-[      2392997 2]
-
-[4987333019653 2]
-
-? factoredbasis(p,fa)
-[1, x, x^2, 1/11699*x^3 + 1847/11699*x^2 - 132/11699*x - 2641/11699, 1/13962
-3738889203638909659*x^4 - 1552451622081122020/139623738889203638909659*x^3 +
- 418509858130821123141/139623738889203638909659*x^2 - 6810913798507599407313
-4/139623738889203638909659*x - 13185339461968406/58346808996920447]
-? factoreddiscf(p,fa)
-136866601
-? factoredpolred(p,fa)
-[x - 1, x^5 - 80*x^3 - 223*x^2 + 800*x + 2671]
-? factoredpolred2(p,fa)
-[x - 1, x^5 - 80*x^3 - 223*x^2 + 800*x + 2671]
-? factornf(x^3+x^2-2*x-1,t^3+t^2-2*t-1)
-
-[         x + mod(-t, t^3 + t^2 - 2*t - 1) 1]
-
-[   x + mod(-t^2 + 2, t^3 + t^2 - 2*t - 1) 1]
-
-[x + mod(t^2 + t - 1, t^3 + t^2 - 2*t - 1) 1]
-
-? factorpadic(apol,7,8)
-
-[(1 + O(7^8))*x + (6 + 2*7^2 + 2*7^3 + 3*7^4 + 2*7^5 + 6*7^6 + O(7^8)) 1]
-
-[(1 + O(7^8))*x^2 + (1 + 6*7 + 4*7^2 + 4*7^3 + 3*7^4 + 4*7^5 + 6*7^7 + O(7^8
-))*x + (6 + 5*7 + 3*7^2 + 6*7^3 + 7^4 + 3*7^5 + 2*7^6 + 5*7^7 + O(7^8)) 1]
-
-? factorpadic2(apol,7,8)
-
-[(1 + O(7^8))*x + (6 + 2*7^2 + 2*7^3 + 3*7^4 + 2*7^5 + 6*7^6 + O(7^8)) 1]
-
-[(1 + O(7^8))*x^2 + (1 + 6*7 + 4*7^2 + 4*7^3 + 3*7^4 + 4*7^5 + 6*7^7 + O(7^8
-))*x + (6 + 5*7 + 3*7^2 + 6*7^3 + 7^4 + 3*7^5 + 2*7^6 + 5*7^7 + O(7^8)) 1]
-
-? factpol(x^15-1,3,1)
-
-[                              x - 1 1]
-
-[                        x^2 + x + 1 1]
-
-[            x^4 + x^3 + x^2 + x + 1 1]
-
-[x^8 - x^7 + x^5 - x^4 + x^3 - x + 1 1]
-
-? factpol(x^15-1,0,1)
-
-[                              x - 1 1]
-
-[                        x^2 + x + 1 1]
-
-[            x^4 + x^3 + x^2 + x + 1 1]
-
-[x^8 - x^7 + x^5 - x^4 + x^3 - x + 1 1]
-
-? fibo(100)
-354224848179261915075
-? floor(-1/2)
--1
-? floor(-2.5)
--3
-? for(x=1,5,print(x!))
-1
-2
-6
-24
-120
-? fordiv(10,x,print(x))
-1
-2
-5
-10
-? forprime(p=1,30,print(p))
-2
-3
-5
-7
-11
-13
-17
-19
-23
-29
-? forstep(x=0,pi,pi/12,print(sin(x)))
-0.E-38
-0.25881904510252076234889883762404832835
-0.50000000000000000000000000000000000000
-0.70710678118654752440084436210484903928
-0.86602540378443864676372317075293618347
-0.96592582628906828674974319972889736763
-1.0000000000000000000000000000000000000
-0.96592582628906828674974319972889736764
-0.86602540378443864676372317075293618348
-0.70710678118654752440084436210484903931
-0.50000000000000000000000000000000000003
-0.25881904510252076234889883762404832839
-4.70197740 E-38
-? forvec(x=[[1,3],[-2,2]],print1([x[1],x[2]]," "));print(" ");
-[1, -2] [1, -1] [1, 0] [1, 1] [1, 2] [2, -2] [2, -1] [2, 0] [2, 1] [2, 2] [3
-, -2] [3, -1] [3, 0] [3, 1] [3, 2]  
-? frac(-2.7)
-0.30000000000000000000000000000000000000
-? galois(x^6-3*x^2-1)
-[12, 1, 1, "A_4(6) = [2^2]3"]
-? nf3=initalg(x^6+108);galoisconj(nf3)
-[-x, x, -1/12*x^4 - 1/2*x, -1/12*x^4 + 1/2*x, 1/12*x^4 - 1/2*x, 1/12*x^4 + 1
-/2*x]~
-? aut=%[2];galoisapply(nf3,aut,mod(x^5,x^6+108))
-mod(x^5, x^6 + 108)
-? gamh(10)
-1133278.3889487855673345741655888924756
-? gamma(10.5)
-1133278.3889487855673345741655888924756
-? gauss(hilbert(10),[1,2,3,4,5,6,7,8,9,0]~)
-[9236800, -831303990, 18288515520, -170691240720, 832112321040, -23298940665
-00, 3883123564320, -3803844432960, 2020775945760, -449057772020]~
-? gaussmodulo([2,3;5,4],[7,11]~,[1,4]~)
-[-5, -1]~
-? gaussmodulo2([2,3;5,4],[7,11]~,[1,4]~)
-[[-5, -1]~, [4, 9; -5, 8]]
-? gcd(12345678,87654321)
-9
-? getrand()
-Vecsmall([1220248512, -582244995, 485580680, -1643185972, -2103930341, -9694
-07356, 336208700, 1439513079, -1910826353, -2042699820, 222745475, 183991374
-4, -2047550919, -1071833333, -2039471221, 1515565777, 534035968, 1434812685,
- 491096522, 1540420857, 68034275, 307497241, 177037322, -1910209700, 1688743
-598, -1877071123, -1198166641, 184781149, -180667067, 2125896856, 2115414405
-, -1331546909, 182563306, -1668813554, -146811882, -511262153, -14099254, 20
-08709351, 1769611100, 1617398068, 1847419819, -1678454862, -2004927148, 2020
-407188, -253419536, 501072002, 1183173933, -1588428527, 1264275720, 20001149
-40, -152481498, 1985229903, 1344784530, -2033617121, 494748780, -1133870016,
- 2127752844, 1447882915, -1884321492, 982974715, -2039242948, 2142404071, -3
-80331009, -1264605663, -770161853, 430911112, 290533278, -927756173, -186399
-3863, -1149321316, 1135347562, 1205814267, -1293541270, 806702053, -63173041
-9, 2120242162, 1259144634, -259813841, -1748638985, -481185123, 459357013, 1
-39809444, -1094803819, -956855999, -365358884, -39929854, 1096255899, 201771
-3822, 1464920131, -953056017, -564919260, -823296656, -777957747, -116664011
-9, -409307993, -160471003, 1950881272, 2140986234, 1617664168, -179627494, 1
-618528081, 949905077, 1996141541, -1056917386, -1728441144, -389361315, 1869
-686534, -2072896478, -751871013, -1178639831, 1962418281, -690140718, -19182
-97446, -68103184, -1955591658, 1354080479, -14042013, -129902947, 201832307,
- -620608254, -1243546160, -48623379, -479563203, -732434165, -294635956, 193
-5166130, 42381710, 876975196, 64, -967805022])
-? globalred(acurve)
-[37, [1, -1, 2, 2], 1, mat([37, 1]), [[1, 5, 0, 1]]]
-? hclassno(2000003)
-357
-? hell(acurve,apoint)
-0.81778253183950144377417759611107234575
-? hell2(acurve,apoint)
-0.81778253183950144377417759611107234597
-? hermite(amat=1/hilbert(7))
-
-[420   0    0    0   210  168   175]
-
-[  0 840    0    0     0    0   504]
-
-[  0   0 2520    0     0    0  1260]
-
-[  0   0    0 2520     0    0   840]
-
-[  0   0    0    0 13860    0  6930]
-
-[  0   0    0    0     0 5544     0]
-
-[  0   0    0    0     0    0 12012]
-
-? hermite2(amat)
-[[420, 0, 0, 0, 210, 168, 175; 0, 840, 0, 0, 0, 0, 504; 0, 0, 2520, 0, 0, 0,
- 1260; 0, 0, 0, 2520, 0, 0, 840; 0, 0, 0, 0, 13860, 0, 6930; 0, 0, 0, 0, 0, 
-5544, 0; 0, 0, 0, 0, 0, 0, 12012], [420, 420, 840, 630, 2982, 1092, 4159; 21
-0, 280, 630, 504, 2415, 876, 3395; 140, 210, 504, 420, 2050, 749, 2901; 105,
- 168, 420, 360, 1785, 658, 2542; 84, 140, 360, 315, 1582, 588, 2266; 70, 120
-, 315, 280, 1421, 532, 2046; 60, 105, 280, 252, 1290, 486, 1866]]
-? hermitemod(amat,detint(amat))
-
-[420   0    0    0   210  168   175]
-
-[  0 840    0    0     0    0   504]
-
-[  0   0 2520    0     0    0  1260]
-
-[  0   0    0 2520     0    0   840]
-
-[  0   0    0    0 13860    0  6930]
-
-[  0   0    0    0     0 5544     0]
-
-[  0   0    0    0     0    0 12012]
-
-? hermiteperm(amat)
-[[360360, 0, 0, 0, 0, 144144, 300300; 0, 27720, 0, 0, 0, 0, 22176; 0, 0, 277
-20, 0, 0, 0, 6930; 0, 0, 0, 2520, 0, 0, 840; 0, 0, 0, 0, 2520, 0, 1260; 0, 0
-, 0, 0, 0, 168, 0; 0, 0, 0, 0, 0, 0, 7], [51480, 4620, 5544, 630, 840, 20676
-, 48619; 45045, 3960, 4620, 504, 630, 18074, 42347; 40040, 3465, 3960, 420, 
-504, 16058, 37523; 36036, 3080, 3465, 360, 420, 14448, 33692; 32760, 2772, 3
-080, 315, 360, 13132, 30574; 30030, 2520, 2772, 280, 315, 12036, 27986; 2772
-0, 2310, 2520, 252, 280, 11109, 25803], Vecsmall([7, 6, 5, 4, 3, 2, 1])]
-? hess(hilbert(7))
-
-[1 90281/58800 -1919947/4344340 4858466341/1095033030 -77651417539/819678732
-6 3386888964/106615355 1/2]
-
-[1/3 43/48 38789/5585580 268214641/109503303 -581330123627/126464718744 4365
-450643/274153770 1/4]
-
-[0 217/2880 442223/7447440 53953931/292008808 -32242849453/168619624992 1475
-457901/1827691800 1/80]
-
-[0 0 1604444/264539275 24208141/149362505292 847880210129/47916076768560 -45
-44407141/103873817300 -29/40920]
-
-[0 0 0 9773092581/35395807550620 -24363634138919/107305824577186620 72118203
-606917/60481351061158500 55899/3088554700]
-
-[0 0 0 0 67201501179065/8543442888354179988 -9970556426629/74082861999267660
-0 -3229/13661312210]
-
-[0 0 0 0 0 -258198800769/9279048099409000 -13183/38381527800]
-
-? hilb(2/3,3/4,5)
-1
-? hilbert(5)
-
-[  1 1/2 1/3 1/4 1/5]
-
-[1/2 1/3 1/4 1/5 1/6]
-
-[1/3 1/4 1/5 1/6 1/7]
-
-[1/4 1/5 1/6 1/7 1/8]
-
-[1/5 1/6 1/7 1/8 1/9]
-
-? hilbp(mod(5,7),mod(6,7))
-1
-? hvector(10,x,1/x)
-[1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10]
-? hyperu(1,1,1)
-0.59634736232319407434107849936927937607
-? i^2
--1
-? initalgred(nfpol)
-[x^5 - 2*x^4 + 3*x^3 + 8*x^2 + 3*x + 2, [1, 2], 595125, 4, [[1, -1.089115145
-7205048250249527946671612684, -2.4285174907194186068992069565359418365, 0.71
-946691128913178943997506477288225735, -2.55582003506916949506460711594267799
-71; 1, -0.13838372073406036365047976417441696637 + 0.49181637657768643499753
-285514741525107*I, 1.9647119211288133163138753392090569931 - 0.8097149241889
-7895128294082219556466857*I, -0.072312766896812300380582649294307897123 - 2.
-1980803753846276641195195160383234878*I, -0.98796319352507039803950539735452
-837195 - 1.5701452385894131769052374806001981109*I; 1, 1.6829412935943127761
-629561615079976006 + 2.0500351226010726172974286983598602164*I, -0.750453175
-76910401286427186094108607490 + 1.3101462685358123283560773619310445915*I, -
-0.78742068874775359433940488309213323160 + 2.1336633893126618034168454610457
-936016*I, 1.2658732110596551455718089553258673704 - 2.7164790103743150566578
-028035789834836*I], [1, -1.0891151457205048250249527946671612684, -2.4285174
-907194186068992069565359418365, 0.71946691128913178943997506477288225735, -2
-.5558200350691694950646071159426779971; 1, 0.3534326558436260713470530909729
-9828470, 1.1549969969398343650309345170134923246, -2.27039314228143996450010
-21653326313849, -2.5581084321144835749447428779547264828; 1, -0.630200097311
-74679864801261932183221744, 2.7744268453177922675968161614046216617, 2.12576
-76084878153637389368667440155906, 0.58218204506434277886573208324566973893; 
-1, 3.7329764161953853934603848598678578170, 0.559693092766708315491805500989
-95851657, 1.3462427005649082090774405779536603700, -1.4506057993146599110859
-938482531161132; 1, -0.36709382900675984113447253685186261580, -2.0605994443
-049163412203492228721306664, -2.9210840780604153977562503441379268332, 3.982
-3522214339702022296117589048508541], [1, -1, -2, 1, -3; 1, 0, 1, -2, -3; 1, 
--1, 3, 2, 1; 1, 4, 1, 1, -1; 1, 0, -2, -3, 4], [5, 2, 0, -1, -2; 2, -2, -5, 
--10, 20; 0, -5, 10, -10, 5; -1, -10, -10, -17, 1; -2, 20, 5, 1, -8], [345, 0
-, 200, 110, 177; 0, 345, 95, 1, 145; 0, 0, 5, 4, 3; 0, 0, 0, 1, 0; 0, 0, 0, 
-0, 1], [63, 3, 0, -6, -9; 3, 8, -5, -1, 16; 0, -5, 22, -10, 0; -6, -1, -10, 
--14, -9; -9, 16, 0, -9, -2], [345, [138, 117, 330, 288, -636; -172, -88, 65,
- 118, -116; 53, 1, 138, -173, 65; 1, -172, 54, 191, 106; 0, 118, 173, 225, -
-34]], [3, 5, 23]], [-1.0891151457205048250249527946671612684, -0.13838372073
-406036365047976417441696637 + 0.49181637657768643499753285514741525107*I, 1.
-6829412935943127761629561615079976006 + 2.0500351226010726172974286983598602
-164*I], [1, x, -1/2*x^4 + 3/2*x^3 - 5/2*x^2 - 2*x + 1, -1/2*x^4 + x^3 - x^2 
-- 9/2*x - 1, -1/2*x^4 + x^3 - 2*x^2 - 7/2*x - 2], [1, 0, -1, -7, -14; 0, 1, 
-1, -2, -15; 0, 0, 0, 2, 4; 0, 0, 1, 1, -2; 0, 0, -1, -3, -4], [1, 0, 0, 0, 0
-, 0, -1, -1, -2, 4, 0, -1, 3, -1, 1, 0, -2, -1, -3, -1, 0, 4, 1, -1, -1; 0, 
-1, 0, 0, 0, 1, 1, -1, -1, 1, 0, -1, -2, -1, 1, 0, -1, -1, -1, 3, 0, 1, 1, 3,
- -3; 0, 0, 1, 0, 0, 0, 0, 0, 1, -1, 1, 0, 0, 0, -2, 0, 1, 0, -1, -1, 0, -1, 
--2, -1, -1; 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 2, 1, 0, 1, 0, 0, 0, 0
-, 2, 0, -1; 0, 0, 0, 0, 1, 0, -1, -1, -1, 1, 0, -1, 0, 1, 0, 0, -1, 1, 0, 0,
- 1, 1, 0, 0, -1]]
-? initalgred2(nfpol)
-[[x^5 - 2*x^4 + 3*x^3 + 8*x^2 + 3*x + 2, [1, 2], 595125, 4, [[1, -1.08911514
-57205048250249527946671612684, -2.4285174907194186068992069565359418365, 0.7
-1946691128913178943997506477288225735, -2.5558200350691694950646071159426779
-971; 1, -0.13838372073406036365047976417441696637 + 0.4918163765776864349975
-3285514741525107*I, 1.9647119211288133163138753392090569931 - 0.809714924188
-97895128294082219556466857*I, -0.072312766896812300380582649294307897123 - 2
-.1980803753846276641195195160383234878*I, -0.9879631935250703980395053973545
-2837195 - 1.5701452385894131769052374806001981109*I; 1, 1.682941293594312776
-1629561615079976006 + 2.0500351226010726172974286983598602164*I, -0.75045317
-576910401286427186094108607490 + 1.3101462685358123283560773619310445915*I, 
--0.78742068874775359433940488309213323160 + 2.133663389312661803416845461045
-7936016*I, 1.2658732110596551455718089553258673704 - 2.716479010374315056657
-8028035789834836*I], [1, -1.0891151457205048250249527946671612684, -2.428517
-4907194186068992069565359418365, 0.71946691128913178943997506477288225735, -
-2.5558200350691694950646071159426779971; 1, 0.353432655843626071347053090972
-99828470, 1.1549969969398343650309345170134923246, -2.2703931422814399645001
-021653326313849, -2.5581084321144835749447428779547264828; 1, -0.63020009731
-174679864801261932183221744, 2.7744268453177922675968161614046216617, 2.1257
-676084878153637389368667440155906, 0.58218204506434277886573208324566973893;
- 1, 3.7329764161953853934603848598678578170, 0.55969309276670831549180550098
-995851657, 1.3462427005649082090774405779536603700, -1.450605799314659911085
-9938482531161132; 1, -0.36709382900675984113447253685186261580, -2.060599444
-3049163412203492228721306664, -2.9210840780604153977562503441379268332, 3.98
-23522214339702022296117589048508541], [1, -1, -2, 1, -3; 1, 0, 1, -2, -3; 1,
- -1, 3, 2, 1; 1, 4, 1, 1, -1; 1, 0, -2, -3, 4], [5, 2, 0, -1, -2; 2, -2, -5,
- -10, 20; 0, -5, 10, -10, 5; -1, -10, -10, -17, 1; -2, 20, 5, 1, -8], [345, 
-0, 200, 110, 177; 0, 345, 95, 1, 145; 0, 0, 5, 4, 3; 0, 0, 0, 1, 0; 0, 0, 0,
- 0, 1], [63, 3, 0, -6, -9; 3, 8, -5, -1, 16; 0, -5, 22, -10, 0; -6, -1, -10,
- -14, -9; -9, 16, 0, -9, -2], [345, [138, 117, 330, 288, -636; -172, -88, 65
-, 118, -116; 53, 1, 138, -173, 65; 1, -172, 54, 191, 106; 0, 118, 173, 225, 
--34]], [3, 5, 23]], [-1.0891151457205048250249527946671612684, -0.1383837207
-3406036365047976417441696637 + 0.49181637657768643499753285514741525107*I, 1
-.6829412935943127761629561615079976006 + 2.050035122601072617297428698359860
-2164*I], [1, x, -1/2*x^4 + 3/2*x^3 - 5/2*x^2 - 2*x + 1, -1/2*x^4 + x^3 - x^2
- - 9/2*x - 1, -1/2*x^4 + x^3 - 2*x^2 - 7/2*x - 2], [1, 0, -1, -7, -14; 0, 1,
- 1, -2, -15; 0, 0, 0, 2, 4; 0, 0, 1, 1, -2; 0, 0, -1, -3, -4], [1, 0, 0, 0, 
-0, 0, -1, -1, -2, 4, 0, -1, 3, -1, 1, 0, -2, -1, -3, -1, 0, 4, 1, -1, -1; 0,
- 1, 0, 0, 0, 1, 1, -1, -1, 1, 0, -1, -2, -1, 1, 0, -1, -1, -1, 3, 0, 1, 1, 3
-, -3; 0, 0, 1, 0, 0, 0, 0, 0, 1, -1, 1, 0, 0, 0, -2, 0, 1, 0, -1, -1, 0, -1,
- -2, -1, -1; 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 2, 1, 0, 1, 0, 0, 0, 
-0, 2, 0, -1; 0, 0, 0, 0, 1, 0, -1, -1, -1, 1, 0, -1, 0, 1, 0, 0, -1, 1, 0, 0
-, 1, 1, 0, 0, -1]], mod(-1/2*x^4 + 3/2*x^3 - 5/2*x^2 - 2*x + 1, x^5 - 2*x^4 
-+ 3*x^3 + 8*x^2 + 3*x + 2)]
-? vp=primedec(nf,3)[1]
-[3, [1, 0, 1, 0, 0]~, 1, 1, [1, 4, -1, 6, -4; -1, 2, 4, 3, -5; -1, -1, 1, 0,
- 4; -1, -1, -2, 0, -2; 0, 3, 0, 0, 0]]
-? idx=idealmul(nf,idmat(5),vp)
-
-[3 2 1 0 1]
-
-[0 1 0 0 0]
-
-[0 0 1 0 0]
-
-[0 0 0 1 0]
-
-[0 0 0 0 1]
-
-? idy=ideallllred(nf,idx,[1,5,6])
-
-[5 0 0 0 2]
-
-[0 5 0 0 2]
-
-[0 0 5 0 1]
+  ***   too few arguments: abs()
+  ***                          ^-
+  ***   at top-level: addell()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: addell(e,z1,z2) ===> elladd(e,z1,z2)
+
+elladd(E,z1,z2): sum of the points z1 and z2 on elliptic curve E.
+
+
+[]
+  ***   at top-level: adj()
+  ***                 ^-----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: adj(x) ===> matadjoint(x)
+
+matadjoint(M,{flag=0}): adjoint matrix of M using Leverrier-Faddeev's 
+algorithm. If flag is 1, compute the characteristic polynomial independently 
+first.
+
+
+  ***   at top-level: akell()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: akell(e,n) ===> ellak(e,n)
+
+ellak(E,n): computes the n-th Fourier coefficient of the L-function of the 
+elliptic curve E (assumed E is an integral model).
+
+
+  ***   at top-level: algdep2()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: algdep2(x,n,dec) ===> algdep(x,n,dec)
+
+algdep(x,k,{flag=0}): algebraic relations up to degree n of x, using 
+lindep([1,x,...,x^(k-1)], flag).
+
+
+  ***   at top-level: algtobasis()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: algtobasis(nf,x) ===> nfalgtobasis(nf,x)
+
+nfalgtobasis(nf,x): transforms the algebraic number x into a column vector on 
+the integral basis nf.zk.
+
+
+  ***   at top-level: anell()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: anell(e,n) ===> ellan(e,n)
+
+ellan(E,n): computes the first n Fourier coefficients of the L-function of the 
+elliptic curve E (n<2^24 on a 32-bit machine).
+
+
+  ***   at top-level: apell()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: apell(e,n) ===> ellap(e,n)
+
+ellap(E,{p}): computes the trace of Frobenius a_p for the elliptic curve E, 
+defined over Q or a finite field.
+
+
+  ***   at top-level: apell2()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: apell2(e,n) ===> ellap(e,n)
+
+ellap(E,{p}): computes the trace of Frobenius a_p for the elliptic curve E, 
+defined over Q or a finite field.
+
+
+  ***   at top-level: apprpadic()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: apprpadic(x,a) ===> padicappr(x,a)
+
+padicappr(pol,a): p-adic roots of the polynomial pol congruent to a mod p.
+
+
+  ***   at top-level: assmat()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: assmat(x) ===> matcompanion(x)
+
+matcompanion(x): companion matrix to polynomial x.
+
+
+  ***   at top-level: basis()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: basis(x) ===> nfbasis(x)
+
+nfbasis(T): integral basis of the field Q[a], where a is a root of the 
+polynomial T, using the round 4 algorithm. An argument [T,listP] is possible, 
+where listP is a list of primes (to get an order which is maximal at certain 
+primes only) or a prime bound.
+
+
+  ***   at top-level: basis2()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: basis2(x) ===> nfbasis(x,2)
+
+nfbasis(T): integral basis of the field Q[a], where a is a root of the 
+polynomial T, using the round 4 algorithm. An argument [T,listP] is possible, 
+where listP is a list of primes (to get an order which is maximal at certain 
+primes only) or a prime bound.
+
+
+  ***   at top-level: basistoalg()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: basistoalg(nf,x) ===> nfbasistoalg(nf,x)
+
+nfbasistoalg(nf,x): transforms the column vector x on the integral basis into 
+an algebraic number.
+
+
+  ***   at top-level: bilhell()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: bilhell(e,z1,z2) ===> ellbil(e,z1,z2)
+
+ellbil(E,z1,z2): deprecated alias for ellheight(E,P,Q).
+
+
+  ***   at top-level: bin()
+  ***                 ^-----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: bin(x,y) ===> binomial(x,y)
+
+binomial(x,y): binomial coefficient x*(x-1)...*(x-y+1)/y! defined for y in Z 
+and any x.
+
+
+  ***   at top-level: boundcf()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: boundcf(x,lmax) ===> contfrac(x,,lmax)
+
+contfrac(x,{b},{nmax}): continued fraction expansion of x (x rational,real or 
+rational function). b and nmax are both optional, where b is the vector of 
+numerators of the continued fraction, and nmax is a bound for the number of 
+terms in the continued fraction expansion.
+
 
-[0 0 0 5 2]
+  ***   at top-level: boundfact()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[0 0 0 0 1]
+New syntax: boundfact(x,lim) ===> factor(x,lim)
 
-? idealadd(nf,idx,idy)
+factor(x,{lim}): factorization of x. lim is optional and can be set whenever x 
+is of (possibly recursive) rational type. If lim is set return partial 
+factorization, using primes < lim.
 
-[1 0 0 0 0]
 
-[0 1 0 0 0]
+  ***   at top-level: buchcertify()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[0 0 1 0 0]
+New syntax: buchcertify(bnf) ===> bnfcertify(bnf)
 
-[0 0 0 1 0]
+bnfcertify(bnf,{flag = 0}): certify the correctness (i.e. remove the GRH) of 
+the bnf data output by bnfinit. If flag is present, only certify that the class 
+group is a quotient of the one computed in bnf (much simpler in general).
 
-[0 0 0 0 1]
 
-? idealaddone(nf,idx,idy)
-[[0, -1, -3, -1, 2]~, [1, 1, 3, 1, -2]~]
-? idealaddmultone(nf,[idy,idx])
-[[-5, 0, 0, 0, 0]~, [6, 0, 0, 0, 0]~]
-? idealappr(nf,idy)
-[-1, 4, 2, -1, -3]~
-? idealapprfact(nf,idealfactor(nf,idy))
-[-1, 4, 2, -1, -3]~
-? idealcoprime(nf,idx,idx)
-[-1/3, 1/3, 1/3, 1/3, 0]~
-? idz=idealintersect(nf,idx,idy)
+  ***   at top-level: buchfu()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[15 10 5 0 12]
+This function no longer exists
 
-[ 0  5 0 0  2]
 
-[ 0  0 5 0  1]
+  ***   at top-level: buchgen()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[ 0  0 0 5  2]
+This function no longer exists
 
-[ 0  0 0 0  1]
 
-? idealfactor(nf,idz)
+  ***   at top-level: buchgenforcefu()
+  ***                 ^----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[[3, [1, 0, 1, 0, 0]~, 1, 1, [1, 4, -1, 6, -4; -1, 2, 4, 3, -5; -1, -1, 1, 0
-, 4; -1, -1, -2, 0, -2; 0, 3, 0, 0, 0]] 1]
+This function no longer exists
 
-[[5, [-1, 0, 0, 0, 2]~, 4, 1, [2, -3, 0, -12, 6; 2, 2, -5, -2, 6; 1, 1, 0, -
-1, -7; 2, 2, 5, 3, 1; 1, -4, 0, -1, 3]] 3]
 
-[[5, [2, 0, 0, 0, -2]~, 1, 1, [2, 1, 10, -4, 2; 0, 0, -5, 0, 0; 3, -1, 0, -1
-, -7; 0, 0, 5, 5, 5; 1, -2, 0, 3, 1]] 1]
+  ***   at top-level: buchgenfu()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-? ideallist(bnf,20)
-[[[1, 0; 0, 1]], [], [[3, 2; 0, 1], [3, 0; 0, 1]], [[2, 0; 0, 2]], [[5, 3; 0
-, 1], [5, 1; 0, 1]], [], [], [], [[9, 5; 0, 1], [3, 0; 0, 3], [9, 3; 0, 1]],
- [], [[11, 9; 0, 1], [11, 1; 0, 1]], [[6, 4; 0, 2], [6, 0; 0, 2]], [], [], [
-[15, 8; 0, 1], [15, 3; 0, 1], [15, 11; 0, 1], [15, 6; 0, 1]], [[4, 0; 0, 4]]
-, [[17, 14; 0, 1], [17, 2; 0, 1]], [], [[19, 18; 0, 1], [19, 0; 0, 1]], [[10
-, 6; 0, 2], [10, 2; 0, 2]]]
-? idx2=idealmul(nf,idx,idx)
+This function no longer exists
 
-[9 5 7 0 4]
 
-[0 1 0 0 0]
+  ***   at top-level: buchimag()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[0 0 1 0 0]
+New syntax: buchimag(D,c1,c2,g) ===> quadclassunit(D,,[c1,c2,g])
 
-[0 0 0 1 0]
+quadclassunit(D,{flag=0},{tech=[]}): compute the structure of the class group 
+and the regulator of the quadratic field of discriminant D. See manual for the 
+optional technical parameters.
 
-[0 0 0 0 1]
 
-? idt=idealmulred(nf,idx,idx)
+  ***   at top-level: buchinit()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[2 0 0 0 0]
+New syntax: buchinit(P) ===> bnfinit(P,2)
 
-[0 2 0 0 0]
+bnfinit(P,{flag=0},{tech=[]}): compute the necessary data for future use in 
+ideal and unit group computations, including fundamental units if they are not 
+too large. flag and tech are both optional. flag can be any of 0: default, 1: 
+insist on having fundamental units. See manual for details about tech.
 
-[0 0 2 0 0]
 
-[0 0 0 2 1]
+  ***   at top-level: buchinitforcefu()
+  ***                 ^-----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[0 0 0 0 1]
+New syntax: buchinitforcefu(P) ===> bnfinit(P,1)
 
-? idealdiv(nf,idy,idt)
+bnfinit(P,{flag=0},{tech=[]}): compute the necessary data for future use in 
+ideal and unit group computations, including fundamental units if they are not 
+too large. flag and tech are both optional. flag can be any of 0: default, 1: 
+insist on having fundamental units. See manual for details about tech.
 
-[5   0 5/2   0   1]
 
-[0 5/2   0   0   1]
+  ***   at top-level: buchinitfu()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[0   0 5/2   0 1/2]
+New syntax: buchinitfu(P) ===> bnfinit(P)
 
-[0   0   0 5/2   1]
+bnfinit(P,{flag=0},{tech=[]}): compute the necessary data for future use in 
+ideal and unit group computations, including fundamental units if they are not 
+too large. flag and tech are both optional. flag can be any of 0: default, 1: 
+insist on having fundamental units. See manual for details about tech.
 
-[0   0   0   0 1/2]
 
-? idealdivexact(nf,idx2,idx)
+  ***   at top-level: buchnarrow()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[3 2 1 0 1]
+New syntax: buchnarrow(bnf) ===> bnfnarrow(bnf)
 
-[0 1 0 0 0]
+bnfnarrow(bnf): given a big number field as output by bnfinit, gives as a 
+3-component vector the structure of the narrow class group.
 
-[0 0 1 0 0]
 
-[0 0 0 1 0]
+  ***   at top-level: buchray()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[0 0 0 0 1]
+New syntax: buchray(bnf,ideal) ===> bnrinit(bnf,ideal)
 
-? idealhermite(nf,vp)
+bnrinit(bnf,f,{flag=0}): given a bnf as output by bnfinit and a modulus f, 
+initializes data linked to the ray class group structure corresponding to this 
+module. flag is optional, and can be 0: default, 1: compute also the 
+generators.
 
-[3 2 1 0 1]
 
-[0 1 0 0 0]
+  ***   at top-level: buchrayinit()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[0 0 1 0 0]
+New syntax: buchrayinit(bnf,ideal) ===> bnrinit(bnf,ideal)
 
-[0 0 0 1 0]
+bnrinit(bnf,f,{flag=0}): given a bnf as output by bnfinit and a modulus f, 
+initializes data linked to the ray class group structure corresponding to this 
+module. flag is optional, and can be 0: default, 1: compute also the 
+generators.
 
-[0 0 0 0 1]
 
-? idealhermite2(nf,vp[2],3)
+  ***   at top-level: buchrayinitgen()
+  ***                 ^----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[3 2 1 0 1]
+New syntax: buchrayinitgen(bnf,ideal) ===> bnrinit(bnf,ideal,1)
 
-[0 1 0 0 0]
+bnrinit(bnf,f,{flag=0}): given a bnf as output by bnfinit and a modulus f, 
+initializes data linked to the ray class group structure corresponding to this 
+module. flag is optional, and can be 0: default, 1: compute also the 
+generators.
 
-[0 0 1 0 0]
 
-[0 0 0 1 0]
+  ***   at top-level: buchreal()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[0 0 0 0 1]
+New syntax: buchreal(D) ===> quadclassunit(D)
 
-? idealnorm(nf,idt)
-16
-? idp=idealpow(nf,idx,7)
+quadclassunit(D,{flag=0},{tech=[]}): compute the structure of the class group 
+and the regulator of the quadratic field of discriminant D. See manual for the 
+optional technical parameters.
 
-[2187 1436 1807 630 1822]
 
-[   0    1    0   0    0]
+  ***   at top-level: bytesize()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[   0    0    1   0    0]
+New syntax: bytesize(x) ===> sizebyte(x)
 
-[   0    0    0   1    0]
+sizebyte(x): number of bytes occupied by the complete tree of the object x.
 
-[   0    0    0   0    1]
 
-? idealpowred(nf,idx,7)
+  ***   at top-level: cf()
+  ***                 ^----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[1 0 0 0 0]
+New syntax: cf(x) ===> contfrac(x)
 
-[0 1 0 0 0]
+contfrac(x,{b},{nmax}): continued fraction expansion of x (x rational,real or 
+rational function). b and nmax are both optional, where b is the vector of 
+numerators of the continued fraction, and nmax is a bound for the number of 
+terms in the continued fraction expansion.
 
-[0 0 1 0 0]
 
-[0 0 0 1 0]
+  ***   at top-level: cf2()
+  ***                 ^-----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[0 0 0 0 1]
+New syntax: cf2(b,x) ===> contfrac(x,b)
 
-? idealtwoelt(nf,idy)
-[5, [2, 2, 1, 2, 1]~]
-? idealtwoelt2(nf,idy,10)
-[-1, 4, 2, 4, 2]~
-? idealval(nf,idp,vp)
-7
-? idmat(5)
+contfrac(x,{b},{nmax}): continued fraction expansion of x (x rational,real or 
+rational function). b and nmax are both optional, where b is the vector of 
+numerators of the continued fraction, and nmax is a bound for the number of 
+terms in the continued fraction expansion.
 
-[1 0 0 0 0]
 
-[0 1 0 0 0]
+  ***   at top-level: changevar()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[0 0 1 0 0]
+This function no longer exists
 
-[0 0 0 1 0]
 
-[0 0 0 0 1]
+  ***   at top-level: char()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-? if(3<2,print("bof"),print("ok"));
-ok
-? imag(2+3*i)
-3
-? image([1,3,5;2,4,6;3,5,7])
+New syntax: char(x,y) ===> charpoly(x,y)
 
-[1 3]
+charpoly(A,{v='x},{flag=5}): det(v*Id-A)=characteristic polynomial of the 
+matrix or polmod A. flag is optional and ignored unless A is a matrix; it may 
+be set to 0 (Le Verrier), 1 (Lagrange interpolation), 2 (Hessenberg form), 3 
+(Berkowitz), 4 (modular) if A is integral, or 5 (default, choose best method). 
+Algorithms 0 (Le Verrier) and 1 (Lagrange) assume that n! is invertible, where 
+n is the dimension of the matrix.
 
-[2 4]
 
-[3 5]
+  ***   at top-level: char1()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-? image(pi*[1,3,5;2,4,6;3,5,7])
+New syntax: char1(x,y) ===> charpoly(x,y,1)
 
-[3.1415926535897932384626433832795028842 9.424777960769379715387930149838508
-6526]
+charpoly(A,{v='x},{flag=5}): det(v*Id-A)=characteristic polynomial of the 
+matrix or polmod A. flag is optional and ignored unless A is a matrix; it may 
+be set to 0 (Le Verrier), 1 (Lagrange interpolation), 2 (Hessenberg form), 3 
+(Berkowitz), 4 (modular) if A is integral, or 5 (default, choose best method). 
+Algorithms 0 (Le Verrier) and 1 (Lagrange) assume that n! is invertible, where 
+n is the dimension of the matrix.
 
-[6.2831853071795864769252867665590057684 12.56637061435917295385057353311801
-1537]
-
-[9.4247779607693797153879301498385086526 15.70796326794896619231321691639751
-4421]
-
-? incgam(2,1)
-0.73575888234288464319104754032292173491
-? incgam3(2,1)
-0.26424111765711535680895245967707826509
-? incgam4(4,1,6)
-5.8860710587430771455283803225833738791
-? indexrank([1,1,1;1,1,1;1,1,2])
-[Vecsmall([1, 3]), Vecsmall([1, 3])]
-? indsort([8,7,6,5])
-Vecsmall([4, 3, 2, 1])
-? initell([0,0,0,-1,0])
-[0, 0, 0, -1, 0, 0, -2, 0, -1, 48, 0, 64, 1728, Vecsmall([1]), [Vecsmall([12
-8, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]
-? initrect(1,700,700)
-? nfz=initzeta(x^2-2);
-? integ(sin(x),x)
-1/2*x^2 - 1/24*x^4 + 1/720*x^6 - 1/40320*x^8 + 1/3628800*x^10 - 1/479001600*
-x^12 + 1/87178291200*x^14 - 1/20922789888000*x^16 + O(x^18)
-? integ((-x^2-2*a*x+8*a)/(x^4-14*x^3+(2*a+49)*x^2-14*a*x+a^2),x)
-(x + a)/(x^2 - 7*x + a)
-? intersect([1,2;3,4;5,6],[2,3;7,8;8,9])
-
-[-1]
-
-[-1]
-
-[-1]
-
-? \precision=19
-   realprecision = 19 significant digits
-? intgen(x=0,pi,sin(x))
-2.000000000000000018
-? sqr(2*intgen(x=0,4,exp(-x^2)))
-3.141592556720305686
-? 4*intinf(x=1,10^20,1/(1+x^2))
-3.141592653589793209
-? intnum(x=-0.5,0.5,1/sqrt(1-x^2))
-1.047197551196597746
-? 2*intopen(x=0,100,sin(x)/x)
-3.124450933778112629
-? \precision=38
-   realprecision = 38 significant digits
-? inverseimage([1,1;2,3;5,7],[2,2,6]~)
-[4, -2]~
-? isdiagonal([1,0,0;0,5,0;0,0,0])
-1
-? isfund(12345)
-1
-? isideal(bnf[7],[5,1;0,1])
-1
-? isincl(x^2+1,x^4+1)
-[-x^2, x^2]
-? isinclfast(initalg(x^2+1),initalg(x^4+1))
-[-x^2, x^2]
-? isirreducible(x^5+3*x^3+5*x^2+15)
-0
-? isisom(x^3+x^2-2*x-1,x^3+x^2-2*x-1)
-[x, -x^2 - x + 1, x^2 - 2]
-? isisomfast(initalg(x^3-2),initalg(x^3-6*x^2-6*x-30))
-[-1/25*x^2 + 13/25*x - 2/5]
-? isprime(12345678901234567)
-0
-? isprincipal(bnf,[5,1;0,1])
-[1]~
-? isprincipalgen(bnf,[5,1;0,1])
-[[1]~, [-2, -1/3]~]
-? isprincipalraygen(bnr,primedec(bnf,7)[1])
-[[9]~, [32879/6561, 13958/19683]~]
-? ispsp(73!+1)
-1
-? isqrt(10!^2+1)
-3628800
-? isset([-3,5,7,7])
-0
-? issqfree(123456789876543219)
-0
-? issquare(12345678987654321)
-1
-? isunit(bnf,mod(3405*x-27466,x^2-x-57))
-[-4, mod(1, 2)]~
-? jacobi(hilbert(6))
-[[1.0827994845655497685388772372251778091 E-7, 1.257075712262519492298239799
-6498755378 E-5, 0.00061574835418265769764919938428527140434, 0.0163215213198
-75822124345079564191505890, 0.24236087057520955213572841585070114077, 1.6188
-998589243390969705881471257800713]~, [-0.00124819408408217511693981630463878
-36342, 0.011144320930724710530678340374220998345, -0.06222658815019768177515
-2126611810492941, 0.24032536934252330399154228873240534569, -0.6145448282925
-8676899320019644273870646, 0.74871921887909485900280109200517845109; 0.03560
-6642944287635266122848131812051370, -0.1797327572407600375877689780374064077
-9, 0.49083920971092436297498316169060045043, -0.6976513752773701229620833504
-6678265583, 0.21108248167867048675227675845247769095, 0.44071750324351206127
-160083580231701802; -0.24067907958842295837736719558855680218, 0.60421220675
-295973004426567844103061740, -0.53547692162107486593474491750949545605, -0.2
-3138937333290388042251363554209048307, 0.36589360730302614149086554211117169
-623, 0.32069686982225190106359024326699463107; 0.625460386549227244577534410
-39459331707, -0.44357471627623954554460416705180104473, -0.41703769221897886
-840494514780771076351, 0.13286315850933553530333839628101576048, 0.394706776
-09501756783094636145991581709, 0.25431138634047419251788312792590944672; -0.
-68980719929383668419801738006926828754, -0.441536641012289662221436497529772
-04448, 0.047034018933115649705614518466541245344, 0.362714921464871475252994
-57604461742112, 0.38819043387388642863111448825992418974, 0.2115308400789652
-4664213667673977991960; 0.27160545336631286930015536176213646338, 0.45911481
-681642960284551392793050867151, 0.54068156310385293880022293448123781988, 0.
-50276286675751538489260566368647786274, 0.3706959077673628086177550108480739
-4603, 0.18144297664876947372217005457727093716]]
-? jbesselh(1,1)
-0.24029783912342701089584304474193368046
-? jell(i)
-1728.0000000000000000000000000000000000
-? kbessel(1+i,1)
-0.32545977186584141085464640324923711950 + 0.2894280370259921276345671592415
-2302743*I
-? kbessel2(1+i,1)
-0.32545977186584141085464640324923711950 + 0.2894280370259921276345671592415
-2302743*I
-? x
-x
-? y
-x
-? ker(matrix(4,4,x,y,x/y))
-
-[-1/2 -1/3 -1/4]
-
-[   1    0    0]
-
-[   0    1    0]
-
-[   0    0    1]
-
-? ker(matrix(4,4,x,y,sin(x+y)))
-
-[1.0000000000000000000000000000000000000 1.080604611736279434801873214885953
-2075]
-
-[-1.0806046117362794348018732148859532075 -0.1677063269057152260048635409984
-7562047]
-
-[1 0]
-
-[0 1]
-
-? keri(matrix(4,4,x,y,x+y))
-
-[ 1  2]
-
-[-2 -3]
-
-[ 1  0]
-
-[ 0  1]
-
-? kerint(matrix(4,4,x,y,x*y))
-
-[-1 -1 -1]
-
-[-1  0  1]
 
-[ 1 -1  1]
+  ***   at top-level: char2()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[ 0  1 -1]
+New syntax: char2(x,y) ===> charpoly(x,y,2)
 
-? kerint1(matrix(4,4,x,y,x*y))
+charpoly(A,{v='x},{flag=5}): det(v*Id-A)=characteristic polynomial of the 
+matrix or polmod A. flag is optional and ignored unless A is a matrix; it may 
+be set to 0 (Le Verrier), 1 (Lagrange interpolation), 2 (Hessenberg form), 3 
+(Berkowitz), 4 (modular) if A is integral, or 5 (default, choose best method). 
+Algorithms 0 (Le Verrier) and 1 (Lagrange) assume that n! is invertible, where 
+n is the dimension of the matrix.
 
-[-1 -1 -1]
 
-[-1  0  1]
+  ***   at top-level: chell()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[ 1 -1  1]
+New syntax: chell(x,y) ===> ellchangecurve(x,y)
 
-[ 0  1 -1]
+ellchangecurve(E,v): change data on elliptic curve according to v=[u,r,s,t].
 
-? f(u)=u+1;
-? print(f(5));kill(f);
-6
-? f=12
-12
-? killrect(1)
-? kro(5,7)
--1
-? kro(3,18)
-0
-? laplace(x*exp(x*y)/(exp(x)-1))
-1 - 1/2*x + 13/6*x^2 - 3*x^3 + 419/30*x^4 - 30*x^5 + 6259/42*x^6 - 420*x^7 +
- 22133/10*x^8 - 7560*x^9 + 2775767/66*x^10 - 166320*x^11 + 2655339269/2730*x
-^12 - 4324320*x^13 + 264873251/10*x^14 - 129729600*x^15 + O(x^16)
-? lcm(15,-21)
-105
-? length(divisors(1000))
-16
-? legendre(10)
-46189/256*x^10 - 109395/256*x^8 + 45045/128*x^6 - 15015/128*x^4 + 3465/256*x
-^2 - 63/256
-? lex([1,3],[1,3,5])
--1
-? lexsort([[1,5],[2,4],[1,5,1],[1,4,2]])
-[[1, 4, 2], [1, 5], [1, 5, 1], [2, 4]]
-? lift(chinese(mod(7,15),mod(4,21)))
-67
-? lindep([(1-3*sqrt(2))/(3-2*sqrt(3)),1,sqrt(2),sqrt(3),sqrt(6)])
-[3, 3, -9, 2, -6]~
-? lindep2([(1-3*sqrt(2))/(3-2*sqrt(3)),1,sqrt(2),sqrt(3),sqrt(6)],14)
-[-3, -3, 9, -2, 6]~
-? move(0,0,900);line(0,900,0)
-? lines(0,vector(5,k,50*k),vector(5,k,10*k*k))
-? m=1/hilbert(7)
 
-[    49    -1176      8820    -29400      48510     -38808     12012]
+  ***   at top-level: chptell()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[ -1176    37632   -317520   1128960   -1940400    1596672   -504504]
+New syntax: chptell(x,y) ===> ellchangepoint(x,y)
 
-[  8820  -317520   2857680 -10584000   18711000  -15717240   5045040]
+ellchangepoint(x,v): change data on point or vector of points x on an elliptic 
+curve according to v=[u,r,s,t].
 
-[-29400  1128960 -10584000  40320000  -72765000   62092800 -20180160]
 
-[ 48510 -1940400  18711000 -72765000  133402500 -115259760  37837800]
+  ***   at top-level: classno()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[-38808  1596672 -15717240  62092800 -115259760  100590336 -33297264]
+New syntax: classno(x) ===> qfbclassno(x)
 
-[ 12012  -504504   5045040 -20180160   37837800  -33297264  11099088]
+qfbclassno(D,{flag=0}): class number of discriminant D using Shanks's method by 
+default. If (optional) flag is set to 1, use Euler products.
 
-? mp=concat(m,idmat(7))
 
-[49 -1176 8820 -29400 48510 -38808 12012 1 0 0 0 0 0 0]
+  ***   at top-level: classno2()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[-1176 37632 -317520 1128960 -1940400 1596672 -504504 0 1 0 0 0 0 0]
+New syntax: classno2(x) ===> qfbclassno(x,1)
 
-[8820 -317520 2857680 -10584000 18711000 -15717240 5045040 0 0 1 0 0 0 0]
+qfbclassno(D,{flag=0}): class number of discriminant D using Shanks's method by 
+default. If (optional) flag is set to 1, use Euler products.
 
-[-29400 1128960 -10584000 40320000 -72765000 62092800 -20180160 0 0 0 1 0 0 
-0]
 
-[48510 -1940400 18711000 -72765000 133402500 -115259760 37837800 0 0 0 0 1 0
- 0]
+  ***   at top-level: coeff()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[-38808 1596672 -15717240 62092800 -115259760 100590336 -33297264 0 0 0 0 0 
-1 0]
+New syntax: coeff(x,s) ===> polcoeff(x,s)
 
-[12012 -504504 5045040 -20180160 37837800 -33297264 11099088 0 0 0 0 0 0 1]
+polcoeff(x,n,{v}): coefficient of degree n of x, or the n-th component for 
+vectors or matrices (for which it is simpler to use x[]). With respect to the 
+main variable if v is omitted, with respect to the variable v otherwise.
 
-? lll(m)
 
-[-420 -420 840 630 -1092 757 2982]
+  ***   at top-level: compimag()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[-210 -280 630 504  -876 700 2415]
+New syntax: compimag(x,y) ===> x*y
 
-[-140 -210 504 420  -749 641 2050]
+x*y: product of x and y.
 
-[-105 -168 420 360  -658 589 1785]
 
-[ -84 -140 360 315  -588 544 1582]
+  ***   at top-level: compo()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[ -70 -120 315 280  -532 505 1421]
+New syntax: compo(x,s) ===> component(x,s)
 
-[ -60 -105 280 252  -486 471 1290]
+component(x,n): the n'th component of the internal representation of x. For 
+vectors or matrices, it is simpler to use x[]. For list objects such as nf, 
+bnf, bnr or ell, it is much easier to use member functions starting with ".".
 
-? lllgram(m)
 
-[1 1 27 -27 69   0 141]
+  ***   at top-level: compositum()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[0 1  5 -23 35 -24  50]
+New syntax: compositum(pol1,pol2) ===> polcompositum(pol1,pol2)
 
-[0 1  4 -22 19 -24  24]
+polcompositum(P,Q,{flag=0}): vector of all possible compositums of the number 
+fields defined by the polynomials P and Q; flag is optional, whose binary 
+digits mean 1: output for each compositum, not only the compositum polynomial 
+pol, but a vector [R,a,b,k] where a (resp. b) is a root of P (resp. Q) 
+expressed as a polynomial modulo R, and a small integer k such that al2+k*al1 
+is the chosen root of R; 2: assume that the number fields defined by P and Q 
+are linearly disjoint.
 
-[0 1  4 -21 11 -19  14]
 
-[0 1  4 -20  7 -14   9]
+  ***   at top-level: compositum2()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[0 1  4 -19  5 -10   6]
+New syntax: compositum2(pol1,pol2) ===> polcompositum(pol1,pol2,1)
 
-[0 1  4 -18  4  -7   4]
+polcompositum(P,Q,{flag=0}): vector of all possible compositums of the number 
+fields defined by the polynomials P and Q; flag is optional, whose binary 
+digits mean 1: output for each compositum, not only the compositum polynomial 
+pol, but a vector [R,a,b,k] where a (resp. b) is a root of P (resp. Q) 
+expressed as a polynomial modulo R, and a small integer k such that al2+k*al1 
+is the chosen root of R; 2: assume that the number fields defined by P and Q 
+are linearly disjoint.
 
-? lllgramint(m)
 
-[1 1 27 -27 69   0 141]
+  ***   at top-level: comprealraw()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[0 1  5 -23 35 -24  50]
+New syntax: comprealraw(x,y) ===> qfbcompraw(x,y)
 
-[0 1  4 -22 19 -24  24]
+qfbcompraw(x,y): Gaussian composition without reduction of the binary quadratic 
+forms x and y.
 
-[0 1  4 -21 11 -19  14]
 
-[0 1  4 -20  7 -14   9]
+  ***   at top-level: conductor()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[0 1  4 -19  5 -10   6]
+New syntax: conductor(a1) ===> bnrconductor(a1)
 
-[0 1  4 -18  4  -7   4]
+bnrconductor(A,{B},{C},{flag=0}): conductor f of the subfield of the ray class 
+field given by A,B,C. flag is optional and can be 0: default, 1: returns [f, 
+Cl_f, H], H subgroup of the ray class group modulo f defining the extension, 2: 
+returns [f, bnr(f), H].
 
-? lllgramkerim(mp~*mp)
-[[-420, -420, 840, 630, 2982, -1092, 757; -210, -280, 630, 504, 2415, -876, 
-700; -140, -210, 504, 420, 2050, -749, 641; -105, -168, 420, 360, 1785, -658
-, 589; -84, -140, 360, 315, 1582, -588, 544; -70, -120, 315, 280, 1421, -532
-, 505; -60, -105, 280, 252, 1290, -486, 471; 420, 0, 0, 0, -210, 168, 35; 0,
- 840, 0, 0, 0, 0, 336; 0, 0, -2520, 0, 0, 0, -1260; 0, 0, 0, -2520, 0, 0, -8
-40; 0, 0, 0, 0, -13860, 0, 6930; 0, 0, 0, 0, 0, 5544, 0; 0, 0, 0, 0, 0, 0, -
-12012], [0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0; 0, 0
-, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 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, 0, 0, 0; 0, 0, 0, 
-1, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 1]]
-? lllint(m)
 
-[-420 -420 840 630 -1092 757 2982]
+  ***   at top-level: conductorofchar()
+  ***                 ^-----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[-210 -280 630 504  -876 700 2415]
+New syntax: conductorofchar(bnr,chi) ===> bnrconductorofchar(bnr,chi)
 
-[-140 -210 504 420  -749 641 2050]
+bnrconductorofchar(bnr,chi): conductor of the character chi on the ray class 
+group bnr.
 
-[-105 -168 420 360  -658 589 1785]
 
-[ -84 -140 360 315  -588 544 1582]
+  ***   at top-level: convol()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[ -70 -120 315 280  -532 505 1421]
+New syntax: convol(x,y) ===> serconvol(x,y)
 
-[ -60 -105 280 252  -486 471 1290]
+serconvol(x,y): convolution (or Hadamard product) of two power series.
 
-? lllintpartial(m)
 
-[-420 -420 -630 840 1092 2982 -83]
+  ***   at top-level: core2()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[-210 -280 -504 630  876 2415  70]
-
-[-140 -210 -420 504  749 2050 137]
-
-[-105 -168 -360 420  658 1785 169]
-
-[ -84 -140 -315 360  588 1582 184]
-
-[ -70 -120 -280 315  532 1421 190]
-
-[ -60 -105 -252 280  486 1290 191]
-
-? lllkerim(mp)
-[[-420, -420, 840, 630, 2982, -1092, 757; -210, -280, 630, 504, 2415, -876, 
-700; -140, -210, 504, 420, 2050, -749, 641; -105, -168, 420, 360, 1785, -658
-, 589; -84, -140, 360, 315, 1582, -588, 544; -70, -120, 315, 280, 1421, -532
-, 505; -60, -105, 280, 252, 1290, -486, 471; 420, 0, 0, 0, -210, 168, 35; 0,
- 840, 0, 0, 0, 0, 336; 0, 0, -2520, 0, 0, 0, -1260; 0, 0, 0, -2520, 0, 0, -8
-40; 0, 0, 0, 0, -13860, 0, 6930; 0, 0, 0, 0, 0, 5544, 0; 0, 0, 0, 0, 0, 0, -
-12012], [0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0; 0, 0
-, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 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, 0, 0, 0; 0, 0, 0, 
-1, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 1]]
-? \precision=96
-   realprecision = 96 significant digits
-? ln(2)
-0.69314718055994530941723212145817656807550013436025525412068000949339362196
-9694715605863326996419
-? lngamma(10^50*i)
--157079632679489661923132169163975144209858469968811.93673753887608474948977
-0941153418951907406848 + 114129254649702284200899572734218210380055074431438
-64.0947684761073895534327259165813042649761556*I
-? \precision=2000
-   realprecision = 2003 significant digits (2000 digits displayed)
-? log(2)
-0.69314718055994530941723212145817656807550013436025525412068000949339362196
-9694715605863326996418687542001481020570685733685520235758130557032670751635
-0759619307275708283714351903070386238916734711233501153644979552391204751726
-8157493206515552473413952588295045300709532636664265410423915781495204374043
-0385500801944170641671518644712839968171784546957026271631064546150257207402
-4816377733896385506952606683411372738737229289564935470257626520988596932019
-6505855476470330679365443254763274495125040606943814710468994650622016772042
-4524529612687946546193165174681392672504103802546259656869144192871608293803
-1727143677826548775664850856740776484514644399404614226031930967354025744460
-7030809608504748663852313818167675143866747664789088143714198549423151997354
-8803751658612753529166100071053558249879414729509293113897155998205654392871
-7000721808576102523688921324497138932037843935308877482597017155910708823683
-6275898425891853530243634214367061189236789192372314672321720534016492568727
-4778234453534764811494186423867767744060695626573796008670762571991847340226
-5146283790488306203306114463007371948900274364396500258093651944304119115060
-8094879306786515887090060520346842973619384128965255653968602219412292420757
-4321757489097706752687115817051137009158942665478595964890653058460258668382
-9400228330053820740056770530467870018416240441883323279838634900156312188956
-0650553151272199398332030751408426091479001265168243443893572472788205486271
-5527418772430024897945401961872339808608316648114909306675193393128904316413
-7068139777649817697486890388778999129650361927071088926410523092478391737350
-1229842420499568935992206602204654941510613918788574424557751020683703086661
-9480896412186807790208181588580001688115973056186676199187395200766719214592
-2367206025395954365416553112951759899400560003665135675690512459268257439464
-8316833262490180382424082423145230614096380570070255138770268178516306902551
-3703234053802145019015374029509942262995779647427138157363801729873940704242
-17997226696297993931270694
-? logagm(2)
-0.69314718055994530941723212145817656807550013436025525412068000949339362196
-9694715605863326996418687542001481020570685733685520235758130557032670751635
-0759619307275708283714351903070386238916734711233501153644979552391204751726
-8157493206515552473413952588295045300709532636664265410423915781495204374043
-0385500801944170641671518644712839968171784546957026271631064546150257207402
-4816377733896385506952606683411372738737229289564935470257626520988596932019
-6505855476470330679365443254763274495125040606943814710468994650622016772042
-4524529612687946546193165174681392672504103802546259656869144192871608293803
-1727143677826548775664850856740776484514644399404614226031930967354025744460
-7030809608504748663852313818167675143866747664789088143714198549423151997354
-8803751658612753529166100071053558249879414729509293113897155998205654392871
-7000721808576102523688921324497138932037843935308877482597017155910708823683
-6275898425891853530243634214367061189236789192372314672321720534016492568727
-4778234453534764811494186423867767744060695626573796008670762571991847340226
-5146283790488306203306114463007371948900274364396500258093651944304119115060
-8094879306786515887090060520346842973619384128965255653968602219412292420757
-4321757489097706752687115817051137009158942665478595964890653058460258668382
-9400228330053820740056770530467870018416240441883323279838634900156312188956
-0650553151272199398332030751408426091479001265168243443893572472788205486271
-5527418772430024897945401961872339808608316648114909306675193393128904316413
-7068139777649817697486890388778999129650361927071088926410523092478391737350
-1229842420499568935992206602204654941510613918788574424557751020683703086661
-9480896412186807790208181588580001688115973056186676199187395200766719214592
-2367206025395954365416553112951759899400560003665135675690512459268257439464
-8316833262490180382424082423145230614096380570070255138770268178516306902551
-3703234053802145019015374029509942262995779647427138157363801729873940704242
-17997226696297993931270694
-? \precision=19
-   realprecision = 19 significant digits
-? bcurve=initell([0,0,0,-3,0])
-[0, 0, 0, -3, 0, 0, -6, 0, -9, 144, 0, 1728, 1728, Vecsmall([1]), [Vecsmall(
-[64, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]
-? localred(bcurve,2)
-[6, 2, [1, 1, 1, 0], 1]
-? ccurve=initell([0,0,-1,-1,0])
-[0, 0, -1, -1, 0, 0, -2, 1, -1, 48, -216, 37, 110592/37, Vecsmall([1]), [Vec
-small([64, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]
-? l=lseriesell(ccurve,2,-37,1)
-0.3815754082607112109
-? lseriesell(ccurve,2,-37,1.2)-l
--8.13151629 E-20
-? sbnf=smallbuchinit(x^3-x^2-14*x-1)
-[x^3 - x^2 - 14*x - 1, 3, 10889, [1, x, x^2 - x - 9], [-3.233732695981516673
-, -0.07182350902743636345, 4.305556205008953036], 0, mat(2), mat([1, 1, 0, 1
-, 0, 1]), [9, 15, 16, 17, 39, 33, 10], [2, -1], [[0, 1, 0]~, [5, 3, 1]~], [[
-[4, -1, 0]~, [-1, 1, 0]~, [2, 1, 0]~, [3, 1, 0]~, [-10, -5, -1]~, [-1, -1, 0
-]~, [-3, 0, 0]~], 0]]
-? makebigbnf(sbnf)
-[mat(2), mat([1, 1, 0, 1, 0, 1]), [1.173637103435061715 + 3.1415926535897932
-38*I, -4.562279014988837902 + 3.141592653589793238*I; -2.633543432738976050 
-+ 3.141592653589793238*I, 1.420330600779487358 + 3.141592653589793238*I; 1.4
-59906329303914335, 3.141948414209350544], [1.246346989334819161, 0.540400637
-6129469728 + 3.141592653589793238*I, -0.6926391142471042845 + 3.141592653589
-793238*I, -1.990056445584799714 + 3.141592653589793238*I, -0.830562594660718
-8640, 0.004375616572659815402, 0; 0.6716827432867392936, -0.8333219883742404
-172 + 3.141592653589793238*I, -0.2461086674077943078, 0.5379005671092853267,
- -1.552661549868775854 + 3.141592653589793238*I, -0.8738318043071131265 + 3.
-141592653589793238*I, 0; -1.918029732621558455 + 3.141592653589793238*I, 0.2
-929213507612934444, 0.9387477816548985923, 1.452155878475514387, 2.383224144
-529494718 + 3.141592653589793238*I, 0.8694561877344533111 + 3.14159265358979
-3238*I, 0], [[3, [-1, 1, 0]~, 1, 1, [1, 10, 45; 1, 7, 6; 1, 1, -3]], [5, [-1
-, 1, 0]~, 1, 1, [0, 10, 45; 1, 6, 6; 1, 1, -4]], [5, [2, 1, 0]~, 1, 1, [1, -
-17, 42; -2, 4, -9; 1, -2, -3]], [5, [3, 1, 0]~, 1, 1, [2, 19, 46; 2, 9, 11; 
-1, 2, -2]], [13, [19, 1, 0]~, 1, 1, [-2, -53, 38; -6, -3, -29; 1, -6, -6]], 
-[11, [1, 1, 0]~, 1, 1, [-3, -8, 43; -1, 1, -4; 1, -1, -7]], [3, [10, 1, 1]~,
- 1, 2, [-1, 9, 1; 1, 0, 5; 0, 1, -1]]]~, 0, [x^3 - x^2 - 14*x - 1, [3, 0], 1
-0889, 1, [[1, -3.233732695981516673, 4.690759845041404812; 1, -0.07182350902
-743636345, -8.923017874523549404; 1, 4.305556205008953036, 5.232258029482144
-592], [1, -3.233732695981516673, 4.690759845041404812; 1, -0.071823509027436
-36345, -8.923017874523549404; 1, 4.305556205008953036, 5.232258029482144592]
-, [1, -3, 5; 1, 0, -9; 1, 4, 5], [3, 1, 1; 1, 29, 8; 1, 8, 129], [10889, 569
-8, 8994; 0, 1, 0; 0, 0, 1], [3677, -121, -21; -121, 386, -23; -21, -23, 86],
- [10889, [1899, 46720, 5235; 5191, 7095, 25956; 1, 5191, 1895]], []], [-3.23
-3732695981516673, -0.07182350902743636345, 4.305556205008953036], [1, x, x^2
- - x - 9], [1, 0, 9; 0, 1, 1; 0, 0, 1], [1, 0, 0, 0, 9, 1, 0, 1, 44; 0, 1, 0
-, 1, 1, 5, 0, 5, 1; 0, 0, 1, 0, 1, 0, 1, 0, -4]], [[2, [2], [[3, 2, 0; 0, 1,
- 0; 0, 0, 1]]], 10.34800724602767998, 1, [2, -1], [x, x^2 + 2*x - 4]], [mat(
-1), [[0, 0, 0]], [[1.246346989334819161, 0.6716827432867392936, -1.918029732
-621558455 + 3.141592653589793238*I]]], [[[4, -1, 0]~, [-1, 1, 0]~, [2, 1, 0]
-~, [3, 1, 0]~, [-10, -5, -1]~, [-1, -1, 0]~, [-3, 0, 0]~], 0]]
-? concat(mat(vector(4,x,x)~),vector(4,x,10+x)~)
-
-[1 11]
-
-[2 12]
-
-[3 13]
-
-[4 14]
-
-? matextract(matrix(15,15,x,y,x+y),vector(5,x,3*x),vector(3,y,3*y))
-
-[ 6  9 12]
-
-[ 9 12 15]
-
-[12 15 18]
-
-[15 18 21]
-
-[18 21 24]
-
-? ma=mathell(mcurve,mpoints)
-
-[ 1.172183098700697011 0.4476973883408951692]
-
-[0.4476973883408951692  1.755026016172950714]
-
-? gauss(ma,mhbi)
-[-0.9999999999999999999, 0.9999999999999999999]~
-? (1.*hilbert(7))^(-1)
-
-[49.00000000002166512 -1176.000000000823818 8820.000000007686140 -29400.0000
-0002919865 48510.00000005260063 -38808.00000004482172 12012.00000001455373]
-
-[-1176.000000000829171 37632.00000003143297 -317520.0000002926227 1128960.00
-0001109758 -1940400.000001996436 1596672.000001699551 -504504.0000005513250]
-
-[8820.000000007767680 -317520.0000002938229 2857680.000002730998 -10584000.0
-0001034460 18711000.00001859176 -15717240.00001581475 5045040.000005126835]
-
-[-29400.00000002959150 1128960.000001117474 -10584000.00001037403 40320000.0
-0003925864 -72765000.00007050504 62092800.00005993762 -20180160.00001942077]
-
-[48510.00000005341642 -1940400.000002014519 18711000.00001868372 -72765000.0
-0007065280 133402500.0001268113 -115259760.0001077525 37837800.00003489948]
+New syntax: core2(x) ===> core(x,1)
 
-[-38808.00000004559575 1596672.000001717726 -15717240.00001591859 62092800.0
-0006016001 -115259760.0001079261 100590336.0000916694 -33297264.00002968058]
+core(n,{flag=0}): unique squarefree integer d dividing n such that n/d is a 
+square. If (optional) flag is non-null, output the two-component row vector 
+[d,f], where d is the unique squarefree integer dividing n such that n/d=f^2 is 
+a square.
 
-[12012.00000001482304 -504504.0000005579285 5045040.000005167082 -20180160.0
-0001951774 37837800.00003500041 -33297264.00002971854 11099088.00000961957]
 
-? matsize([1,2;3,4;5,6])
-[3, 2]
-? matrix(5,5,x,y,gcd(x,y))
+  ***   at top-level: coredisc2()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[1 1 1 1 1]
+New syntax: coredisc2(x) ===> coredisc(x,1)
 
-[1 2 1 2 1]
+coredisc(n,{flag=0}): discriminant of the quadratic field Q(sqrt(n)). If 
+(optional) flag is non-null, output a two-component row vector [d,f], where d 
+is the discriminant of the quadratic field Q(sqrt(n)) and n=df^2. f may be a 
+half integer.
 
-[1 1 3 1 1]
 
-[1 2 1 4 1]
+  ***   at top-level: cvtoi()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[1 1 1 1 5]
+New syntax: cvtoi(x) ===> truncate(x,&e)
 
-? matrixqz([1,3;3,5;5,7],0)
+truncate(x,{&e}): truncation of x; when x is a power series,take away the 
+O(X^). If e is present, do not take into account loss of integer part 
+precision, and set e = error estimate in bits.
 
-[1 1]
 
-[3 2]
+  ***   at top-level: cyclo()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[5 3]
+New syntax: cyclo(n) ===> polcyclo(n)
 
-? matrixqz2([1/3,1/4,1/6;1/2,1/4,-1/4;1/3,1,0])
+polcyclo(n,{a = 'x}): n-th cyclotomic polynomial evaluated at a.
 
-[19 12 2]
 
-[ 0  1 0]
+  ***   at top-level: decodefactor()
+  ***                 ^--------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[ 0  0 1]
+New syntax: decodefactor(fa) ===> factorback(fa)
 
-? matrixqz3([1,3;3,5;5,7])
+factorback(f,{e}): given a factorisation f, gives the factored object back. If 
+this is a prime ideal factorisation you must supply the corresponding number 
+field as last argument. If e is present, f has to be a vector of the same 
+length, and we return the product of the f[i]^e[i].
+
+
+  ***   at top-level: decodemodule()
+  ***                 ^--------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: decodemodule(nf,fa) ===> bnfdecodemodule(nf,fa)
+
+bnfdecodemodule(nf,m): given a coded module m as in bnrdisclist, gives the true 
+module.
+
+
+  ***   at top-level: degree()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: degree(x) ===> poldegree(x)
+
+poldegree(x,{v}): degree of the polynomial or rational function x with respect 
+to main variable if v is omitted, with respect to v otherwise. For scalar x, 
+return 0 is x is non-zero and -oo otherwise.
+
+
+  ***   at top-level: denom()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: denom(x) ===> denominator(x)
+
+denominator(x): denominator of x (or lowest common denominator in case of an 
+array).
+
+
+  ***   at top-level: deplin()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: deplin(x) ===> lindep(x,-1)
+
+lindep(v,{flag=0}): integral linear dependencies between components of v. flag 
+is optional, and can be 0: default, guess a suitable accuracy, or positive: 
+accuracy to use for the computation, in decimal digits.
+
+
+  ***   at top-level: det()
+  ***                 ^-----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: det(x) ===> matdet(x)
+
+matdet(x,{flag=0}): determinant of the matrix x using an appropriate algorithm 
+depending on the coefficients. If (optional) flag is set to 1, use classical 
+Gaussian elimination (usually worse than the default).
+
+
+  ***   at top-level: det2()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: det2(x) ===> matdet(x,1)
+
+matdet(x,{flag=0}): determinant of the matrix x using an appropriate algorithm 
+depending on the coefficients. If (optional) flag is set to 1, use classical 
+Gaussian elimination (usually worse than the default).
+
+
+  ***   at top-level: detint()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: detint(x) ===> matdetint(x)
+
+matdetint(B): some multiple of the determinant of the lattice generated by the 
+columns of B (0 if not of maximal rank). Useful with mathnfmod.
+
+
+  ***   at top-level: diagonal()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: diagonal(x) ===> matdiagonal(x)
+
+matdiagonal(x): creates the diagonal matrix whose diagonal entries are the 
+entries of the vector x.
+
+
+  ***   at top-level: disc()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: disc(x) ===> poldisc(x)
+
+poldisc(pol,{v}): discriminant of the polynomial pol, with respect to main 
+variable if v is omitted, with respect to v otherwise.
+
+
+  ***   at top-level: discf()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: discf(x) ===> nfdisc(x)
+
+nfdisc(T): discriminant of the number field defined by the polynomial T. An 
+argument [T,listP] is possible, where listP is a list of primes or a prime 
+bound.
+
+
+  ***   at top-level: discf2()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: discf2(x) ===> nfdisc(x,2)
+
+nfdisc(T): discriminant of the number field defined by the polynomial T. An 
+argument [T,listP] is possible, where listP is a list of primes or a prime 
+bound.
+
+
+  ***   at top-level: discrayabs()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: discrayabs(bnr,subgroup) ===> bnrdisc(bnr,subgroup)
+
+bnrdisc(A,{B},{C},{flag=0}): absolute or relative [N,R1,discf] of the field 
+defined by A,B,C. [A,{B},{C}] is of type [bnr], [bnr,subgroup], [bnf, modulus] 
+or [bnf,modulus,subgroup], where bnf is as output by bnfinit, bnr by bnrinit, 
+and subgroup is the HNF matrix of a subgroup of the corresponding ray class 
+group (if omitted, the trivial subgroup). flag is optional whose binary digits 
+mean 1: give relative data; 2: return 0 if modulus is not the conductor.
+
+
+  ***   at top-level: discrayabscond()
+  ***                 ^----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: discrayabscond(bnr) ===> bnrdisc(bnr,,,2)
+
+bnrdisc(A,{B},{C},{flag=0}): absolute or relative [N,R1,discf] of the field 
+defined by A,B,C. [A,{B},{C}] is of type [bnr], [bnr,subgroup], [bnf, modulus] 
+or [bnf,modulus,subgroup], where bnf is as output by bnfinit, bnr by bnrinit, 
+and subgroup is the HNF matrix of a subgroup of the corresponding ray class 
+group (if omitted, the trivial subgroup). flag is optional whose binary digits 
+mean 1: give relative data; 2: return 0 if modulus is not the conductor.
+
+
+  ***   at top-level: discrayabslist()
+  ***                 ^----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: discrayabslist(bnf,list) ===> bnrdisclist(bnf,list)
+
+bnrdisclist(bnf,bound,{arch}): gives list of discriminants of ray class fields 
+of all conductors up to norm bound, in a long vector The ramified Archimedean 
+places are given by arch; all possible values are taken if arch is omitted. 
+Supports the alternative syntax bnrdisclist(bnf,list), where list is as output 
+by ideallist or ideallistarch (with units).
+
+
+  ***   at top-level: discrayabslistarch()
+  ***                 ^--------------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: discrayabslistarch(bnf,arch,bound) ===> bnrdisclist(bnf,bound,arch)
+
+bnrdisclist(bnf,bound,{arch}): gives list of discriminants of ray class fields 
+of all conductors up to norm bound, in a long vector The ramified Archimedean 
+places are given by arch; all possible values are taken if arch is omitted. 
+Supports the alternative syntax bnrdisclist(bnf,list), where list is as output 
+by ideallist or ideallistarch (with units).
+
+
+  ***   at top-level: discrayabslistarchal
+  ***                 ^--------------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
 
-[2 -1]
+New syntax: discrayabslistarchall(bnf,bound) ===> bnrdisclist(bnf,bound,,1)
 
-[1  0]
+bnrdisclist(bnf,bound,{arch}): gives list of discriminants of ray class fields 
+of all conductors up to norm bound, in a long vector The ramified Archimedean 
+places are given by arch; all possible values are taken if arch is omitted. 
+Supports the alternative syntax bnrdisclist(bnf,list), where list is as output 
+by ideallist or ideallistarch (with units).
 
-[0  1]
 
-? max(2,3)
-3
-? min(2,3)
-2
-? minim([2,1;1,2],4,6)
-[6, 2, [0, -1, 1; 1, 1, 0]]
-? mod(-12,7)
-mod(2, 7)
-? modp(-12,7)
-mod(2, 7)
-? mod(10873,49649)^-1
-  ***   at top-level: mod(10873,49649)^-1
-  ***                                 ^---
-  *** _^_: impossible inverse in Fp_inv: mod(131, 49649).
-? modreverse(mod(x^2+1,x^3-x-1))
-mod(x^2 - 3*x + 2, x^3 - 5*x^2 + 8*x - 5)
-? move(0,243,583);cursor(0)
-? mu(3*5*7*11*13)
--1
-? newtonpoly(x^4+3*x^3+27*x^2+9*x+81,3)
-[2, 2/3, 2/3, 2/3]
-? nextprime(100000000000000000000000)
-100000000000000000000117
-? setrand(1);n=10^8;a=matrix(3,5,j,k,vvector(5,l,random()\n))
-
-[[3, 13, 9, 6, 18]~ [18, 1, 20, 4, 7]~ [11, 6, 19, 10, 18]~ [18, 4, 7, 6, 18
-]~ [6, 7, 10, 9, 15]~]
-
-[[6, 17, 13, 19, 5]~ [7, 13, 4, 10, 13]~ [11, 14, 18, 0, 20]~ [9, 8, 2, 4, 1
-4]~ [16, 2, 1, 8, 16]~]
-
-[[6, 17, 13, 14, 18]~ [5, 6, 20, 21, 1]~ [0, 16, 8, 7, 5]~ [17, 16, 21, 0, 1
-3]~ [3, 7, 8, 16, 18]~]
-
-? aid=[idx,idy,idz,idmat(5),idx]
-[[3, 2, 1, 0, 1; 0, 1, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1]
-, [5, 0, 0, 0, 2; 0, 5, 0, 0, 2; 0, 0, 5, 0, 1; 0, 0, 0, 5, 2; 0, 0, 0, 0, 1
-], [15, 10, 5, 0, 12; 0, 5, 0, 0, 2; 0, 0, 5, 0, 1; 0, 0, 0, 5, 2; 0, 0, 0, 
-0, 1], [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], [3, 2, 1, 0, 1; 0, 1, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0, 0, 0
-, 0, 1]]
-? bb=algtobasis(nf,mod(x^3+x,nfpol))
-[1, 1, 4, 1, 3]~
-? da=nfdetint(nf,[a,aid])
-
-[15 10 5 0 12]
-
-[ 0  5 0 0  2]
-
-[ 0  0 5 0  1]
-
-[ 0  0 0 5  2]
-
-[ 0  0 0 0  1]
-
-? nfdiv(nf,ba,bb)
-[584/373, 66/373, -32/373, -105/373, 120/373]~
-? nfdiveuc(nf,ba,bb)
-[2, 0, 0, 0, 0]~
-? nfdivres(nf,ba,bb)
-[[2, 0, 0, 0, 0]~, [4, -1, -5, -1, -3]~]
-? nfhermite(nf,[a,aid])
-[[1, -1, -1; 0, 1, 0; 0, 0, 1], [[3, 2, 1, 0, 1; 0, 1, 0, 0, 0; 0, 0, 1, 0, 
-0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], 1, 1]]
-? nfhermitemod(nf,[a,aid],da)
-[[1, -1, -1; 0, 1, 0; 0, 0, 1], [[3, 2, 1, 0, 1; 0, 1, 0, 0, 0; 0, 0, 1, 0, 
-0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], 1, 1]]
-? nfmod(nf,ba,bb)
-[4, -1, -5, -1, -3]~
-? nfmul(nf,ba,bb)
-[50, -15, -35, 60, 15]~
-? nfpow(nf,bb,5)
-[-291920, 136855, 230560, -178520, 74190]~
-? nfreduce(nf,ba,idx)
-[1, 0, 0, 0, 0]~
-? nfsmith(nf,[a[,1..3],[1,1,1],[idealinv(nf,idx),idealinv(nf,idy),1]])
-[[5113790367401366394295125, 4367721766083689974291960, 47291190972301090559
-2775, 4905437241737335488566685, 4697851874666647634403882; 0, 5, 0, 0, 2; 0
-, 0, 5, 0, 1; 0, 0, 0, 5, 2; 0, 0, 0, 0, 1], [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], [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]]
-? nfval(nf,ba,vp)
-0
-? norm(1+i)
-2
-? norm(mod(x+5,x^3+x+1))
-129
-? norml2(vector(10,x,x))
-385
-? nucomp(qfi(2,1,9),qfi(4,3,5),3)
-qfi(2, -1, 9)
-? form=qfi(2,1,9);nucomp(form,form,3)
-qfi(4, -3, 5)
-? numdiv(2^99*3^49)
-5000
-? numer((x+1)/(x-1))
-x + 1
-? nupow(form,111)
-qfi(2, -1, 9)
-? 1/(1+x)+o(x^20)
-1 - x + x^2 - x^3 + x^4 - x^5 + x^6 - x^7 + x^8 - x^9 + x^10 - x^11 + x^12 -
- x^13 + x^14 - x^15 + x^16 - x^17 + x^18 - x^19 + O(x^20)
-? omega(100!)
-25
-? ordell(acurve,1)
-[8, 3]
-? order(mod(33,2^16+1))
-2048
-? tcurve=initell([1,0,1,-19,26]);
-? orderell(tcurve,[1,2])
-6
-? ordred(x^3-12*x+45*x-1)
-[x - 1, x^3 + 33*x - 1]
-? padicprec(padicno,127)
-5
-? pascal(8)
-
-[1 0  0  0  0  0  0 0 0]
-
-[1 1  0  0  0  0  0 0 0]
-
-[1 2  1  0  0  0  0 0 0]
-
-[1 3  3  1  0  0  0 0 0]
-
-[1 4  6  4  1  0  0 0 0]
-
-[1 5 10 10  5  1  0 0 0]
-
-[1 6 15 20 15  6  1 0 0]
-
-[1 7 21 35 35 21  7 1 0]
-
-[1 8 28 56 70 56 28 8 1]
-
-? perf([2,0,1;0,2,1;1,1,2])
-6
-? permutation(7,1035)
-[2, 4, 6, 1, 5, 7, 3]
-? permutation2num([4,7,1,6,3,5,2])
-2781
-? pf(-44,3)
-qfi(3, 2, 4)
-? phi(257^2)
-65792
-? pi
-3.141592653589793239
-? b=10;a=1<<b;plot(x=-5,5,round(sin(x)<<b)/a)
-
-        1 x""x_''''''''''''''''''''''''''''''''''_x""x'''''''''''''''''''|
-          |    x                                _     "_                 |
-          |     x                              _        _                |
-          |      x                            _                          |
-          |       _                                      "               |
-          |                                  "            x              |
-          |        x                        _                            |
-          |                                                "             |
-          |         "                      x                _            |
-          |          _                                                   |
-          |                               "                  x           |
-          ````````````x``````````````````_````````````````````````````````
-          |                                                   "          |
-          |            "                x                      _         |
-          |             _                                                |
-          |                            "                        x        |
-          |              x            _                                  |
-          |               _                                      "       |
-          |                          "                            x      |
-          |                "        "                              x     |
-          |                 "_     "                                x    |
-       -1 |...................x__x".................................."x__x
-          -5                                                             5
-? pnqn([2,6,10,14,18,22,26])
-
-[19318376 741721]
-
-[ 8927353 342762]
-
-? pnqn([1,1,1,1,1,1,1,1;1,1,1,1,1,1,1,1])
-
-[34 21]
-
-[21 13]
-
-? point(0,225,334)
-? points(0,vector(10,k,10*k),vector(10,k,5*k*k))
-? pointell(acurve,zell(acurve,apoint))
-[1.000000000000000000, 3.000000000000000000]
-? polint([0,2,3],[0,4,9],5)
-25
-? polred(x^5-2*x^4-4*x^3-96*x^2-352*x-568)
-[x - 1, x^5 - x^4 + 2*x^3 - 4*x^2 + x - 1]
-? polred2(x^4-28*x^3-458*x^2+9156*x-25321)
-
-[                                                1           x - 1]
-
-[                   1/115*x^2 - 14/115*x - 212/115   x^2 - 2*x - 9]
-
-[                  -1/115*x^2 + 14/115*x + 442/115   x^2 - 2*x - 9]
-
-[                   1/115*x^2 - 14/115*x - 327/115        x^2 - 10]
-
-[1/4485*x^3 - 7/1495*x^2 - 1034/4485*x + 7924/4485 x^4 - 8*x^2 + 6]
-
-? polredabs(x^5-2*x^4-4*x^3-96*x^2-352*x-568)
-x^5 - x^4 + 2*x^3 - 4*x^2 + x - 1
-? polredabs2(x^5-2*x^4-4*x^3-96*x^2-352*x-568)
-[x^5 - x^4 + 2*x^3 - 4*x^2 + x - 1, mod(2*x^4 - x^3 + 3*x^2 - 3*x - 1, x^5 -
- x^4 + 2*x^3 - 4*x^2 + x - 1)]
-? polsym(x^17-1,17)
-[17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17]~
-? polvar(name^4-other)
-name
-? poly(sin(x),x)
--1/1307674368000*x^15 + 1/6227020800*x^13 - 1/39916800*x^11 + 1/362880*x^9 -
- 1/5040*x^7 + 1/120*x^5 - 1/6*x^3 + x
-? polylog(5,0.5)
-0.5084005792422687074
-? polylog(-4,t)
-(t^4 + 11*t^3 + 11*t^2 + t)/(-t^5 + 5*t^4 - 10*t^3 + 10*t^2 - 5*t + 1)
-? polylogd(5,0.5)
-1.033792745541689064
-? polylogdold(5,0.5)
-1.034459423449010486
-? polylogp(5,0.5)
-0.9495693489964922601
-? poly([1,2,3,4,5],x)
-x^4 + 2*x^3 + 3*x^2 + 4*x + 5
-? polyrev([1,2,3,4,5],x)
-5*x^4 + 4*x^3 + 3*x^2 + 2*x + 1
-? polzag(6,3)
-4608*x^6 - 13824*x^5 + 46144/3*x^4 - 23168/3*x^3 + 5032/3*x^2 - 120*x + 1
-? postdraw([0,20,20])
-? postploth(x=-5,5,sin(x))
-[-5.000000000000000000, 5.000000000000000000, -0.9999964107564721649, 0.9999
-964107564721649]
-? postploth2(t=0,2*pi,[sin(5*t),sin(7*t)])
-[-0.9999994509568810308, 0.9999994509568810308, -0.9999994509568810308, 0.99
-99994509568810308]
-? postplothraw(vector(100,k,k),vector(100,k,k*k/100))
-[1.000000000000000000, 100.0000000000000000, 0.01000000000000000021, 100.000
-0000000000000]
-? powell(acurve,apoint,10)
-[-28919032218753260057646013785951999/292736325329248127651484680640160000, 
-478051489392386968218136375373985436596569736643531551/158385319626308443937
-475969221994173751192384064000000]
-? cmcurve=initell([0,-3/4,0,-2,-1])
-[0, -3/4, 0, -2, -1, -3, -4, -4, -1, 105, 1323, -343, -3375, Vecsmall([1]), 
-[Vecsmall([64, -1])], [0, 0, 0, 0, 0, 0, 0, 0]]
-? powell(cmcurve,[x,y],quadgen(-7))
-[((-2 + 3*w)*x^2 + (6 - w))/((-2 - 5*w)*x + (-4 - 2*w)), ((34 - 11*w)*x^3 + 
-(40 - 28*w)*x^2 + (22 + 23*w)*x)/((-90 - w)*x^2 + (-136 + 44*w)*x + (-40 + 2
-8*w))]
-? powrealraw(qfr(5,3,-1,0.),3)
-qfr(125, 23, 1, 0.E-18)
-? pprint((x-12*y)/(y+13*x));
--11/14
-? pprint([1,2;3,4])
-[1, 2; 3, 4]
-? pprint1(x+y);pprint(x+y);
-2*x2*x
-? \precision=96
-   realprecision = 96 significant digits
-? pi
-3.14159265358979323846264338327950288419716939937510582097494459230781640628
-620899862803482534212
-? prec(pi,20)
-3.1415926535897932384626433833
-? precision(cmcurve)
-28
-? \precision=38
-   realprecision = 38 significant digits
-? prime(100)
-541
-? primedec(nf,2)
-[[2, [3, 0, 1, 0, 0]~, 1, 1, [0, 2, 0, -4, -2; 0, 0, 0, 2, 0; 0, 0, -2, -2, 
--2; 1, 0, 3, 0, -1; 1, 0, 1, 0, -1]], [2, [12, -4, -2, 11, 3]~, 1, 4, [1, -1
-, 3, -1, 1; 0, 0, -2, -1, 1; 1, 0, 1, 0, -2; 0, 0, 1, 2, 2; 0, -1, 0, 1, 1]]
-]
-? primedec(nf,3)
-[[3, [1, 0, 1, 0, 0]~, 1, 1, [1, 4, -1, 6, -4; -1, 2, 4, 3, -5; -1, -1, 1, 0
-, 4; -1, -1, -2, 0, -2; 0, 3, 0, 0, 0]], [3, [1, 1, 1, 0, 0]~, 2, 2, [0, -6,
- 3, -9, 9; 2, -1, -7, -5, 7; 2, 1, 0, 1, -7; 1, 2, 3, 2, 4; 0, -5, -1, 0, 2]
-]]
-? primedec(nf,11)
-[[11, [11, 0, 0, 0, 0]~, 1, 5, 1]]
-? primes(100)
-[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
- 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 
-157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 2
-39, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 33
-1, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421
-, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509,
- 521, 523, 541]
-? forprime(p=2,100,print(p," ",lift(primroot(p))))
-2 1
-3 2
-5 2
-7 3
-11 2
-13 2
-17 3
-19 2
-23 5
-29 2
-31 3
-37 2
-41 6
-43 3
-47 5
-53 2
-59 2
-61 2
-67 2
-71 7
-73 5
-79 3
-83 2
-89 3
-97 5
-? principalideal(nf,mod(x^3+5,nfpol))
-[6, 1, 3, 1, 3]~
-? print((x-12*y)/(y+13*x));
--11/14
-? print([1,2;3,4])
-[1, 2; 3, 4]
-? print1(x+y);print1(" equals ");print(x+y);
-2*x equals 2*x
-? prod(1,k=1,10,1+1/k!)
-3335784368058308553334783/905932868585678438400000
-? prod(1.,k=1,10,1+1/k!)
-3.6821540356142043935732308433185262946
-? pi^2/6*prodeuler(p=2,10000,1-p^-2)
-1.0000098157493066238697591433298145222
-? prodinf(n=0,(1+2^-n)/(1+2^(-n+1)))
-0.33333333333333333333333333333333333329
-? prodinf1(n=0,-2^-n/(1+2^(-n+1)))
-0.33333333333333333333333333333333333329
-? psi(1)
--0.57721566490153286060651209008240243104
-? quaddisc(-252)
--7
-? quadgen(-11)
-w
-? quadpoly(-11)
-x^2 - x + 3
-? rank(matrix(5,5,x,y,x+y))
-2
-? rayclassno(bnf,[[5,3;0,1],[1,0]])
-12
-? rayclassnolist(bnf,lu)
-[[3], [], [3, 3], [3], [6, 6], [], [], [], [3, 3, 3], [], [3, 3], [3, 3], []
-, [], [12, 6, 6, 12], [3], [3, 3], [], [9, 9], [6, 6], [], [], [], [], [6, 1
-2, 6], [], [3, 3, 3, 3], [], [], [], [], [], [3, 6, 6, 3], [], [], [9, 3, 9]
-, [6, 6], [], [], [], [], [], [3, 3], [3, 3], [12, 12, 6, 6, 12, 12], [], []
-, [6, 6], [9], [], [3, 3, 3, 3], [], [3, 3], [], [6, 12, 12, 6]]
-? move(0,50,50);rbox(0,50,50)
-? print1("give a value for s? ");s=read();print(1/s)
-give a value for s? 37.
-0.027027027027027027027027027027027027027
-? real(5-7*i)
-5
-? recip(3*x^7-5*x^3+6*x-9)
--9*x^7 + 6*x^6 - 5*x^4 + 3
-? redimag(qfi(3,10,12))
-qfi(3, -2, 4)
-? redreal(qfr(3,10,-20,1.5))
-qfr(3, 16, -7, 1.5000000000000000000000000000000000000)
-? redrealnod(qfr(3,10,-20,1.5),18)
-qfr(3, 16, -7, 1.5000000000000000000000000000000000000)
-? reduceddisc(x^3+4*x+12)
-[1036, 4, 1]
-? regula(17)
-2.0947125472611012942448228460655286535
-? kill(y);print(x+y);
-x + y
-? resultant(x^3-1,x^3+1)
-8
-? resultant2(x^3-1.,x^3+1.)
-8.0000000000000000000000000000000000000
-? bezoutres(x^2+1,x^2-1)
-[2, -2, 4]
-? reverse(tan(x))
-x - 1/3*x^3 + 1/5*x^5 - 1/7*x^7 + 1/9*x^9 - 1/11*x^11 + 1/13*x^13 - 1/15*x^1
-5 + O(x^17)
-? rhoreal(qfr(3,10,-20,1.5))
-qfr(-20, -10, 3, 2.1074451073987839947135880252731470616)
-? rhorealnod(qfr(3,10,-20,1.5),18)
-qfr(-20, -10, 3, 1.5000000000000000000000000000000000000)
-? rline(0,200,150)
-? cursor(0)
-? rmove(0,5,5);cursor(0)
-? rndtoi(prod(1,k=1,17,x-exp(2*i*pi*k/17)))
-x^17 - 1
-? qpol=y^3-y-1;setrand(1);bnf2=buchinit(qpol);nf2=bnf2[7];
-? un=mod(1,qpol);w=mod(y,qpol);p=un*(x^5-5*x+w)
-mod(1, y^3 - y - 1)*x^5 + mod(-5, y^3 - y - 1)*x + mod(y, y^3 - y - 1)
-? aa=rnfpseudobasis(nf2,p)
-[[1, 0, 0, -2, [3, 1, 0]~; 0, 1, 0, 2, [0, -1, 0]~; 0, 0, 1, 1, [-5, -2, 0]~
-; 0, 0, 0, 1, -2; 0, 0, 0, 0, 1], [1, 1, 1, [1, 0, 2/5; 0, 1, 3/5; 0, 0, 1/5
-], [1, 0, 22/25; 0, 1, 8/25; 0, 0, 1/25]], [416134375, 202396875, 60056800; 
-0, 3125, 2700; 0, 0, 25], [-1275, 5, 5]~]
-? rnfbasis(bnf2,aa)
-
-[1 0 0  [-26/25, 11/25, -8/25]~         [0, 4, -7]~]
-
-[0 1 0   [53/25, -8/25, -1/25]~ [6/5, -41/5, 53/5]~]
-
-[0 0 1 [-14/25, -21/25, 13/25]~  [-16/5, 1/5, 7/5]~]
-
-[0 0 0     [7/25, -2/25, 6/25]~  [2/5, -2/5, 11/5]~]
-
-[0 0 0     [9/25, 1/25, -3/25]~   [2/5, -7/5, 6/5]~]
-
-? rnfdiscf(nf2,p)
-[[416134375, 202396875, 60056800; 0, 3125, 2700; 0, 0, 25], [-1275, 5, 5]~]
-? rnfequation(nf2,p)
-x^15 - 15*x^11 + 75*x^7 - x^5 - 125*x^3 + 5*x + 1
-? rnfequation2(nf2,p)
-[x^15 - 15*x^11 + 75*x^7 - x^5 - 125*x^3 + 5*x + 1, mod(-x^5 + 5*x, x^15 - 1
-5*x^11 + 75*x^7 - x^5 - 125*x^3 + 5*x + 1), 0]
-? rnfhermitebasis(bnf2,aa)
-
-[1 0 0 [-6/5, -4/5, 2/5]~   [3/25, -8/25, 24/25]~]
-
-[0 1 0  [6/5, 4/5, -2/5]~   [-9/25, -1/25, 3/25]~]
-
-[0 0 1  [3/5, 2/5, -1/5]~ [-8/25, 13/25, -39/25]~]
-
-[0 0 0  [3/5, 2/5, -1/5]~   [4/25, 6/25, -18/25]~]
-
-[0 0 0                  0   [-2/25, -3/25, 9/25]~]
-
-? rnfisfree(bnf2,aa)
-1
-? rnfsteinitz(nf2,aa)
-[[1, 0, 0, [-26/25, 11/25, -8/25]~, [29/125, -2/25, 8/125]~; 0, 1, 0, [53/25
-, -8/25, -1/25]~, [-53/125, 7/125, 1/125]~; 0, 0, 1, [-14/25, -21/25, 13/25]
-~, [9/125, 19/125, -13/125]~; 0, 0, 0, [7/25, -2/25, 6/25]~, [-9/125, 2/125,
- -6/125]~; 0, 0, 0, [9/25, 1/25, -3/25]~, [-8/125, -1/125, 3/125]~], [1, 1, 
-1, 1, [125, 0, 22; 0, 125, 108; 0, 0, 1]], [416134375, 202396875, 60056800; 
-0, 3125, 2700; 0, 0, 25], [-1275, 5, 5]~]
-? rootmod(x^16-1,41)
-[mod(1, 41), mod(3, 41), mod(9, 41), mod(14, 41), mod(27, 41), mod(32, 41), 
-mod(38, 41), mod(40, 41)]~
-? rootpadic(x^4+1,41,6)
-[3 + 22*41 + 27*41^2 + 15*41^3 + 27*41^4 + 33*41^5 + O(41^6), 14 + 20*41 + 2
-5*41^2 + 24*41^3 + 4*41^4 + 18*41^5 + O(41^6), 27 + 20*41 + 15*41^2 + 16*41^
-3 + 36*41^4 + 22*41^5 + O(41^6), 38 + 18*41 + 13*41^2 + 25*41^3 + 13*41^4 + 
-7*41^5 + O(41^6)]~
-? roots(x^5-5*x^2-5*x-5)
-[2.0509134529831982130058170163696514536 + 0.E-38*I, -0.67063790319207539268
-663382582902335603 - 0.84813118358634026680538906224199030918*I, -0.67063790
-319207539268663382582902335603 + 0.84813118358634026680538906224199030918*I,
- -0.35481882329952371381627468235580237078 - 1.39980287391035466982975228340
-62081965*I, -0.35481882329952371381627468235580237078 + 1.399802873910354669
-8297522834062081965*I]~
-? rootsold(x^4-1000000000000000000000)
-  ***   at top-level: rootsold(x^4-1000000
+  ***   at top-level: discrayabslistlong()
   ***                 ^--------------------
-  *** rootsold: this function no longer exists.
-? round(prod(1,k=1,17,x-exp(2*i*pi*k/17)))
-x^17 - 1
-? rounderror(prod(1,k=1,17,x-exp(2*i*pi*k/17)))
--35
-? rpoint(0,20,20)
-? initrect(3,600,600);scale(3,-7,7,-2,2);cursor(3)
-? q*series(anell(acurve,100),q)
-q - 2*q^2 - 3*q^3 + 2*q^4 - 2*q^5 + 6*q^6 - q^7 + 6*q^9 + 4*q^10 - 5*q^11 - 
-6*q^12 - 2*q^13 + 2*q^14 + 6*q^15 - 4*q^16 - 12*q^18 - 4*q^20 + 3*q^21 + 10*
-q^22 + 2*q^23 - q^25 + 4*q^26 - 9*q^27 - 2*q^28 + 6*q^29 - 12*q^30 - 4*q^31 
-+ 8*q^32 + 15*q^33 + 2*q^35 + 12*q^36 - q^37 + 6*q^39 - 9*q^41 - 6*q^42 + 2*
-q^43 - 10*q^44 - 12*q^45 - 4*q^46 - 9*q^47 + 12*q^48 - 6*q^49 + 2*q^50 - 4*q
-^52 + q^53 + 18*q^54 + 10*q^55 - 12*q^58 + 8*q^59 + 12*q^60 - 8*q^61 + 8*q^6
-2 - 6*q^63 - 8*q^64 + 4*q^65 - 30*q^66 + 8*q^67 - 6*q^69 - 4*q^70 + 9*q^71 -
- q^73 + 2*q^74 + 3*q^75 + 5*q^77 - 12*q^78 + 4*q^79 + 8*q^80 + 9*q^81 + 18*q
-^82 - 15*q^83 + 6*q^84 - 4*q^86 - 18*q^87 + 4*q^89 + 24*q^90 + 2*q^91 + 4*q^
-92 + 12*q^93 + 18*q^94 - 24*q^96 + 4*q^97 + 12*q^98 - 30*q^99 - 2*q^100 + O(
-q^101)
-? aset=set([5,-2,7,3,5,1])
-[-2, 1, 3, 5, 7]
-? bset=set([7,5,-5,7,2])
-[-5, 2, 5, 7]
-? setintersect(aset,bset)
-[5, 7]
-? setminus(aset,bset)
-[-2, 1, 3]
-? setprecision(28)
-38
-? setrand(10)
-? setsearch(aset,3)
-3
-? setsearch(bset,3)
-0
-? setserieslength(12)
-16
-? setunion(aset,bset)
-[-5, -2, 1, 2, 3, 5, 7]
-? shift(1,50)
-1125899906842624
-? shift([3,4,-11,-12],-2)
-[0, 1, -2, -3]
-? shiftmul([3,4,-11,-12],-2)
-[3/4, 1, -11/4, -3]
-? sigma(100)
-217
-? sigmak(2,100)
-13671
-? sigmak(-3,100)
-1149823/1000000
-? sign(-1)
--1
-? sign(0)
-0
-? sign(0.)
-0
-? signat(hilbert(5)-0.11*idmat(5))
-[2, 3]
-? signunit(bnf)
-
-[-1]
-
-[ 1]
-
-? simplefactmod(x^11+1,7)
-
-[ 1 1]
-
-[10 1]
-
-? simplify(((x+i+1)^2-x^2-2*x*(i+1))^2)
--4
-? sin(pi/6)
-0.5000000000000000000000000000
-? sinh(1)
-1.175201193643801456882381851
-? size([1.3*10^5,2*i*pi*exp(4*pi)])
-7
-? smallbasis(x^3+4*x+12)
-[1, x, 1/2*x^2]
-? smalldiscf(x^3+4*x+12)
--1036
-? smallfact(100!+1)
-
-[101 1]
-
-[14303 1]
-
-[149239 1]
-
-[432885273849892962613071800918658949059679308685024481795740765527568493010
-727023757461397498800981521440877813288657839195622497225621499427628453 1]
-
-? smallinitell([0,0,0,-17,0])
-[0, 0, 0, -17, 0, 0, -34, 0, -289, 816, 0, 314432, 1728, Vecsmall([1]), [Vec
-small([96, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]
-? smallpolred(x^4+576)
-[x - 1, x^2 - 3*x + 3, x^2 - 2*x + 2, x^2 - x + 1, x^2 + 1, x^4 - x^2 + 1]
-? smallpolred2(x^4+576)
-
-[                           1         x - 1]
-
-[    -1/192*x^3 - 1/8*x + 3/2 x^2 - 3*x + 3]
-
-[                1/24*x^2 + 1 x^2 - 2*x + 2]
-
-[               -1/24*x^2 + 1 x^2 - 2*x + 2]
-
-[    -1/192*x^3 - 1/8*x + 1/2   x^2 - x + 1]
-
-[     1/192*x^3 + 1/8*x + 1/2   x^2 - x + 1]
-
-[                    1/24*x^2       x^2 + 1]
-
-[1/192*x^3 + 1/48*x^2 - 1/8*x x^4 - x^2 + 1]
-
-? smith(matrix(5,5,j,k,random()))
-[1672445828511544211967627586516667006907439878, 2, 1, 1, 1]
-? smith(1/hilbert(6))
-[27720, 2520, 2520, 840, 210, 6]
-? smithpol(x*idmat(5)-matrix(5,5,j,k,1))
-[x^2 - 5*x, x, x, x, 1]
-? solve(x=1,4,sin(x))
-3.141592653589793238462643383
-? sort(vector(17,x,5*x%17))
-[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
-? sqr(1+o(2))
-1 + O(2^3)
-? sqred(hilbert(5))
-
-[1  1/2   1/3    1/4     1/5]
-
-[0 1/12     1   9/10     4/5]
-
-[0    0 1/180    3/2    12/7]
-
-[0    0     0 1/2800       2]
-
-[0    0     0      0 1/44100]
-
-? sqrt(13+o(127^12))
-34 + 125*127 + 83*127^2 + 107*127^3 + 53*127^4 + 42*127^5 + 22*127^6 + 98*12
-7^7 + 127^8 + 23*127^9 + 122*127^10 + 79*127^11 + O(127^12)
-? srgcd(x^10-1,x^15-1)
-x^5 - 1
-? move(0,100,100);string(0,pi)
-? move(0,200,200);string(0,"(0,0)")
-? postdraw([0,10,10])
-? apol=0.3+legendre(10)
-46189/256*x^10 - 109395/256*x^8 + 45045/128*x^6 - 15015/128*x^4 + 3465/256*x
-^2 + 0.05390625000000000000000000000
-? sturm(apol)
-4
-? sturmpart(apol,0.91,1)
-1
-? subcyclo(31,5)
-x^5 + x^4 - 12*x^3 - 21*x^2 + x + 5
-? subell(initell([0,0,0,-17,0]),[-1,4],[-4,2])
-[9, -24]
-? subst(sin(x),x,y)
-y - 1/6*y^3 + 1/120*y^5 - 1/5040*y^7 + 1/362880*y^9 - 1/39916800*y^11 + O(y^
-13)
-? subst(sin(x),x,x+x^2)
-x + x^2 - 1/6*x^3 - 1/2*x^4 - 59/120*x^5 - 1/8*x^6 + 419/5040*x^7 + 59/720*x
-^8 + 13609/362880*x^9 + 19/13440*x^10 - 273241/39916800*x^11 - 14281/3628800
-*x^12 + O(x^13)
-? sum(0,k=1,10,2^-k)
-1023/1024
-? sum(0.,k=1,10,2^-k)
-0.9990234375000000000000000000
-? sylvestermatrix(a2*x^2+a1*x+a0,b1*x+b0)
-
-[a2 b1  0]
-
-[a1 b0 b1]
-
-[a0  0 b0]
-
-? \precision=38
-   realprecision = 38 significant digits
-? 4*sumalt(n=0,(-1)^n/(2*n+1))
-3.1415926535897932384626433832795028842
-? 4*sumalt2(n=0,(-1)^n/(2*n+1))
-3.1415926535897932384626433832795028842
-? suminf(n=1,2.^-n)
-0.99999999999999999999999999999999999999
-? 6/pi^2*sumpos(n=1,n^-2)
-1.0000000000000000000000000000000000000
-? supplement([1,3;2,4;3,6])
-
-[1 3 0]
-
-[2 4 0]
-
-[3 6 1]
-
-? sqr(tan(pi/3))
-3.0000000000000000000000000000000000000
-? tanh(1)
-0.76159415595576488811945828260479359041
-? taniyama(bcurve)
-[x^-2 - x^2 + 3*x^6 - 2*x^10 + O(x^11), -x^-3 + 3*x - 3*x^5 + 8*x^9 + O(x^10
-)]
-? taylor(y/(x-y),y)
-(O(y^12)*x^11 + y*x^10 + y^2*x^9 + y^3*x^8 + y^4*x^7 + y^5*x^6 + y^6*x^5 + y
-^7*x^4 + y^8*x^3 + y^9*x^2 + y^10*x + y^11)/x^11
-? tchebi(10)
-512*x^10 - 1280*x^8 + 1120*x^6 - 400*x^4 + 50*x^2 - 1
-? teich(7+o(127^12))
-7 + 57*127 + 58*127^2 + 83*127^3 + 52*127^4 + 109*127^5 + 74*127^6 + 16*127^
-7 + 60*127^8 + 47*127^9 + 65*127^10 + 5*127^11 + O(127^12)
-? texprint((x+y)^3/(x-y)^2)
-\frac{x^3
- + 3 y x^2
- + 3 y^2 x
- + y^3}{x^2
- - 2 y x
- + y^2}
-? theta(0.5,3)
-0.080806418251894691299871683210466298523
-? thetanullk(0.5,7)
--804.63037320243369422783730584965684023
-? torsell(tcurve)
-[12, [6, 2], [[1, 2], [3, -2]]]
-? trace(1+i)
-2
-? trace(mod(x+5,x^3+x+1))
-15
-? trans(vector(2,x,x))
-[1, 2]~
-? %*%~
-
-[1 2]
-
-[2 4]
-
-? trunc(-2.7)
--2
-? trunc(sin(x^2))
-1/120*x^10 - 1/6*x^6 + x^2
-? tschirnhaus(x^5-x-1)
-x^5 + 10*x^4 + 38*x^3 + 47*x^2 + 27*x + 281
-? type(mod(x,x^2+1))
-9
-? unit(17)
-3 + 2*w
-? n=33;until(n==1,print1(n," ");if(n%2,n=3*n+1,n=n/2));print(1)
-33 100 50 25 76 38 19 58 29 88 44 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
-? valuation(6^10000-1,5)
-5
-? vec(sin(x))
-[1, 0, -1/6, 0, 1/120, 0, -1/5040, 0, 1/362880, 0, -1/39916800, 0]
-? vecmax([-3,7,-2,11])
-11
-? vecmin([-3,7,-2,11])
--3
-? vecsort([[1,8,5],[2,5,8],[3,6,-6],[4,8,6]],2)
-[[2, 5, 8], [3, 6, -6], [1, 8, 5], [4, 8, 6]]
-? vecsort([[1,8,5],[2,5,8],[3,6,-6],[4,8,6]],[2,1])
-[[2, 5, 8], [3, 6, -6], [1, 8, 5], [4, 8, 6]]
-? weipell(acurve)
-x^-2 + 1/5*x^2 - 1/28*x^4 + 1/75*x^6 - 3/1540*x^8 + O(x^10)
-? wf(i)
-1.1892071150027210667174999705604759153
-? wf2(i)
-1.0905077326652576592070106557607079790
-? m=5;while(m<20,print1(m," ");m=m+1);print()
-5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
-? zell(acurve,apoint)
-0.72491221490962306778878739838332384646
-? zeta(3)
-1.2020569031595942853997381615114499908
-? zeta(0.5+14.1347251*i)
-5.2043097453468479398562848599360610966 E-9 - 3.2690639869786982176409251733
-763732423 E-8*I
-? zetak(nfz,-3)
-0.091666666666666666666666666666666666667
-? zetak(nfz,1.5+3*i)
-0.88324345992059326405525724366416928892 - 0.2067536250233895222724230899142
-7938848*I
-? zidealstar(nf2,54)
-[132678, [1638, 9, 9], [[11, -3, 11]~, [1, -24, 0]~, [-23, -18, -12]~]]
-? bid=zidealstarinit(nf2,54)
-[[[54, 0, 0; 0, 54, 0; 0, 0, 54], [0]], [132678, [1638, 9, 9]], [[2, [2, 0, 
-0]~, 1, 3, 1], 1; [3, [3, 0, 0]~, 1, 3, 1], 3], [[[[7], [[1, 1, 0]~], [[1, -
-27, 0]~], [Vecsmall([])], 1]], [[[26], [[4, 2, 1]~], [[-23, 2, -26]~], [Vecs
-mall([])], 1], [[3, 3, 3], [4, [1, 3, 0]~, [1, 0, 3]~], [-77, [1, -24, 0]~, 
-[1, 0, -24]~], [Vecsmall([]), Vecsmall([]), Vecsmall([])], [1/3, 0, 0; 0, 1/
-3, 0; 0, 0, 1/3]], [[3, 3, 3], [10, [1, 9, 0]~, [1, 0, 9]~], [-233, [1, -18,
- 0]~, [1, 0, -18]~], [Vecsmall([]), Vecsmall([]), Vecsmall([])], [1/9, 0, 0;
- 0, 1/9, 0; 0, 0, 1/9]]], [[], [], []]], [468, -77, 0, 728, -1456, 0, 546, -
-1092; 0, 0, 1, 0, -1, -6, 0, -3; 0, 1, 0, -1, 1, 0, -3, 3]]
-? zideallog(nf2,w,bid)
-[752, 1, 1]~
-? znstar(3120)
-[768, [12, 4, 4, 2, 2], [mod(2641, 3120), mod(2341, 3120), mod(2497, 3120), 
-mod(391, 3120), mod(2081, 3120)]]
-? sin'(4)
--0.65364362086361191463916818309775038142
-? m=3;if(m==1,2,m==3,4,5)
-4
-? a=[1,2,3];
-? deplin(a)
-[-2, 1, 0]~
-? deplin(mod(a,2))
-[0, 1, 0]~
-? deplin(mod(a,7))
-[-2, 1, 0]~
-? deplin(mod(a,2^64+13))
-[-2, 1, 0]~
-? p=2^64+13;t=char(mod(4*p*y+1,y^4+1),x);discf2(t)
-256
-? getstack()
-104
-? getheap()
-[721, 108902]
-? print("Total time spent: ",gettime);
-Total time spent: 228
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: discrayabslistlong(bnf,bound) ===> bnrdisclist(bnf,bound)
+
+bnrdisclist(bnf,bound,{arch}): gives list of discriminants of ray class fields 
+of all conductors up to norm bound, in a long vector The ramified Archimedean 
+places are given by arch; all possible values are taken if arch is omitted. 
+Supports the alternative syntax bnrdisclist(bnf,list), where list is as output 
+by ideallist or ideallistarch (with units).
+
+
+  ***   at top-level: discrayrel()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: discrayrel(bnr,subgroup) ===> bnrdisc(bnr,subgroup,,1)
+
+bnrdisc(A,{B},{C},{flag=0}): absolute or relative [N,R1,discf] of the field 
+defined by A,B,C. [A,{B},{C}] is of type [bnr], [bnr,subgroup], [bnf, modulus] 
+or [bnf,modulus,subgroup], where bnf is as output by bnfinit, bnr by bnrinit, 
+and subgroup is the HNF matrix of a subgroup of the corresponding ray class 
+group (if omitted, the trivial subgroup). flag is optional whose binary digits 
+mean 1: give relative data; 2: return 0 if modulus is not the conductor.
+
+
+  ***   at top-level: discrayrelcond()
+  ***                 ^----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: discrayrelcond(bnr,subgroup) ===> bnrdisc(bnr,subgroup,,3)
+
+bnrdisc(A,{B},{C},{flag=0}): absolute or relative [N,R1,discf] of the field 
+defined by A,B,C. [A,{B},{C}] is of type [bnr], [bnr,subgroup], [bnf, modulus] 
+or [bnf,modulus,subgroup], where bnf is as output by bnfinit, bnr by bnrinit, 
+and subgroup is the HNF matrix of a subgroup of the corresponding ray class 
+group (if omitted, the trivial subgroup). flag is optional whose binary digits 
+mean 1: give relative data; 2: return 0 if modulus is not the conductor.
+
+
+  ***   at top-level: divres()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: divres(x,y) ===> divrem(x,y)
+
+divrem(x,y,{v}): euclidean division of x by y giving as a 2-dimensional column 
+vector the quotient and the remainder, with respect to v (to main variable if v 
+is omitted)
+
+
+  ***   at top-level: divsum()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: divsum(n,X,expr) ===> sumdiv(n,X,expr)
+
+sumdiv(n,X,expr): sum of expression expr, X running over the divisors of n.
+
+
+  ***   at top-level: eigen()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: eigen(x) ===> mateigen(x)
+
+mateigen(x,{flag=0}): complex eigenvectors of the matrix x given as columns of 
+a matrix H. If flag=1, return [L,H], where L contains the eigenvalues and H the 
+corresponding eigenvectors.
+
+
+  ***   at top-level: euler()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: euler ===> Euler
+
+Euler=Euler(): Euler's constant with current precision.
+
+
+  ***   at top-level: extract()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: extract(x,y) ===> vecextract(x,y)
+
+vecextract(x,y,{z}): extraction of the components of the matrix or vector x 
+according to y and z. If z is omitted, y represents columns, otherwise y 
+corresponds to rows and z to columns. y and z can be vectors (of indices), 
+strings (indicating ranges as in "1..10") or masks (integers whose binary 
+representation indicates the indices to extract, from left to right 1, 2, 4, 8, 
+etc.).
+
+
+  ***   at top-level: fact()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: fact(x) ===> factorial(x)
+
+factorial(x): factorial of x, the result being given as a real number.
+
+
+  ***   at top-level: factcantor()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: factcantor(x,p) ===> factorcantor(x,p)
+
+factorcantor(x,p): factorization mod p of the polynomial x using 
+Cantor-Zassenhaus.
+
+
+  ***   at top-level: factfq()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: factfq(x,p,a) ===> factorff(x,p,a)
+
+factorff(x,{p},{a}): factorization of the polynomial x in the finite field 
+F_p[X]/a(X)F_p[X].
+
+
+  ***   at top-level: factmod()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: factmod(x,p) ===> factormod(x,p)
+
+factormod(x,p,{flag=0}): factors the polynomial x modulo the prime p, using 
+Berlekamp. flag is optional, and can be 0: default or 1: only the degrees of 
+the irreducible factors are given.
+
+
+  ***   at top-level: factoredbasis()
+  ***                 ^---------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: factoredbasis(x,p) ===> nfbasis(x,,p)
+
+nfbasis(T): integral basis of the field Q[a], where a is a root of the 
+polynomial T, using the round 4 algorithm. An argument [T,listP] is possible, 
+where listP is a list of primes (to get an order which is maximal at certain 
+primes only) or a prime bound.
+
+
+  ***   at top-level: factoreddiscf()
+  ***                 ^---------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: factoreddiscf(x,p) ===> nfdisc(x,,p)
+
+nfdisc(T): discriminant of the number field defined by the polynomial T. An 
+argument [T,listP] is possible, where listP is a list of primes or a prime 
+bound.
+
+
+  ***   at top-level: factoredpolred()
+  ***                 ^----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: factoredpolred(x,p) ===> polred(x,,p)
+
+polred(T,{flag=0}): Deprecated, use polredbest. Reduction of the polynomial T 
+(gives minimal polynomials only). The following binary digits of (optional) 
+flag are significant 1: partial reduction, 2: gives also elements.
+
+
+  ***   at top-level: factoredpolred2()
+  ***                 ^-----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: factoredpolred2(x,p) ===> polred(x,2,p)
+
+polred(T,{flag=0}): Deprecated, use polredbest. Reduction of the polynomial T 
+(gives minimal polynomials only). The following binary digits of (optional) 
+flag are significant 1: partial reduction, 2: gives also elements.
+
+
+  ***   at top-level: factorpadic2()
+  ***                 ^--------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: factorpadic2(x,p,r) ===> factorpadic(x,p,r,1)
+
+factorpadic(pol,p,r): p-adic factorization of the polynomial pol to precision 
+r.
+
+
+  ***   at top-level: factpol()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: factpol(x,l,hint) ===> factor(x)
+
+factor(x,{lim}): factorization of x. lim is optional and can be set whenever x 
+is of (possibly recursive) rational type. If lim is set return partial 
+factorization, using primes < lim.
+
+
+  ***   at top-level: factpol2()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: factpol2(x,l,hint) ===> factor(x)
+
+factor(x,{lim}): factorization of x. lim is optional and can be set whenever x 
+is of (possibly recursive) rational type. If lim is set return partial 
+factorization, using primes < lim.
+
+
+  ***   at top-level: fibo()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: fibo(x) ===> fibonacci(x)
+
+fibonacci(x): fibonacci number of index x (x C-integer).
+
+
+  ***   at top-level: fpn()
+  ***                 ^-----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: fpn(p,n) ===> ffinit(p,n)
+
+ffinit(p,n,{v='x}): monic irreducible polynomial of degree n over F_p[v].
+
+
+  ***   at top-level: galois()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: galois(x) ===> polgalois(x)
+
+polgalois(T): Galois group of the polynomial T (see manual for group coding). 
+Return [n, s, k, name] where n is the group order, s the signature, k the index 
+and name is the GAP4 name of the transitive group.
+
+
+  ***   at top-level: galoisapply()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: galoisapply(nf,aut,x) ===> nfgaloisapply(nf,aut,x)
+
+nfgaloisapply(nf,aut,x): Apply the Galois automorphism aut to the object x 
+(element or ideal) in the number field nf.
+
+
+  ***   at top-level: galoisconj()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: galoisconj(nf) ===> nfgaloisconj(nf)
+
+nfgaloisconj(nf,{flag=0},{d}): list of conjugates of a root of the polynomial 
+x=nf.pol in the same number field. flag is optional (set to 0 by default), 
+meaning 0: use combination of flag 4 and 1, always complete; 1: use nfroots; 2 
+: use complex numbers, LLL on integral basis (not always complete); 4: use 
+Allombert's algorithm, complete if the field is Galois of degree <= 35 (see 
+manual for details). nf can be simply a polynomial.
+
+
+  ***   at top-level: galoisconj1()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: galoisconj1(nf) ===> nfgaloisconj(nf,2)
+
+nfgaloisconj(nf,{flag=0},{d}): list of conjugates of a root of the polynomial 
+x=nf.pol in the same number field. flag is optional (set to 0 by default), 
+meaning 0: use combination of flag 4 and 1, always complete; 1: use nfroots; 2 
+: use complex numbers, LLL on integral basis (not always complete); 4: use 
+Allombert's algorithm, complete if the field is Galois of degree <= 35 (see 
+manual for details). nf can be simply a polynomial.
+
+
+  ***   at top-level: galoisconjforce()
+  ***                 ^-----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: galoisconjforce ===> nfgaloisconj(nf,1)
+
+nfgaloisconj(nf,{flag=0},{d}): list of conjugates of a root of the polynomial 
+x=nf.pol in the same number field. flag is optional (set to 0 by default), 
+meaning 0: use combination of flag 4 and 1, always complete; 1: use nfroots; 2 
+: use complex numbers, LLL on integral basis (not always complete); 4: use 
+Allombert's algorithm, complete if the field is Galois of degree <= 35 (see 
+manual for details). nf can be simply a polynomial.
+
+
+  ***   at top-level: gamh()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: gamh(x) ===> gammah(x)
+
+gammah(x): gamma of x+1/2 (x integer).
+
+
+  ***   at top-level: gauss()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: gauss(a,b) ===> matsolve(a,b)
+
+matsolve(M,B): solution of MX=B (M matrix, B column vector).
+
+
+  ***   at top-level: gaussmodulo()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: gaussmodulo(M,D,Y) ===> matsolvemod(M,D,Y)
+
+matsolvemod(M,D,B,{flag=0}): one solution of system of congruences MX=B mod D 
+(M matrix, B and D column vectors). If (optional) flag is non-null return all 
+solutions.
+
+
+  ***   at top-level: gaussmodulo2()
+  ***                 ^--------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: gaussmodulo2(M,D,Y) ===> matsolvemod(M,D,Y,1)
+
+matsolvemod(M,D,B,{flag=0}): one solution of system of congruences MX=B mod D 
+(M matrix, B and D column vectors). If (optional) flag is non-null return all 
+solutions.
+
+
+  ***   at top-level: globalred()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: globalred(x,y) ===> ellglobalred(x,y)
+
+ellglobalred(E): E being an elliptic curve, returns [N,[u,r,s,t],c, faN,L], 
+where N is the conductor of E, [u,r,s,t] leads to the standard model for E, c 
+is the product of the local Tamagawa numbers c_p, faN is factor(N) and L[i] is 
+elllocalred(E, faN[i,1]).
+
+
+  ***   at top-level: goto()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+This function no longer exists
+
+
+  ***   at top-level: hclassno()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: hclassno(x) ===> qfbhclassno(x)
+
+qfbhclassno(x): Hurwitz-Kronecker class number of x>0.
+
+
+  ***   at top-level: hell()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: hell(e,x) ===> ellheight(e,x)
+
+ellheight(E,P,{Q}): canonical height of point P on elliptic curve E, resp. the 
+value of the associated bilinear form at (P,Q).
+
+
+  ***   at top-level: hell2()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: hell2(e,x) ===> ellheight(e,x,1)
+
+ellheight(E,P,{Q}): canonical height of point P on elliptic curve E, resp. the 
+value of the associated bilinear form at (P,Q).
+
+
+  ***   at top-level: hermite()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: hermite(x) ===> mathnf(x)
+
+mathnf(M,{flag=0}): (upper triangular) Hermite normal form of M, basis for the 
+lattice formed by the columns of M. flag is optional whose value range from 0 
+to 3 have a binary meaning. Bit 1: complete output, returns a 2-component 
+vector [H,U] such that H is the HNF of M, and U is an invertible matrix such 
+that MU=H. Bit 2: allow polynomial entries, otherwise assume that M is 
+integral. These use a naive algorithm; larger values correspond to more 
+involved algorithms and are restricted to integer matrices; flag = 4: returns 
+[H,U] using LLL reduction along the way; flag = 5: return [H,U,P] where P is a 
+permutation of row indices such that P applied to M U is H.
+
+
+  ***   at top-level: hermite2()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: hermite2(x) ===> mathnf(x,1)
+
+mathnf(M,{flag=0}): (upper triangular) Hermite normal form of M, basis for the 
+lattice formed by the columns of M. flag is optional whose value range from 0 
+to 3 have a binary meaning. Bit 1: complete output, returns a 2-component 
+vector [H,U] such that H is the HNF of M, and U is an invertible matrix such 
+that MU=H. Bit 2: allow polynomial entries, otherwise assume that M is 
+integral. These use a naive algorithm; larger values correspond to more 
+involved algorithms and are restricted to integer matrices; flag = 4: returns 
+[H,U] using LLL reduction along the way; flag = 5: return [H,U,P] where P is a 
+permutation of row indices such that P applied to M U is H.
+
+
+  ***   at top-level: hermitehavas()
+  ***                 ^--------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+This function no longer exists
+
+
+  ***   at top-level: hermitemod()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: hermitemod(x,d) ===> mathnfmod(x,d)
+
+mathnfmod(x,d): (upper triangular) Hermite normal form of x, basis for the 
+lattice formed by the columns of x, where d is a multiple of the non-zero 
+determinant of this lattice.
+
+
+  ***   at top-level: hermitemodid()
+  ***                 ^--------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: hermitemodid(x,d) ===> mathnfmodid(x,d)
+
+mathnfmodid(x,d): (upper triangular) Hermite normal form of x concatenated with 
+matdiagonal(d)
+
+
+  ***   at top-level: hermiteperm()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: hermiteperm(x) ===> mathnf(x,3)
+
+mathnf(M,{flag=0}): (upper triangular) Hermite normal form of M, basis for the 
+lattice formed by the columns of M. flag is optional whose value range from 0 
+to 3 have a binary meaning. Bit 1: complete output, returns a 2-component 
+vector [H,U] such that H is the HNF of M, and U is an invertible matrix such 
+that MU=H. Bit 2: allow polynomial entries, otherwise assume that M is 
+integral. These use a naive algorithm; larger values correspond to more 
+involved algorithms and are restricted to integer matrices; flag = 4: returns 
+[H,U] using LLL reduction along the way; flag = 5: return [H,U,P] where P is a 
+permutation of row indices such that P applied to M U is H.
+
+
+  ***   at top-level: hess()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: hess(x) ===> mathess(x)
+
+mathess(x): Hessenberg form of x.
+
+
+  ***   at top-level: hilb()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: hilb(x,y) ===> hilbert(x,y)
+
+hilbert(x,y,{p}): Hilbert symbol at p of x,y.
+
+
+  ***   at top-level: hilbp()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: hilbp(x,y,p) ===> hilbert(x,y,p)
+
+hilbert(x,y,{p}): Hilbert symbol at p of x,y.
+
+
+  ***   at top-level: hvector()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: hvector(n,X,expr) ===> vector(n,X,expr)
+
+vector(n,{X},{expr=0}): row vector with n components of expression expr (X 
+ranges from 1 to n). By default, fill with 0s.
+
+
+  ***   at top-level: i()
+  ***                 ^---
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: i ===> I
+
+I=I(): square root of -1.
+
+
+  ***   at top-level: idealaddmultone()
+  ***                 ^-----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: idealaddmultone(nf,list) ===> idealaddtoone(nf,list)
+
+idealaddtoone(nf,x,{y}): if y is omitted, when the sum of the ideals in the 
+number field K defined by nf and given in the vector x is equal to Z_K, gives a 
+vector of elements of the corresponding ideals who sum to 1. Otherwise, x and y 
+are ideals, and if they sum up to 1, find one element in each of them such that 
+the sum is 1.
+
+
+  ***   at top-level: idealaddone()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: idealaddone(nf,x,y) ===> idealaddtoone(nf,x,y)
+
+idealaddtoone(nf,x,{y}): if y is omitted, when the sum of the ideals in the 
+number field K defined by nf and given in the vector x is equal to Z_K, gives a 
+vector of elements of the corresponding ideals who sum to 1. Otherwise, x and y 
+are ideals, and if they sum up to 1, find one element in each of them such that 
+the sum is 1.
+
+
+  ***   at top-level: idealapprfact()
+  ***                 ^---------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: idealapprfact(nf,x) ===> idealappr(nf,x,1)
+
+idealappr(nf,x,{flag=0}): x being a fractional ideal, gives an element b such 
+that v_p(b)=v_p(x) for all prime ideals p dividing x, and v_p(b)>=0 for all 
+other p. If (optional) flag is non-null x must be a prime ideal factorization 
+with possibly zero exponents.
+
+
+  ***   at top-level: idealdivexact()
+  ***                 ^---------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: idealdivexact(nf,x,y) ===> idealdiv(nf,x,y,1)
+
+idealdiv(nf,x,y,{flag=0}): quotient x/y of two ideals x and y in HNF in the 
+number field nf. If (optional) flag is non-null, the quotient is supposed to be 
+an integral ideal (slightly faster).
+
+
+  ***   at top-level: idealhermite()
+  ***                 ^--------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: idealhermite(nf,x) ===> idealhnf(nf,x)
+
+idealhnf(nf,u,{v}): hermite normal form of the ideal u in the number field nf 
+if v is omitted. If called as idealhnf(nf,u,v), the ideal is given as uZ_K + 
+vZ_K in the number field K defined by nf.
+
+
+  ***   at top-level: idealhermite2()
+  ***                 ^---------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: idealhermite2(nf,x) ===> idealhnf(nf,x)
+
+idealhnf(nf,u,{v}): hermite normal form of the ideal u in the number field nf 
+if v is omitted. If called as idealhnf(nf,u,v), the ideal is given as uZ_K + 
+vZ_K in the number field K defined by nf.
+
+
+  ***   at top-level: idealinv2()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: idealinv2(nf,x) ===> idealinv(nf,x,1)
+
+idealinv(nf,x): inverse of the ideal x in the number field nf.
+
+
+  ***   at top-level: ideallistarchgen()
+  ***                 ^------------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: ideallistarchgen(nf,list,arch) ===> ideallistarch(nf,list,arch)
+
+ideallistarch(nf,list,arch): list is a vector of vectors of of bid's as output 
+by ideallist. Return a vector of vectors with the same number of components as 
+the original list. The leaves give information about moduli whose finite part 
+is as in original list, in the same order, and Archimedean part is now arch. 
+The information contained is of the same kind as was present in the input.
+
+
+  ***   at top-level: ideallistunit()
+  ***                 ^---------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: ideallistunit(nf,list) ===> ideallist(nf,list,2)
+
+ideallist(nf,bound,{flag=4}): vector of vectors L of all idealstar of all 
+ideals of norm<=bound. If (optional) flag is present, its binary digits are 
+toggles meaning 1: give generators; 2: add units; 4: give only the ideals and 
+not the bid.
+
+
+  ***   at top-level: ideallistunitarch()
+  ***                 ^-------------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: ideallistunitarch ===> ideallistarch(nf,list,arch)
+
+ideallistarch(nf,list,arch): list is a vector of vectors of of bid's as output 
+by ideallist. Return a vector of vectors with the same number of components as 
+the original list. The leaves give information about moduli whose finite part 
+is as in original list, in the same order, and Archimedean part is now arch. 
+The information contained is of the same kind as was present in the input.
+
+
+  ***   at top-level: ideallistunitarchgen
+  ***                 ^--------------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: ideallistunitarchgen ===> ideallistarch(nf,list,arch)
+
+ideallistarch(nf,list,arch): list is a vector of vectors of of bid's as output 
+by ideallist. Return a vector of vectors with the same number of components as 
+the original list. The leaves give information about moduli whose finite part 
+is as in original list, in the same order, and Archimedean part is now arch. 
+The information contained is of the same kind as was present in the input.
+
+
+  ***   at top-level: ideallistunitgen()
+  ***                 ^------------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: ideallistunitgen ===> ideallist(nf,list,3)
+
+ideallist(nf,bound,{flag=4}): vector of vectors L of all idealstar of all 
+ideals of norm<=bound. If (optional) flag is present, its binary digits are 
+toggles meaning 1: give generators; 2: add units; 4: give only the ideals and 
+not the bid.
+
+
+  ***   at top-level: ideallistzstar()
+  ***                 ^----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: ideallistzstar(nf,bound) ===> ideallist(nf,bound)
+
+ideallist(nf,bound,{flag=4}): vector of vectors L of all idealstar of all 
+ideals of norm<=bound. If (optional) flag is present, its binary digits are 
+toggles meaning 1: give generators; 2: add units; 4: give only the ideals and 
+not the bid.
+
+
+  ***   at top-level: ideallistzstargen()
+  ***                 ^-------------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: ideallistzstargen(nf,bound) ===> ideallist(nf,bound,1)
+
+ideallist(nf,bound,{flag=4}): vector of vectors L of all idealstar of all 
+ideals of norm<=bound. If (optional) flag is present, its binary digits are 
+toggles meaning 1: give generators; 2: add units; 4: give only the ideals and 
+not the bid.
+
+
+  ***   at top-level: ideallllred()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: ideallllred(nf,x,vdir) ===> idealred(nf,x,vdir)
+
+idealred(nf,I,{v=0}): LLL reduction of the ideal I in the number field nf along 
+direction v, in HNF.
+
+
+  ***   at top-level: idealmulred()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: idealmulred(nf,x,y) ===> idealmul(nf,x,y,1)
+
+idealmul(nf,x,y,{flag=0}): product of the two ideals x and y in the number 
+field nf. If (optional) flag is non-nul, reduce the result.
+
+
+  ***   at top-level: idealpowred()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: idealpowred(nf,x,y) ===> idealpow(nf,x,y,1)
+
+idealpow(nf,x,k,{flag=0}): k-th power of the ideal x in HNF in the number field 
+nf. If (optional) flag is non-null, reduce the result.
+
+
+  ***   at top-level: idealtwoelt2()
+  ***                 ^--------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: idealtwoelt2(nf,x,a) ===> idealtwoelt(nf,x,a)
+
+idealtwoelt(nf,x,{a}): two-element representation of an ideal x in the number 
+field nf. If (optional) a is non-zero, first element will be equal to a.
+
+
+  ***   at top-level: idmat()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: idmat(n) ===> matid(n)
+
+matid(n): identity matrix of order n.
+
+
+  ***   at top-level: image()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: image(x) ===> matimage(x)
+
+matimage(x,{flag=0}): basis of the image of the matrix x. flag is optional and 
+can be set to 0 or 1, corresponding to two different algorithms.
+
+
+  ***   at top-level: image2()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: image2(x) ===> matimage(x,1)
+
+matimage(x,{flag=0}): basis of the image of the matrix x. flag is optional and 
+can be set to 0 or 1, corresponding to two different algorithms.
+
+
+  ***   at top-level: imagecompl()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: imagecompl(x) ===> matimagecompl(x)
+
+matimagecompl(x): vector of column indices not corresponding to the indices 
+given by the function matimage.
+
+
+  ***   at top-level: incgam1()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+This function no longer exists
+
+
+  ***   at top-level: incgam2()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+This function no longer exists
+
+
+  ***   at top-level: incgam3()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+This function no longer exists
+
+
+  ***   at top-level: incgam4()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: incgam4(s,x,y) ===> incgam(s,x,y)
+
+incgam(s,x,{g}): incomplete gamma function. g is optional and is the 
+precomputed value of gamma(s).
+
+
+  ***   at top-level: indexrank()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: indexrank(x) ===> matindexrank(x)
+
+matindexrank(x): gives two extraction vectors (rows and columns) for the matrix 
+x such that the extracted matrix is square of maximal rank.
+
+
+  ***   at top-level: indsort()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: indsort(x) ===> vecsort(x,,1)
+
+vecsort(x,{cmpf},{flag=0}): sorts the vector of vectors (or matrix) x in 
+ascending order, according to the comparison function cmpf, if not omitted. (If 
+cmpf is an integer, sort according to the value of the k-th component of each 
+entry.) Binary digits of flag (if present) mean: 1: indirect sorting, return 
+the permutation instead of the permuted vector, 2: sort using lexicographic 
+order, 4: use descending instead of ascending order, 8: remove duplicate 
+entries.
+
+
+  ***   at top-level: initalg()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: initalg(pol) ===> nfinit(pol)
+
+nfinit(pol,{flag=0}): pol being a nonconstant irreducible polynomial, gives the 
+vector: [pol,[r1,r2],discf,index,[M,MC,T2,T,different] (see manual),r1+r2 first 
+roots, integral basis, matrix of power basis in terms of integral basis, 
+multiplication table of basis]. flag is optional and can be set to 0: default; 
+1: do not compute different; 2: first use polred to find a simpler polynomial; 
+3: outputs a two-element vector [nf,Mod(a,P)], where nf is as in 2 and Mod(a,P) 
+is a polmod equal to Mod(x,pol) and P=nf.pol.
+
+
+  ***   at top-level: initalgred()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: initalgred(x) ===> nfinit(x,2)
+
+nfinit(pol,{flag=0}): pol being a nonconstant irreducible polynomial, gives the 
+vector: [pol,[r1,r2],discf,index,[M,MC,T2,T,different] (see manual),r1+r2 first 
+roots, integral basis, matrix of power basis in terms of integral basis, 
+multiplication table of basis]. flag is optional and can be set to 0: default; 
+1: do not compute different; 2: first use polred to find a simpler polynomial; 
+3: outputs a two-element vector [nf,Mod(a,P)], where nf is as in 2 and Mod(a,P) 
+is a polmod equal to Mod(x,pol) and P=nf.pol.
+
+
+  ***   at top-level: initalgred2()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: initalgred2(x) ===> nfinit(x,3)
+
+nfinit(pol,{flag=0}): pol being a nonconstant irreducible polynomial, gives the 
+vector: [pol,[r1,r2],discf,index,[M,MC,T2,T,different] (see manual),r1+r2 first 
+roots, integral basis, matrix of power basis in terms of integral basis, 
+multiplication table of basis]. flag is optional and can be set to 0: default; 
+1: do not compute different; 2: first use polred to find a simpler polynomial; 
+3: outputs a two-element vector [nf,Mod(a,P)], where nf is as in 2 and Mod(a,P) 
+is a polmod equal to Mod(x,pol) and P=nf.pol.
+
+
+  ***   at top-level: initell()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: initell(x) ===> ellinit(x)
+
+ellinit(x,{D=1}): let x be a vector [a1,a2,a3,a4,a6], or [a4,a6] if a1=a2=a3=0, 
+defining the curve Y^2 + a1.XY + a3.Y = X^3 + a2.X^2 + a4.X + a6; x can also be 
+a string, in which case the curve with matching name is retrieved from the 
+elldata database, if available. This function initializes an elliptic curve 
+over the domain D (inferred from coefficients if omitted).
+
+
+  ***   at top-level: initzeta()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: initzeta(x) ===> zetakinit(x)
+
+zetakinit(bnf): compute number field information necessary to use zetak. bnf 
+may also be an irreducible polynomial.
+
+
+  ***   at top-level: integ()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: integ(x,y) ===> intformal(x,y)
+
+intformal(x,{v}): formal integration of x with respect to v, or to the main 
+variable of x if v is omitted.
+
+
+  ***   at top-level: intersect()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: intersect(x,y) ===> matintersect(x,y)
+
+matintersect(x,y): intersection of the vector spaces whose bases are the 
+columns of x and y.
+
+
+  ***   at top-level: intgen()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: intgen(x=a,b,s) ===> intnum(x=a,b,s,1)
+
+intnum(X=a,b,expr,{tab}): numerical integration of expr from a to b with 
+respect to X. Plus/minus infinity is coded as +oo/-oo. Finally tab is either 
+omitted (let the program choose the integration step), a positive integer m 
+(choose integration step 1/2^m), or data precomputed with intnuminit.
+
+
+  ***   at top-level: intinf()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: intinf(x=a,b,s) ===> intnum(x=a,b,s,2)
+
+intnum(X=a,b,expr,{tab}): numerical integration of expr from a to b with 
+respect to X. Plus/minus infinity is coded as +oo/-oo. Finally tab is either 
+omitted (let the program choose the integration step), a positive integer m 
+(choose integration step 1/2^m), or data precomputed with intnuminit.
+
+
+  ***   at top-level: intopen()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: intopen(x=a,b,s) ===> intnum(x=a,b,s,3)
+
+intnum(X=a,b,expr,{tab}): numerical integration of expr from a to b with 
+respect to X. Plus/minus infinity is coded as +oo/-oo. Finally tab is either 
+omitted (let the program choose the integration step), a positive integer m 
+(choose integration step 1/2^m), or data precomputed with intnuminit.
+
+
+  ***   at top-level: inverseimage()
+  ***                 ^--------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: inverseimage(x,y) ===> matinverseimage(x,y)
+
+matinverseimage(x,y): an element of the inverse image of the vector y by the 
+matrix x if one exists, the empty vector otherwise.
+
+
+  ***   at top-level: isdiagonal()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: isdiagonal(x) ===> matisdiagonal(x)
+
+matisdiagonal(x): true(1) if x is a diagonal matrix, false(0) otherwise.
+
+
+  ***   at top-level: isfund()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: isfund(x) ===> isfundamental(x)
+
+isfundamental(x): true(1) if x is a fundamental discriminant (including 1), 
+false(0) if not.
+
+
+  ***   at top-level: isideal()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: isideal(nf,x) ===> nfisideal(nf,x)
+
+nfisideal(nf,x): true(1) if x is an ideal in the number field nf, false(0) if 
+not.
+
+
+  ***   at top-level: isincl()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: isincl(x,y) ===> nfisincl(x,y)
+
+nfisincl(x,y): tests whether the number field x is isomorphic to a subfield of 
+y (where x and y are either polynomials or number fields as output by nfinit). 
+Return 0 if not, and otherwise all the isomorphisms. If y is a number field, a 
+faster algorithm is used.
+
+
+  ***   at top-level: isinclfast()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: isinclfast(nf1,nf2) ===> nfisincl(nf1,nf2,1)
+
+nfisincl(x,y): tests whether the number field x is isomorphic to a subfield of 
+y (where x and y are either polynomials or number fields as output by nfinit). 
+Return 0 if not, and otherwise all the isomorphisms. If y is a number field, a 
+faster algorithm is used.
+
+
+  ***   at top-level: isirreducible()
+  ***                 ^---------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: isirreducible(x) ===> polisirreducible(x)
+
+polisirreducible(pol): true(1) if pol is an irreducible non-constant 
+polynomial, false(0) if pol is reducible or constant.
+
+
+  ***   at top-level: isisom()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: isisom(x,y) ===> nfisisom(x,y)
+
+nfisisom(x,y): as nfisincl but tests whether x is isomorphic to y.
+
+
+  ***   at top-level: isisomfast()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: isisomfast(x,y) ===> nfisisom(x,y)
+
+nfisisom(x,y): as nfisincl but tests whether x is isomorphic to y.
+
+
+  ***   at top-level: isoncurve()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: isoncurve(e,x) ===> ellisoncurve(e,x)
+
+ellisoncurve(E,z): true(1) if z is on elliptic curve E, false(0) if not.
+
+
+  ***   at top-level: isprincipal()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: isprincipal(bnf,x) ===> bnfisprincipal(bnf,x,0)
+
+bnfisprincipal(bnf,x,{flag=1}): bnf being output by bnfinit (with flag<=2), 
+gives [v,alpha], where v is the vector of exponents on the class group 
+generators and alpha is the generator of the resulting principal ideal. In 
+particular x is principal if and only if v is the zero vector. flag is 
+optional, whose binary digits mean 1: output [v,alpha] (only v if unset); 2: 
+increase precision until alpha can be computed (do not insist if unset).
+
+
+  ***   at top-level: isprincipalforce()
+  ***                 ^------------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: isprincipalforce(bnf,x) ===> bnfisprincipal(bnf,x,2)
+
+bnfisprincipal(bnf,x,{flag=1}): bnf being output by bnfinit (with flag<=2), 
+gives [v,alpha], where v is the vector of exponents on the class group 
+generators and alpha is the generator of the resulting principal ideal. In 
+particular x is principal if and only if v is the zero vector. flag is 
+optional, whose binary digits mean 1: output [v,alpha] (only v if unset); 2: 
+increase precision until alpha can be computed (do not insist if unset).
+
+
+  ***   at top-level: isprincipalgen()
+  ***                 ^----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: isprincipalgen(bnf,x) ===> bnfisprincipal(bnf,x)
+
+bnfisprincipal(bnf,x,{flag=1}): bnf being output by bnfinit (with flag<=2), 
+gives [v,alpha], where v is the vector of exponents on the class group 
+generators and alpha is the generator of the resulting principal ideal. In 
+particular x is principal if and only if v is the zero vector. flag is 
+optional, whose binary digits mean 1: output [v,alpha] (only v if unset); 2: 
+increase precision until alpha can be computed (do not insist if unset).
+
+
+  ***   at top-level: isprincipalgenforce(
+  ***                 ^--------------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: isprincipalgenforce(bnf,x) ===> bnfisprincipal(bnf,x,3)
+
+bnfisprincipal(bnf,x,{flag=1}): bnf being output by bnfinit (with flag<=2), 
+gives [v,alpha], where v is the vector of exponents on the class group 
+generators and alpha is the generator of the resulting principal ideal. In 
+particular x is principal if and only if v is the zero vector. flag is 
+optional, whose binary digits mean 1: output [v,alpha] (only v if unset); 2: 
+increase precision until alpha can be computed (do not insist if unset).
+
+
+  ***   at top-level: isprincipalray()
+  ***                 ^----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: isprincipalray(bnf,x) ===> bnrisprincipal(bnf,x)
+
+bnrisprincipal(bnr,x,{flag=1}): bnr being output by bnrinit, gives [v,alpha], 
+where v is the vector of exponents on the class group generators and alpha is 
+the generator of the resulting principal ideal. In particular x is principal if 
+and only if v is the zero vector. If (optional) flag is set to 0, output only 
+v.
+
+
+  ***   at top-level: isprincipalraygen()
+  ***                 ^-------------------
+  ***   not a function in function call
+  ***   at top-level: ispsp()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: ispsp(x) ===> ispseudoprime(x)
+
+ispseudoprime(x,{flag}): true(1) if x is a strong pseudoprime, false(0) if not. 
+If flag is 0 or omitted, use BPSW test, otherwise use strong Rabin-Miller test 
+for flag randomly chosen bases.
+
+
+  ***   at top-level: isqrt()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: isqrt(x) ===> sqrtint(x)
+
+sqrtint(x): integer square root of x, where x is a non-negative integer.
+
+
+  ***   at top-level: isset()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: isset(x) ===> setisset(x)
+
+setisset(x): true(1) if x is a set (row vector with strictly increasing 
+entries), false(0) if not.
+
+
+  ***   at top-level: issqfree()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: issqfree(x) ===> issquarefree(x)
+
+issquarefree(x): true(1) if x is squarefree, false(0) if not.
+
+
+  ***   at top-level: isunit()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: isunit(bnf,x) ===> bnfisunit(bnf,x)
+
+bnfisunit(bnf,x): bnf being output by bnfinit, gives the column vector of 
+exponents of x on the fundamental units and the roots of unity if x is a unit, 
+the empty vector otherwise.
+
+
+  ***   at top-level: jacobi()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: jacobi(x) ===> qfjacobi(x)
+
+qfjacobi(A): eigenvalues and orthogonal matrix of eigenvectors of the real 
+symmetric matrix A.
+
+
+  ***   at top-level: jbesselh()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: jbesselh(n,x) ===> besseljh(n,x)
+
+besseljh(n,x): J-bessel function of index n+1/2 and argument x, where n is a 
+non-negative integer.
+
+
+  ***   at top-level: jell()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: jell(x) ===> ellj(x)
+
+ellj(x): elliptic j invariant of x.
+
+
+  ***   at top-level: karamul()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+This function no longer exists
+
+
+  ***   at top-level: kbessel()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: kbessel(nu,x) ===> besselk(nu,x)
+
+besselk(nu,x): K-bessel function of index nu and argument x.
+
+
+  ***   at top-level: kbessel2()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: kbessel2(nu,x) ===> besselk(nu,x)
+
+besselk(nu,x): K-bessel function of index nu and argument x.
+
+
+  ***   at top-level: ker()
+  ***                 ^-----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: ker(x) ===> matker(x)
+
+matker(x,{flag=0}): basis of the kernel of the matrix x. flag is optional, and 
+may be set to 0: default; non-zero: x is known to have integral entries.
+
+
+  ***   at top-level: keri()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: keri(x) ===> matker(x,1)
+
+matker(x,{flag=0}): basis of the kernel of the matrix x. flag is optional, and 
+may be set to 0: default; non-zero: x is known to have integral entries.
+
+
+  ***   at top-level: kerint()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: kerint(x) ===> matkerint(x)
+
+matkerint(x,{flag=0}): LLL-reduced Z-basis of the kernel of the matrix x with 
+integral entries. flag is deprecated, and may be set to 0 or 1 for backward 
+compatibility.
+
+
+  ***   at top-level: kerint1()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: kerint1(x) ===> matkerint(x,1)
+
+matkerint(x,{flag=0}): LLL-reduced Z-basis of the kernel of the matrix x with 
+integral entries. flag is deprecated, and may be set to 0 or 1 for backward 
+compatibility.
+
+
+  ***   at top-level: kerint2()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+This function no longer exists
+
+
+  ***   at top-level: kro()
+  ***                 ^-----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: kro(x,y) ===> kronecker(x,y)
+
+kronecker(x,y): kronecker symbol (x/y).
+
+
+  ***   at top-level: label()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+This function no longer exists
+
+
+  ***   at top-level: lambdak()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: lambdak(nfz,s) ===> zetak(nfz,s,1)
+
+zetak(nfz,x,{flag=0}): Dedekind zeta function of the number field nfz at x, 
+where nfz is the vector computed by zetakinit (NOT by nfinit); flag is 
+optional, and can be 0: default, compute zetak, or non-zero: compute the 
+lambdak function, i.e. with the gamma factors.
+
+
+  ***   at top-level: laplace()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: laplace(x) ===> serlaplace(x)
+
+serlaplace(x): replaces the power series sum of a_n*x^n/n! by sum of a_n*x^n. 
+For the reverse operation, use serconvol(x,exp(X)).
+
+
+  ***   at top-level: legendre()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: legendre(n) ===> pollegendre(n)
+
+pollegendre(n,{a='x}): legendre polynomial of degree n evaluated at a.
+
+
+  ***   at top-level: lexsort()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: lexsort(x) ===> vecsort(x,,2)
+
+vecsort(x,{cmpf},{flag=0}): sorts the vector of vectors (or matrix) x in 
+ascending order, according to the comparison function cmpf, if not omitted. (If 
+cmpf is an integer, sort according to the value of the k-th component of each 
+entry.) Binary digits of flag (if present) mean: 1: indirect sorting, return 
+the permutation instead of the permuted vector, 2: sort using lexicographic 
+order, 4: use descending instead of ascending order, 8: remove duplicate 
+entries.
+
+
+  ***   at top-level: lindep2()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: lindep2(x) ===> lindep(x,1)
+
+lindep(v,{flag=0}): integral linear dependencies between components of v. flag 
+is optional, and can be 0: default, guess a suitable accuracy, or positive: 
+accuracy to use for the computation, in decimal digits.
+
+
+  ***   at top-level: lll()
+  ***                 ^-----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: lll(x) ===> qflll(x)
+
+qflll(x,{flag=0}): LLL reduction of the vectors forming the matrix x (gives the 
+unimodular transformation matrix T such that x*T is LLL-reduced). flag is 
+optional, and can be 0: default, 1: assumes x is integral, 2: assumes x is 
+integral, returns a partially reduced basis, 4: assumes x is integral, returns 
+[K,T] where K is the integer kernel of x and T the LLL reduced image, 5: same 
+as 4 but x may have polynomial coefficients, 8: same as 0 but x may have 
+polynomial coefficients.
+
+
+  ***   at top-level: lll1()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+This function no longer exists
+
+
+  ***   at top-level: lllgen()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: lllgen(x) ===> qflll(x,8)
+
+qflll(x,{flag=0}): LLL reduction of the vectors forming the matrix x (gives the 
+unimodular transformation matrix T such that x*T is LLL-reduced). flag is 
+optional, and can be 0: default, 1: assumes x is integral, 2: assumes x is 
+integral, returns a partially reduced basis, 4: assumes x is integral, returns 
+[K,T] where K is the integer kernel of x and T the LLL reduced image, 5: same 
+as 4 but x may have polynomial coefficients, 8: same as 0 but x may have 
+polynomial coefficients.
+
+
+  ***   at top-level: lllgram()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: lllgram(x) ===> qflllgram(x)
+
+qflllgram(G,{flag=0}): LLL reduction of the lattice whose gram matrix is G 
+(gives the unimodular transformation matrix). flag is optional and can be 0: 
+default,1: assumes x is integral, 4: assumes x is integral, returns [K,T], 
+where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 
+but x may have polynomial coefficients, 8: same as 0 but x may have polynomial 
+coefficients.
+
+
+  ***   at top-level: lllgram1()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+This function no longer exists
+
+
+  ***   at top-level: lllgramgen()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: lllgramgen(x) ===> qflllgram(x,8)
+
+qflllgram(G,{flag=0}): LLL reduction of the lattice whose gram matrix is G 
+(gives the unimodular transformation matrix). flag is optional and can be 0: 
+default,1: assumes x is integral, 4: assumes x is integral, returns [K,T], 
+where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 
+but x may have polynomial coefficients, 8: same as 0 but x may have polynomial 
+coefficients.
+
+
+  ***   at top-level: lllgramint()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: lllgramint(x) ===> qflllgram(x,1)
+
+qflllgram(G,{flag=0}): LLL reduction of the lattice whose gram matrix is G 
+(gives the unimodular transformation matrix). flag is optional and can be 0: 
+default,1: assumes x is integral, 4: assumes x is integral, returns [K,T], 
+where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 
+but x may have polynomial coefficients, 8: same as 0 but x may have polynomial 
+coefficients.
+
+
+  ***   at top-level: lllgramkerim()
+  ***                 ^--------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: lllgramkerim(x) ===> qflllgram(x,4)
+
+qflllgram(G,{flag=0}): LLL reduction of the lattice whose gram matrix is G 
+(gives the unimodular transformation matrix). flag is optional and can be 0: 
+default,1: assumes x is integral, 4: assumes x is integral, returns [K,T], 
+where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 
+but x may have polynomial coefficients, 8: same as 0 but x may have polynomial 
+coefficients.
+
+
+  ***   at top-level: lllgramkerimgen()
+  ***                 ^-----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: lllgramkerimgen(x) ===> qflllgram(x,5)
+
+qflllgram(G,{flag=0}): LLL reduction of the lattice whose gram matrix is G 
+(gives the unimodular transformation matrix). flag is optional and can be 0: 
+default,1: assumes x is integral, 4: assumes x is integral, returns [K,T], 
+where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 
+but x may have polynomial coefficients, 8: same as 0 but x may have polynomial 
+coefficients.
+
+
+  ***   at top-level: lllint()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: lllint(x) ===> qflll(x,1)
+
+qflll(x,{flag=0}): LLL reduction of the vectors forming the matrix x (gives the 
+unimodular transformation matrix T such that x*T is LLL-reduced). flag is 
+optional, and can be 0: default, 1: assumes x is integral, 2: assumes x is 
+integral, returns a partially reduced basis, 4: assumes x is integral, returns 
+[K,T] where K is the integer kernel of x and T the LLL reduced image, 5: same 
+as 4 but x may have polynomial coefficients, 8: same as 0 but x may have 
+polynomial coefficients.
+
+
+  ***   at top-level: lllintpartial()
+  ***                 ^---------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: lllintpartial(x) ===> qflll(x,2)
+
+qflll(x,{flag=0}): LLL reduction of the vectors forming the matrix x (gives the 
+unimodular transformation matrix T such that x*T is LLL-reduced). flag is 
+optional, and can be 0: default, 1: assumes x is integral, 2: assumes x is 
+integral, returns a partially reduced basis, 4: assumes x is integral, returns 
+[K,T] where K is the integer kernel of x and T the LLL reduced image, 5: same 
+as 4 but x may have polynomial coefficients, 8: same as 0 but x may have 
+polynomial coefficients.
+
+
+  ***   at top-level: lllkerim()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: lllkerim(x) ===> qflll(x,4)
+
+qflll(x,{flag=0}): LLL reduction of the vectors forming the matrix x (gives the 
+unimodular transformation matrix T such that x*T is LLL-reduced). flag is 
+optional, and can be 0: default, 1: assumes x is integral, 2: assumes x is 
+integral, returns a partially reduced basis, 4: assumes x is integral, returns 
+[K,T] where K is the integer kernel of x and T the LLL reduced image, 5: same 
+as 4 but x may have polynomial coefficients, 8: same as 0 but x may have 
+polynomial coefficients.
+
+
+  ***   at top-level: lllkerimgen()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: lllkerimgen(x) ===> qflll(x,5)
+
+qflll(x,{flag=0}): LLL reduction of the vectors forming the matrix x (gives the 
+unimodular transformation matrix T such that x*T is LLL-reduced). flag is 
+optional, and can be 0: default, 1: assumes x is integral, 2: assumes x is 
+integral, returns a partially reduced basis, 4: assumes x is integral, returns 
+[K,T] where K is the integer kernel of x and T the LLL reduced image, 5: same 
+as 4 but x may have polynomial coefficients, 8: same as 0 but x may have 
+polynomial coefficients.
+
+
+  ***   at top-level: lllrat()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+This function no longer exists
+
+
+  ***   at top-level: ln()
+  ***                 ^----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: ln(x) ===> log(x)
+
+log(x): natural logarithm of x.
+
+
+  ***   at top-level: localred()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: localred(e) ===> elllocalred(e)
+
+elllocalred(E,p): E being an elliptic curve, returns [f,kod,[u,r,s,t],c], where 
+f is the conductor's exponent, kod is the Kodaira type for E at p, [u,r,s,t] is 
+the change of variable needed to make E minimal at p, and c is the local 
+Tamagawa number c_p.
+
+
+  ***   at top-level: logagm()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: logagm(x) ===> log(x,1)
+
+log(x): natural logarithm of x.
+
+
+  ***   at top-level: lseriesell()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: lseriesell(e,s,N,A) ===> elllseries(e,s,A)
+
+elllseries(E,s,{A=1}): L-series at s of the elliptic curve E, where A a cut-off 
+point close to 1.
+
+
+  ***   at top-level: makebigbnf()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: makebigbnf(sbnf) ===> bnfinit(sbnf)
+
+bnfinit(P,{flag=0},{tech=[]}): compute the necessary data for future use in 
+ideal and unit group computations, including fundamental units if they are not 
+too large. flag and tech are both optional. flag can be any of 0: default, 1: 
+insist on having fundamental units. See manual for details about tech.
+
+
+  ***   at top-level: mat()
+  ***                 ^-----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: mat(x) ===> Mat(x)
+
+Mat({x=[]}): transforms any GEN x into a matrix. Empty matrix if x is omitted.
+
+
+  ***   at top-level: matextract()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: matextract(x,y,z) ===> vecextract(x,y,z)
+
+vecextract(x,y,{z}): extraction of the components of the matrix or vector x 
+according to y and z. If z is omitted, y represents columns, otherwise y 
+corresponds to rows and z to columns. y and z can be vectors (of indices), 
+strings (indicating ranges as in "1..10") or masks (integers whose binary 
+representation indicates the indices to extract, from left to right 1, 2, 4, 8, 
+etc.).
+
+
+  ***   at top-level: mathell()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: mathell(e,x) ===> ellheightmatrix(e,x)
+
+ellheightmatrix(E,x): gives the height matrix for vector of points x on 
+elliptic curve E.
+
+
+  ***   at top-level: matrixqz2()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: matrixqz2(x,p) ===> matrixqz(x,-1)
+
+matrixqz(A,{p=0}): if p>=0, transforms the rational or integral mxn (m>=n) 
+matrix A into an integral matrix with gcd of maximal determinants coprime to p. 
+If p=-1, finds a basis of the intersection with Z^n of the lattice spanned by 
+the columns of A. If p=-2, finds a basis of the intersection with Z^n of the 
+Q-vector space spanned by the columns of A.
+
+
+  ***   at top-level: matrixqz3()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: matrixqz3(x,p) ===> matrixqz(x,-2)
+
+matrixqz(A,{p=0}): if p>=0, transforms the rational or integral mxn (m>=n) 
+matrix A into an integral matrix with gcd of maximal determinants coprime to p. 
+If p=-1, finds a basis of the intersection with Z^n of the lattice spanned by 
+the columns of A. If p=-2, finds a basis of the intersection with Z^n of the 
+Q-vector space spanned by the columns of A.
+
+
+  ***   at top-level: minideal()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: minideal(nf,ix,vdir) ===> idealmin(nf,ix,vdir)
+
+idealmin(nf,ix,{vdir}): pseudo-minimum of the ideal ix in the direction vdir in 
+the number field nf.
+
+
+  ***   at top-level: minim()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: minim(x,bound,maxnum) ===> qfminim(x,bound,maxnum)
+
+qfminim(x,{b},{m},{flag=0}): x being a square and symmetric matrix representing 
+a positive definite quadratic form, this function deals with the vectors of x 
+whose norm is less than or equal to b, enumerated using the Fincke-Pohst 
+algorithm, storing at most m vectors (no limit if m is omitted). The function 
+searches for the minimal non-zero vectors if b is omitted. The precise behavior 
+depends on flag. 0: seeks at most 2m vectors (unless m omitted), returns 
+[N,M,mat] where N is the number of vectors found, M the maximum norm among 
+these, and mat lists half the vectors (the other half is given by -mat). 1: 
+ignores m and returns the first vector whose norm is less than b. 2: as 0 but 
+uses a more robust, slower implementation, valid for non integral quadratic 
+forms.
+
+
+  ***   at top-level: minim2()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: minim2(x,bound) ===> qfminim(x,bound,,1)
+
+qfminim(x,{b},{m},{flag=0}): x being a square and symmetric matrix representing 
+a positive definite quadratic form, this function deals with the vectors of x 
+whose norm is less than or equal to b, enumerated using the Fincke-Pohst 
+algorithm, storing at most m vectors (no limit if m is omitted). The function 
+searches for the minimal non-zero vectors if b is omitted. The precise behavior 
+depends on flag. 0: seeks at most 2m vectors (unless m omitted), returns 
+[N,M,mat] where N is the number of vectors found, M the maximum norm among 
+these, and mat lists half the vectors (the other half is given by -mat). 1: 
+ignores m and returns the first vector whose norm is less than b. 2: as 0 but 
+uses a more robust, slower implementation, valid for non integral quadratic 
+forms.
+
+
+  ***   at top-level: mod()
+  ***                 ^-----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: mod(x,y) ===> Mod(x,y)
+
+Mod(a,b): creates 'a modulo b'.
+
+
+  ***   at top-level: modp()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: modp(x,y,p) ===> Mod(x,y)
+
+Mod(a,b): creates 'a modulo b'.
+
+
+  ***   at top-level: modulargcd()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: modulargcd(x,y) ===> gcd(x,y,1)
+
+gcd(x,{y}): greatest common divisor of x and y.
+
+
+  ***   at top-level: mu()
+  ***                 ^----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: mu(n) ===> moebius(n)
+
+moebius(x): Moebius function of x.
+
+
+  ***   at top-level: nfdiv()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: nfdiv(nf,a,b) ===> nfeltdiv(nf,a,b)
+
+nfdiv(nf,x,y): element x/y in nf.
+
+
+  ***   at top-level: nfdiveuc()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: nfdiveuc(nf,a,b) ===> nfeltdiveuc(nf,a,b)
+
+nfdiveuc(nf,x,y): gives algebraic integer q such that x-by is small.
+
+
+  ***   at top-level: nfdivres()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: nfdivres(nf,a,b) ===> nfeltdivrem(nf,a,b)
+
+nfeltdivrem(nf,x,y): gives [q,r] such that r=x-by is small.
+
+
+  ***   at top-level: nfhermite()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: nfhermite(nf,x) ===> nfhnf(nf,x)
+
+nfhnf(nf,x,{flag=0}): if x=[A,I], gives a pseudo-basis [B,J] of the module sum 
+A_jI_j. If flag is non-zero, return [[B,J], U], where U is the transformation 
+matrix such that AU = [0|B]
+
+
+  ***   at top-level: nfhermitemod()
+  ***                 ^--------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: nfhermitemod(nf,x,detx) ===> nfhnfmod(nf,x,detx)
+
+nfhnfmod(nf,x,detx): if x=[A,I], and detx is a multiple of the ideal 
+determinant of x, gives a pseudo-basis of the module sum A_jI_j.
+
+
+  ***   at top-level: nfmod()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: nfmod(nf,a,b) ===> nfeltmod(nf,a,b)
+
+nfeltmod(nf,x,y): gives r such that r=x-by is small with q algebraic integer.
+
+
+  ***   at top-level: nfmul()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: nfmul(nf,a,b) ===> nfeltmul(nf,a,b)
+
+nfmul(nf,x,y): element x.y in nf.
+
+
+  ***   at top-level: nfpow()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: nfpow(nf,a,k) ===> nfeltpow(nf,a,k)
+
+nfeltpow(nf,x,k): element x^k in nf.
+
+
+  ***   at top-level: nfreduce()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: nfreduce(nf,a,id) ===> nfeltreduce(nf,a,id)
+
+nfeltreduce(nf,a,id): gives r such that a-r is in the ideal id and r is small.
+
+
+  ***   at top-level: nfsmith()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: nfsmith(nf,x) ===> nfsnf(nf,x)
+
+nfsnf(nf,x,{flag=0}): if x=[A,I,J], outputs D=[d_1,...d_n] Smith normal form of 
+x. If flag is non-zero return [D,U,V], where UAV = Id.
+
+
+  ***   at top-level: nfval()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: nfval(nf,a,pr) ===> nfeltval(nf,a,pr)
+
+nfeltval(nf,x,pr,{&y}): valuation of element x at the prime pr as output by 
+idealprimedec.
+
+
+  ***   at top-level: nucomp()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: nucomp(x,y,l) ===> qfbnucomp(x,y,l)
+
+qfbnucomp(x,y,L): composite of primitive positive definite quadratic forms x 
+and y using nucomp and nudupl, where L=[|D/4|^(1/4)] is precomputed.
+
+
+  ***   at top-level: numer()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: numer(x) ===> numerator(x)
+
+numerator(x): numerator of x.
+
+
+  ***   at top-level: nupow()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: nupow(x,n) ===> qfbnupow(x,n)
+
+qfbnupow(x,n): n-th power of primitive positive definite quadratic form x using 
+nucomp and nudupl.
+
+
+  ***   at top-level: o()
+  ***                 ^---
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: o(x) ===> O(x)
+
+O(p^e): p-adic or power series zero with precision given by e
+
+
+  ***   at top-level: ordell()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: ordell(e,x) ===> ellordinate(e,x)
+
+ellordinate(E,x): y-coordinates corresponding to x-ordinate x on elliptic curve 
+E.
+
+
+  ***   at top-level: order()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: order(x) ===> znorder(x)
+
+znorder(x,{o}): order of the integermod x in (Z/nZ)*. Optional o represents a 
+multiple of the order of the element.
+
+
+  ***   at top-level: orderell()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: orderell(e,x) ===> ellorder(e,x)
+
+ellorder(E,z,{o}): order of the point z on the elliptic curve E over a number 
+field or a finite field, 0 if non-torsion. The parameter o, if present, 
+represents a non-zero multiple of the order of z.
+
+
+  ***   at top-level: ordred()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: ordred(x) ===> polredord(x)
+
+polredord(x): reduction of the polynomial x, staying in the same order.
+
+
+  ***   at top-level: pascal()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: pascal(n) ===> matpascal(n)
+
+matpascal(n,{q}): Pascal triangle of order n if q is omitted. q-Pascal triangle 
+otherwise.
+
+
+  ***   at top-level: perf()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: perf(a) ===> qfperfection(a)
+
+qfperfection(G): rank of matrix of xx~ for x minimal vectors of a gram matrix 
+G.
+
+
+  ***   at top-level: permutation()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: permutation(n,k) ===> numtoperm(n,k)
+
+numtoperm(n,k): permutation number k (mod n!) of n letters (n C-integer).
+
+
+  ***   at top-level: permutation2num()
+  ***                 ^-----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: permutation2num(vect) ===> permtonum(vect)
+
+permtonum(x): ordinal (between 1 and n!) of permutation x.
+
+
+  ***   at top-level: pf()
+  ***                 ^----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: pf(x,p) ===> qfbprimeform(x,p)
+
+qfbprimeform(x,p): returns the prime form of discriminant x, whose first 
+coefficient is p.
+
+
+  ***   at top-level: phi()
+  ***                 ^-----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: phi(x) ===> eulerphi(x)
+
+eulerphi(x): Euler's totient function of x.
+
+
+  ***   at top-level: pi()
+  ***                 ^----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: pi ===> Pi
+
+Pi=Pi(): the constant pi, with current precision.
+
+
+  ***   at top-level: pnqn()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: pnqn(x) ===> contfracpnqn(x)
+
+contfracpnqn(x, {n=-1}): [p_n,p_{n-1}; q_n,q_{n-1}] corresponding to the 
+continued fraction x. If n >= 0 is present, returns all convergents from 
+p_0/q_0 up to p_n/q_n.
+
+
+  ***   at top-level: pointell()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: pointell(e,z) ===> ellztopoint(e,z)
+
+ellztopoint(E,z): coordinates of point P on the curve E corresponding to the 
+complex number z.
+
+
+  ***   at top-level: polint()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: polint(xa,ya,x) ===> polinterpolate(xa,ya,p)
+
+polinterpolate(X,{Y},{x},{&e}): polynomial interpolation at x according to data 
+vectors X, Y (ie return P such that P(X[i]) = Y[i] for all i). If Y is omitted, 
+return P such that P(i) = X[i]. If present, e will contain an error estimate on 
+the returned value.
+
+
+  ***   at top-level: polred2()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: polred2(x) ===> polred(x,2)
+
+polred(T,{flag=0}): Deprecated, use polredbest. Reduction of the polynomial T 
+(gives minimal polynomials only). The following binary digits of (optional) 
+flag are significant 1: partial reduction, 2: gives also elements.
+
+
+  ***   at top-level: polredabs2()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: polredabs2(x) ===> polredabs(x,1)
+
+polredabs(T,{flag=0}): a smallest generating polynomial of the number field for 
+the T2 norm on the roots, with smallest index for the minimal T2 norm. flag is 
+optional, whose binary digit mean 1: give the element whose characteristic 
+polynomial is the given polynomial. 4: give all polynomials of minimal T2 norm 
+(give only one of P(x) and P(-x)).
+
+
+  ***   at top-level: polredabsall()
+  ***                 ^--------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: polredabsall(x) ===> polredabs(x,4)
+
+polredabs(T,{flag=0}): a smallest generating polynomial of the number field for 
+the T2 norm on the roots, with smallest index for the minimal T2 norm. flag is 
+optional, whose binary digit mean 1: give the element whose characteristic 
+polynomial is the given polynomial. 4: give all polynomials of minimal T2 norm 
+(give only one of P(x) and P(-x)).
+
+
+  ***   at top-level: polredabsfast()
+  ***                 ^---------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: polredabsfast(x) ===> polredabs(x,8)
+
+polredabs(T,{flag=0}): a smallest generating polynomial of the number field for 
+the T2 norm on the roots, with smallest index for the minimal T2 norm. flag is 
+optional, whose binary digit mean 1: give the element whose characteristic 
+polynomial is the given polynomial. 4: give all polynomials of minimal T2 norm 
+(give only one of P(x) and P(-x)).
+
+
+  ***   at top-level: polredabsnored()
+  ***                 ^----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: polredabsnored(x) ===> polredabs(x,2)
+
+polredabs(T,{flag=0}): a smallest generating polynomial of the number field for 
+the T2 norm on the roots, with smallest index for the minimal T2 norm. flag is 
+optional, whose binary digit mean 1: give the element whose characteristic 
+polynomial is the given polynomial. 4: give all polynomials of minimal T2 norm 
+(give only one of P(x) and P(-x)).
+
+
+  ***   at top-level: polvar()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: polvar(x) ===> variable(x)
+
+variable({x}): main variable of object x. Gives p for p-adic x, 0 if no 
+variable can be associated to x. Returns the list of user variables if x is 
+omitted.
+
+
+  ***   at top-level: poly()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: poly(x,v) ===> Pol(x,v)
+
+Pol(t,{v='x}): convert t (usually a vector or a power series) into a polynomial 
+with variable v, starting with the leading coefficient.
+
+
+  ***   at top-level: polylogd()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: polylogd(m,x) ===> polylog(m,x,1)
+
+polylog(m,x,{flag=0}): m-th polylogarithm of x. flag is optional, and can be 0: 
+default, 1: D_m~-modified m-th polylog of x, 2: D_m-modified m-th polylog of x, 
+3: P_m-modified m-th polylog of x.
+
+
+  ***   at top-level: polylogdold()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: polylogdold(m,x) ===> polylog(m,x,2)
+
+polylog(m,x,{flag=0}): m-th polylogarithm of x. flag is optional, and can be 0: 
+default, 1: D_m~-modified m-th polylog of x, 2: D_m-modified m-th polylog of x, 
+3: P_m-modified m-th polylog of x.
+
+
+  ***   at top-level: polylogp()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: polylogp(m,x) ===> polylog(m,x,3)
+
+polylog(m,x,{flag=0}): m-th polylogarithm of x. flag is optional, and can be 0: 
+default, 1: D_m~-modified m-th polylog of x, 2: D_m-modified m-th polylog of x, 
+3: P_m-modified m-th polylog of x.
+
+
+  ***   at top-level: polyrev()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: polyrev(x,v) ===> Polrev(x,v)
+
+Polrev(t,{v='x}): convert t (usually a vector or a power series) into a 
+polynomial with variable v, starting with the constant term.
+
+
+  ***   at top-level: polzag()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: polzag(n,m) ===> polzagier(n,m)
+
+polzagier(n,m): Zagier's polynomials of index n,m.
+
+
+  ***   at top-level: powell()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: powell(e,x,n) ===> ellmul(e,x,n)
+
+ellmul(E,z,n): n times the point z on elliptic curve E (n in Z).
+
+
+  ***   at top-level: powrealraw()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: powrealraw(x,n) ===> qfbpowraw(x,n)
+
+qfbpowraw(x,n): n-th power without reduction of the binary quadratic form x.
+
+
+  ***   at top-level: prec()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: prec(x,n) ===> precision(x,n)
+
+precision(x,{n}): if n is present, return x at precision n. If n is omitted, 
+return real precision of object x.
+
+
+  ***   at top-level: primedec()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: primedec(nf,p) ===> idealprimedec(nf,p)
+
+idealprimedec(nf,p,{f=0}): prime ideal decomposition of the prime number p in 
+the number field nf as a vector of 5 component vectors [p,a,e,f,b] representing 
+the prime ideals pZ_K+a. Z_K, e,f as usual, a as vector of components on the 
+integral basis, b Lenstra's constant. If f is present and non-zero, restrict 
+the result to primes of residue degree <= f.
+
+
+  ***   at top-level: primroot()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: primroot(n) ===> znprimroot(n)
+
+znprimroot(n): returns a primitive root of n when it exists.
+
+
+  ***   at top-level: principalideal()
+  ***                 ^----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+This function no longer exists
+
+
+  ***   at top-level: principalidele()
+  ***                 ^----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+This function no longer exists
+
+
+  ***   at top-level: prodinf1()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: prodinf1(X=a,expr) ===> prodinf(X=a,expr,1)
+
+prodinf(X=a,expr,{flag=0}): infinite product (X goes from a to infinity) of 
+real or complex expression. flag can be 0 (default) or 1, in which case compute 
+the product of the 1+expr instead.
+
+
+  ***   at top-level: qfi()
+  ***                 ^-----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: qfi(a,b,c) ===> Qfb(a,b,c)
+
+Qfb(a,b,c,{D=0.}): binary quadratic form a*x^2+b*x*y+c*y^2. D is optional (0.0 
+by default) and initializes Shanks's distance if b^2-4*a*c>0.
+
+
+  ***   at top-level: qfr()
+  ***                 ^-----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: qfr(a,b,c,d) ===> Qfb(a,b,c,d)
+
+Qfb(a,b,c,{D=0.}): binary quadratic form a*x^2+b*x*y+c*y^2. D is optional (0.0 
+by default) and initializes Shanks's distance if b^2-4*a*c>0.
+
+
+1546275796
+  ***   at top-level: rank()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: rank(x) ===> matrank(x)
+
+matrank(x): rank of the matrix x.
+
+
+  ***   at top-level: rayclassno()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: rayclassno(bnf,x) ===> bnrclassno(bnf,x)
+
+bnrclassno(A,{B},{C}): relative degree of the class field defined by A,B,C. 
+[A,{B},{C}] is of type [bnr], [bnr,subgroup], [bnf,modulus], or 
+[bnf,modulus,subgroup]. Faster than bnrinit if only the ray class number is 
+wanted.
+
+
+  ***   at top-level: rayclassnolist()
+  ***                 ^----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: rayclassnolist(bnf,liste) ===> bnrclassnolist(bnf,liste)
+
+bnrclassnolist(bnf,list): if list is as output by ideallist or similar, gives 
+list of corresponding ray class numbers.
+
+
+  ***   at top-level: recip()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: recip(x) ===> polrecip(x)
+
+polrecip(pol): reciprocal polynomial of pol.
+
+
+  ***   at top-level: redimag()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: redimag(x) ===> qfbred(x)
+
+qfbred(x,{flag=0},{d},{isd},{sd}): reduction of the binary quadratic form x. 
+All other args. are optional. The arguments d, isd and sd, if present, supply 
+the values of the discriminant, floor(sqrt(d)) and sqrt(d) respectively. If 
+d<0, its value is not used and all references to Shanks's distance hereafter 
+are meaningless. flag can be any of 0: default, uses Shanks's distance function 
+d; 1: use d, do a single reduction step; 2: do not use d; 3: do not use d, 
+single reduction step.
+
+
+  ***   at top-level: redreal()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: redreal(x) ===> qfbred(x)
+
+qfbred(x,{flag=0},{d},{isd},{sd}): reduction of the binary quadratic form x. 
+All other args. are optional. The arguments d, isd and sd, if present, supply 
+the values of the discriminant, floor(sqrt(d)) and sqrt(d) respectively. If 
+d<0, its value is not used and all references to Shanks's distance hereafter 
+are meaningless. flag can be any of 0: default, uses Shanks's distance function 
+d; 1: use d, do a single reduction step; 2: do not use d; 3: do not use d, 
+single reduction step.
+
+
+  ***   at top-level: redrealnod()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: redrealnod(x,d) ===> qfbred(x,2,,d)
+
+qfbred(x,{flag=0},{d},{isd},{sd}): reduction of the binary quadratic form x. 
+All other args. are optional. The arguments d, isd and sd, if present, supply 
+the values of the discriminant, floor(sqrt(d)) and sqrt(d) respectively. If 
+d<0, its value is not used and all references to Shanks's distance hereafter 
+are meaningless. flag can be any of 0: default, uses Shanks's distance function 
+d; 1: use d, do a single reduction step; 2: do not use d; 3: do not use d, 
+single reduction step.
+
+
+  ***   at top-level: reduceddisc()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: reduceddisc(f) ===> poldiscreduced(f)
+
+poldiscreduced(f): vector of elementary divisors of Z[a]/f'(a)Z[a], where a is 
+a root of the polynomial f.
+
+
+  ***   at top-level: regula()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: regula(x) ===> quadregulator(x)
+
+quadregulator(x): regulator of the real quadratic field of discriminant x.
+
+
+  ***   at top-level: reorder()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+This function no longer exists
+
+
+  ***   at top-level: resultant()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: resultant(x,y) ===> polresultant(x,y)
+
+polresultant(x,y,{v},{flag=0}): resultant of the polynomials x and y, with 
+respect to the main variables of x and y if v is omitted, with respect to the 
+variable v otherwise. flag is optional, and can be 0: default, uses either the 
+subresultant algorithm, a modular algorithm or Sylvester's matrix, depending on 
+the inputs; 1 uses Sylvester's matrix (should always be slower than the 
+default).
+
+
+  ***   at top-level: resultant2()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: resultant2(x,y) ===> polresultant(x,y,1)
+
+polresultant(x,y,{v},{flag=0}): resultant of the polynomials x and y, with 
+respect to the main variables of x and y if v is omitted, with respect to the 
+variable v otherwise. flag is optional, and can be 0: default, uses either the 
+subresultant algorithm, a modular algorithm or Sylvester's matrix, depending on 
+the inputs; 1 uses Sylvester's matrix (should always be slower than the 
+default).
+
+
+  ***   at top-level: reverse()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: reverse(x) ===> serreverse(x)
+
+serreverse(s): reversion of the power series s.
+
+
+  ***   at top-level: rhoreal()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: rhoreal(x) ===> qfbred(x,1)
+
+qfbred(x,{flag=0},{d},{isd},{sd}): reduction of the binary quadratic form x. 
+All other args. are optional. The arguments d, isd and sd, if present, supply 
+the values of the discriminant, floor(sqrt(d)) and sqrt(d) respectively. If 
+d<0, its value is not used and all references to Shanks's distance hereafter 
+are meaningless. flag can be any of 0: default, uses Shanks's distance function 
+d; 1: use d, do a single reduction step; 2: do not use d; 3: do not use d, 
+single reduction step.
+
+
+  ***   at top-level: rhorealnod()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: rhorealnod(x,d) ===> qfbred(x,3,,d)
+
+qfbred(x,{flag=0},{d},{isd},{sd}): reduction of the binary quadratic form x. 
+All other args. are optional. The arguments d, isd and sd, if present, supply 
+the values of the discriminant, floor(sqrt(d)) and sqrt(d) respectively. If 
+d<0, its value is not used and all references to Shanks's distance hereafter 
+are meaningless. flag can be any of 0: default, uses Shanks's distance function 
+d; 1: use d, do a single reduction step; 2: do not use d; 3: do not use d, 
+single reduction step.
+
+
+  ***   at top-level: rndtoi()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: rndtoi(x) ===> round(x,&e)
+
+round(x,{&e}): take the nearest integer to all the coefficients of x. If e is 
+present, do not take into account loss of integer part precision, and set e = 
+error estimate in bits.
+
+
+  ***   at top-level: rnfdiscf()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: rnfdiscf(nf,pol) ===> rnfdisc(nf,pol)
+
+rnfdisc(nf,pol): given a pol with coefficients in nf, gives a 2-component 
+vector [D,d], where D is the relative ideal discriminant, and d is the relative 
+discriminant in nf^*/nf*^2.
+
+
+  ***   at top-level: rnfequation2()
+  ***                 ^--------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: rnfequation2(nf,pol) ===> rnfequation(nf,pol,1)
+
+rnfequation(nf,pol,{flag=0}): given a pol with coefficients in nf, gives an 
+absolute equation z of the number field defined by pol. flag is optional, and 
+can be 0: default, or non-zero, gives [z,al,k], where z defines the absolute 
+equation L/Q as in the default behavior, al expresses as an element of L a root 
+of the polynomial defining the base field nf, and k is a small integer such 
+that t = b + k al is a root of z, for b a root of pol.
+
+
+  ***   at top-level: rnfhermitebasis()
+  ***                 ^-----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: rnfhermitebasis(bnf,order) ===> rnfhnfbasis(bnf,order)
+
+rnfhnfbasis(bnf,x): given an order x as output by rnfpseudobasis, gives either 
+a true HNF basis of the order if it exists, zero otherwise.
+
+
+  ***   at top-level: rootmod()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: rootmod(x,p) ===> polrootsmod(x,p)
+
+polrootsmod(pol,p,{flag=0}): roots mod the prime p of the polynomial pol. flag 
+is optional, and can be 0: default, or 1: use a naive search, useful for small 
+p.
+
+
+  ***   at top-level: rootmod2()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: rootmod2(x,p) ===> polrootsmod(x,p,1)
+
+polrootsmod(pol,p,{flag=0}): roots mod the prime p of the polynomial pol. flag 
+is optional, and can be 0: default, or 1: use a naive search, useful for small 
+p.
+
+
+  ***   at top-level: rootpadic()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: rootpadic(x,p,r) ===> polrootspadic(x,p,r)
+
+polrootspadic(x,p,r): p-adic roots of the polynomial x to precision r.
+
+
+  ***   at top-level: roots()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: roots(x) ===> polroots(x)
+
+polroots(x): complex roots of the polynomial x using Schonhage's method, as 
+modified by Gourdon.
+
+
+  ***   at top-level: rootsof1()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: rootsof1(nf) ===> nfrootsof1(nf)
+
+nfrootsof1(nf): number of roots of unity and primitive root of unity in the 
+number field nf.
+
+
+  ***   at top-level: rootsold()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+This function no longer exists
+
+
+  ***   at top-level: rounderror()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: rounderror(x) ===> round(x,&e)
+
+round(x,{&e}): take the nearest integer to all the coefficients of x. If e is 
+present, do not take into account loss of integer part precision, and set e = 
+error estimate in bits.
+
+
+  ***   at top-level: series()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: series(x,v) ===> Ser(x,v)
+
+Ser(s,{v='x},{d=seriesprecision}): convert s into a power series with variable 
+v and precision d, starting with the constant coefficient.
+
+
+  ***   at top-level: set()
+  ***                 ^-----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: set(x) ===> Set(x)
+
+Set({x=[]}): convert x into a set, i.e. a row vector with strictly increasing 
+coefficients. Empty set if x is omitted.
+
+
+  ***   at top-level: sigmak()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: sigmak(k,x) ===> sigma(x,k)
+
+sigma(x,{k=1}): sum of the k-th powers of the divisors of x. k is optional and 
+if omitted is assumed to be equal to 1.
+
+
+  ***   at top-level: signat()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: signat(x) ===> qfsign(x)
+
+qfsign(x): signature of the symmetric matrix x.
+
+
+  ***   at top-level: signunit()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: signunit(bnf) ===> bnfsignunit(bnf)
+
+bnfsignunit(bnf): matrix of signs of the real embeddings of the system of 
+fundamental units found by bnfinit.
+
+
+  ***   at top-level: simplefactmod()
+  ***                 ^---------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: simplefactmod(x,p) ===> factormod(x,p,1)
+
+factormod(x,p,{flag=0}): factors the polynomial x modulo the prime p, using 
+Berlekamp. flag is optional, and can be 0: default or 1: only the degrees of 
+the irreducible factors are given.
+
+
+  ***   at top-level: size()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: size(x) ===> sizedigit(x)
+
+sizedigit(x): rough upper bound for the number of decimal digits of (the 
+components of) $x$. DEPRECATED.
+
+
+  ***   at top-level: smallbasis()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: smallbasis(x) ===> nfbasis(x,1)
+
+nfbasis(T): integral basis of the field Q[a], where a is a root of the 
+polynomial T, using the round 4 algorithm. An argument [T,listP] is possible, 
+where listP is a list of primes (to get an order which is maximal at certain 
+primes only) or a prime bound.
+
+
+  ***   at top-level: smallbuchinit()
+  ***                 ^---------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: smallbuchinit(x) ===> bnfcompress(x)
+
+bnfcompress(bnf): converts bnf to a much smaller sbnf, containing the same 
+information. Use bnfinit(sbnf) to recover a true bnf.
+
+
+  ***   at top-level: smalldiscf()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: smalldiscf(x) ===> nfdisc(x,1)
+
+nfdisc(T): discriminant of the number field defined by the polynomial T. An 
+argument [T,listP] is possible, where listP is a list of primes or a prime 
+bound.
+
+
+  ***   at top-level: smallfact()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: smallfact(x) ===> factor(x,0)
+
+factor(x,{lim}): factorization of x. lim is optional and can be set whenever x 
+is of (possibly recursive) rational type. If lim is set return partial 
+factorization, using primes < lim.
+
+
+  ***   at top-level: smallinitell()
+  ***                 ^--------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: smallinitell(x) ===> ellinit(x,1)
+
+ellinit(x,{D=1}): let x be a vector [a1,a2,a3,a4,a6], or [a4,a6] if a1=a2=a3=0, 
+defining the curve Y^2 + a1.XY + a3.Y = X^3 + a2.X^2 + a4.X + a6; x can also be 
+a string, in which case the curve with matching name is retrieved from the 
+elldata database, if available. This function initializes an elliptic curve 
+over the domain D (inferred from coefficients if omitted).
+
+
+  ***   at top-level: smallpolred()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: smallpolred(x) ===> polred(x,1)
+
+polred(T,{flag=0}): Deprecated, use polredbest. Reduction of the polynomial T 
+(gives minimal polynomials only). The following binary digits of (optional) 
+flag are significant 1: partial reduction, 2: gives also elements.
+
+
+  ***   at top-level: smallpolred2()
+  ***                 ^--------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: smallpolred2(x) ===> polred(x,3)
+
+polred(T,{flag=0}): Deprecated, use polredbest. Reduction of the polynomial T 
+(gives minimal polynomials only). The following binary digits of (optional) 
+flag are significant 1: partial reduction, 2: gives also elements.
+
+
+  ***   at top-level: smith()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: smith(x) ===> matsnf(x)
+
+matsnf(X,{flag=0}): Smith normal form (i.e. elementary divisors) of the matrix 
+X, expressed as a vector d. Binary digits of flag mean 1: returns [u,v,d] where 
+d=u*X*v, otherwise only the diagonal d is returned, 2: allow polynomial 
+entries, otherwise assume X is integral, 4: removes all information 
+corresponding to entries equal to 1 in d.
+
+
+  ***   at top-level: smith2()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: smith2(x) ===> matsnf(x,1)
+
+matsnf(X,{flag=0}): Smith normal form (i.e. elementary divisors) of the matrix 
+X, expressed as a vector d. Binary digits of flag mean 1: returns [u,v,d] where 
+d=u*X*v, otherwise only the diagonal d is returned, 2: allow polynomial 
+entries, otherwise assume X is integral, 4: removes all information 
+corresponding to entries equal to 1 in d.
+
+
+  ***   at top-level: smithclean()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: smithclean(x) ===> matsnf(x,4)
+
+matsnf(X,{flag=0}): Smith normal form (i.e. elementary divisors) of the matrix 
+X, expressed as a vector d. Binary digits of flag mean 1: returns [u,v,d] where 
+d=u*X*v, otherwise only the diagonal d is returned, 2: allow polynomial 
+entries, otherwise assume X is integral, 4: removes all information 
+corresponding to entries equal to 1 in d.
+
+
+  ***   at top-level: smithpol()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: smithpol(x) ===> matsnf(x,2)
+
+matsnf(X,{flag=0}): Smith normal form (i.e. elementary divisors) of the matrix 
+X, expressed as a vector d. Binary digits of flag mean 1: returns [u,v,d] where 
+d=u*X*v, otherwise only the diagonal d is returned, 2: allow polynomial 
+entries, otherwise assume X is integral, 4: removes all information 
+corresponding to entries equal to 1 in d.
+
+
+  ***   at top-level: sort()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: sort(x) ===> vecsort(x)
+
+vecsort(x,{cmpf},{flag=0}): sorts the vector of vectors (or matrix) x in 
+ascending order, according to the comparison function cmpf, if not omitted. (If 
+cmpf is an integer, sort according to the value of the k-th component of each 
+entry.) Binary digits of flag (if present) mean: 1: indirect sorting, return 
+the permutation instead of the permuted vector, 2: sort using lexicographic 
+order, 4: use descending instead of ascending order, 8: remove duplicate 
+entries.
+
+
+  ***   at top-level: sqred()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: sqred(x) ===> qfgaussred(x)
+
+qfgaussred(q): square reduction of the (symmetric) matrix q (returns a square 
+matrix whose i-th diagonal term is the coefficient of the i-th square in which 
+the coefficient of the i-th variable is 1).
+
+
+  ***   at top-level: srgcd()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: srgcd(x,y) ===> gcd(x,y,2)
+
+gcd(x,{y}): greatest common divisor of x and y.
+
+
+  ***   at top-level: sturm()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: sturm(x) ===> polsturm(x)
+
+polsturm(T,{ab}): number of real roots of the squarefree polynomial T (in the 
+interval ab = [a,b] if present).
+
+
+  ***   at top-level: sturmpart()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: sturmpart(x,a,b) ===> polsturm(x,a,b)
+
+polsturm(T,{ab}): number of real roots of the squarefree polynomial T (in the 
+interval ab = [a,b] if present).
+
+
+  ***   at top-level: subcyclo()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: subcyclo(p,d) ===> polsubcyclo(p,d)
+
+polsubcyclo(n,d,{v='x}): finds an equation (in variable v) for the d-th degree 
+subfields of Q(zeta_n). Output is a polynomial, or a vector of polynomials if 
+there are several such fields or none.
+
+
+  ***   at top-level: subell()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: subell(e,a,b) ===> ellsub(e,a,b)
+
+ellsub(E,z1,z2): difference of the points z1 and z2 on elliptic curve E.
+
+
+  ***   at top-level: sumalt2()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: sumalt2(X=a,expr) ===> sumalt(X=a,expr,1)
+
+sumalt(X=a,expr,{flag=0}): Cohen-Villegas-Zagier's acceleration of alternating 
+series expr, X starting at a. flag is optional, and can be 0: default, or 1: 
+uses a slightly different method using Zagier's polynomials.
+
+
+  ***   at top-level: sumpos2()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: sumpos2(X=a,expr) ===> sumpos(X=a,expr,1)
+
+sumpos(X=a,expr,{flag=0}): sum of positive (or negative) series expr, the 
+formal variable X starting at a. flag is optional, and can be 0: default, or 1: 
+uses a slightly different method using Zagier's polynomials.
+
+
+  ***   at top-level: supplement()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: supplement(x) ===> matsupplement(x)
+
+matsupplement(x): supplement the columns of the matrix x to an invertible 
+matrix.
+
+
+  ***   at top-level: sylvestermatrix()
+  ***                 ^-----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: sylvestermatrix(x,y) ===> polsylvestermatrix(x,y)
+
+polsylvestermatrix(x,y): forms the sylvester matrix associated to the two 
+polynomials x and y. Warning: the polynomial coefficients are in columns, not 
+in rows.
+
+
+  ***   at top-level: taniyama()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: taniyama(e) ===> elltaniyama(e)
+
+elltaniyama(E, {d = seriesprecision}): modular parametrization of elliptic 
+curve E/Q.
+
+
+  ***   at top-level: tchebi()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: tchebi(n) ===> polchebyshev(n)
+
+polchebyshev(n,{flag=1},{a='x}): Chebychev polynomial of the first (flag = 1) 
+or second (flag = 2) kind, of degree n, evaluated at a.
+
+
+  ***   at top-level: teich()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: teich(x) ===> teichmuller(x)
+
+teichmuller(x): teichmuller character of p-adic number x.
+
+
+  ***   at top-level: threetotwo()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+This function no longer exists
+
+
+  ***   at top-level: threetotwo2()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+This function no longer exists
+
+
+  ***   at top-level: torsell()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: torsell(e) ===> elltors(e)
+
+elltors(E): torsion subgroup of elliptic curve E: order, structure, generators.
+
+
+  ***   at top-level: trans()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: trans(x) ===> mattranspose(x)
+
+mattranspose(x): x~ = transpose of x.
+
+
+  ***   at top-level: trunc()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: trunc(x) ===> truncate(x)
+
+truncate(x,{&e}): truncation of x; when x is a power series,take away the 
+O(X^). If e is present, do not take into account loss of integer part 
+precision, and set e = error estimate in bits.
+
+
+  ***   at top-level: tschirnhaus()
+  ***                 ^-------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: tschirnhaus(x) ===> poltschirnhaus(x)
+
+poltschirnhaus(x): random Tschirnhausen transformation of the polynomial x.
+
+
+  ***   at top-level: twototwo()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+This function no longer exists
+
+
+  ***   at top-level: unit()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: unit(x) ===> quadunit(x)
+
+quadunit(D): fundamental unit of the quadratic field of discriminant D where D 
+must be positive.
+
+
+  ***   at top-level: vec()
+  ***                 ^-----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: vec(x) ===> Vec(x)
+
+Vec(x, {n}): transforms the object x into a vector of dimension n.
+
+
+  ***   at top-level: vecindexsort()
+  ***                 ^--------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: vecindexsort(x) ===> vecsort(x,,1)
+
+vecsort(x,{cmpf},{flag=0}): sorts the vector of vectors (or matrix) x in 
+ascending order, according to the comparison function cmpf, if not omitted. (If 
+cmpf is an integer, sort according to the value of the k-th component of each 
+entry.) Binary digits of flag (if present) mean: 1: indirect sorting, return 
+the permutation instead of the permuted vector, 2: sort using lexicographic 
+order, 4: use descending instead of ascending order, 8: remove duplicate 
+entries.
+
+
+  ***   at top-level: veclexsort()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: veclexsort(x) ===> vecsort(x,,2)
+
+vecsort(x,{cmpf},{flag=0}): sorts the vector of vectors (or matrix) x in 
+ascending order, according to the comparison function cmpf, if not omitted. (If 
+cmpf is an integer, sort according to the value of the k-th component of each 
+entry.) Binary digits of flag (if present) mean: 1: indirect sorting, return 
+the permutation instead of the permuted vector, 2: sort using lexicographic 
+order, 4: use descending instead of ascending order, 8: remove duplicate 
+entries.
+
+
+  ***   at top-level: vvector()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: vvector(n,X,expr) ===> vectorv(n,X,expr)
+
+vectorv(n,{X},{expr=0}): column vector with n components of expression expr (X 
+ranges from 1 to n). By default, fill with 0s.
+
+
+  ***   at top-level: weipell()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: weipell(e) ===> ellwp(e)
+
+ellwp(w,{z='x},{flag=0}): computes the value at z of the Weierstrass P function 
+attached to the lattice w, as given by ellperiods. Optional flag means 0 
+(default), compute only P(z), 1 compute [P(z),P'(z)].
+
+
+  ***   at top-level: wf()
+  ***                 ^----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: wf(x) ===> weber(x)
+
+weber(x,{flag=0}): One of Weber's f function of x. flag is optional, and can be 
+0: default, function f(x)=exp(-i*Pi/24)*eta((x+1)/2)/eta(x), 1: function 
+f1(x)=eta(x/2)/eta(x) 2: function f2(x)=sqrt(2)*eta(2*x)/eta(x). Note that j = 
+(f^24-16)^3/f^24 = (f1^24+16)^3/f1^24 = (f2^24+16)^3/f2^24.
+
+
+  ***   at top-level: wf2()
+  ***                 ^-----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: wf2(x) ===> weber(x,2)
+
+weber(x,{flag=0}): One of Weber's f function of x. flag is optional, and can be 
+0: default, function f(x)=exp(-i*Pi/24)*eta((x+1)/2)/eta(x), 1: function 
+f1(x)=eta(x/2)/eta(x) 2: function f2(x)=sqrt(2)*eta(2*x)/eta(x). Note that j = 
+(f^24-16)^3/f^24 = (f1^24+16)^3/f1^24 = (f2^24+16)^3/f2^24.
+
+
+  ***   at top-level: zell()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: zell(e,P) ===> ellpointtoz(e,P)
+
+ellpointtoz(E,P): lattice point z corresponding to the point P on the elliptic 
+curve E.
+
+
+  ***   at top-level: zideallog()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: zideallog(nf,x,bid) ===> ideallog(nf,x,bid)
+
+ideallog(nf,x,bid): if bid is a big ideal, as given by idealstar(nf,I,1) or 
+idealstar(nf,I,2), gives the vector of exponents on the generators bid[2][3] 
+(even if these generators have not been computed).
+
+
+  ***   at top-level: zidealstar()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: zidealstar(nf,I) ===> idealstar(nf,I)
+
+idealstar(nf,I,{flag=1}): gives the structure of (Z_K/I)^*. flag is optional, 
+and can be 0: simply gives the structure as a 3-component vector v such that 
+v[1] is the order (i.e. eulerphi(I)), v[2] is a vector of cyclic components, 
+and v[3] is a vector giving the corresponding generators. If flag=1 (default), 
+gives idealstarinit, i.e. a 6-component vector [I,v,fa,f2,U,V] where v is as 
+above without the generators, fa is the prime ideal factorisation of I and f2, 
+U and V are technical but essential to work in (Z_K/I)^*. Finally if flag=2, 
+same as with flag=1 except that the generators are also given.
+
+
+  ***   at top-level: zidealstarinit()
+  ***                 ^----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: zidealstarinit(nf,id) ===> idealstar(nf,id,1)
+
+idealstar(nf,I,{flag=1}): gives the structure of (Z_K/I)^*. flag is optional, 
+and can be 0: simply gives the structure as a 3-component vector v such that 
+v[1] is the order (i.e. eulerphi(I)), v[2] is a vector of cyclic components, 
+and v[3] is a vector giving the corresponding generators. If flag=1 (default), 
+gives idealstarinit, i.e. a 6-component vector [I,v,fa,f2,U,V] where v is as 
+above without the generators, fa is the prime ideal factorisation of I and f2, 
+U and V are technical but essential to work in (Z_K/I)^*. Finally if flag=2, 
+same as with flag=1 except that the generators are also given.
+
+
+  ***   at top-level: zidealstarinitgen()
+  ***                 ^-------------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: zidealstarinitgen(nf,id) ===> idealstar(nf,id,2)
+
+idealstar(nf,I,{flag=1}): gives the structure of (Z_K/I)^*. flag is optional, 
+and can be 0: simply gives the structure as a 3-component vector v such that 
+v[1] is the order (i.e. eulerphi(I)), v[2] is a vector of cyclic components, 
+and v[3] is a vector giving the corresponding generators. If flag=1 (default), 
+gives idealstarinit, i.e. a 6-component vector [I,v,fa,f2,U,V] where v is as 
+above without the generators, fa is the prime ideal factorisation of I and f2, 
+U and V are technical but essential to work in (Z_K/I)^*. Finally if flag=2, 
+same as with flag=1 except that the generators are also given.
+
+
+  ***   at top-level: box()
+  ***                 ^-----
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: box(x,a) ===> plotbox(x,a)
+
+plotbox(w,x2,y2): if the cursor is at position (x1,y1), draw a box with 
+diagonal (x1,y1) and (x2,y2) in rectwindow w (cursor does not move).
+
+
+  ***   at top-level: color()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: color(w,c) ===> plotcolor(w,c)
+
+plotcolor(w,c): in rectwindow w, set default color to c. Possible values for c 
+are given by the graphcolormap default: factory settings are 1=black, 2=blue, 
+3=sienna, 4=red, 5=green, 6=grey, 7=gainsborough.
+
+
+  ***   at top-level: cursor()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: cursor(w) ===> plotcursor(w)
+
+plotcursor(w): current position of cursor in rectwindow w.
+
+
+  ***   at top-level: draw()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: draw(list) ===> plotdraw(list)
+
+plotdraw(list, {flag=0}): draw vector of rectwindows list at indicated x,y 
+positions; list is a vector w1,x1,y1,w2,x2,y2,etc. If flag!=0, x1, y1 etc. 
+express fractions of the size of the current output device.
+
+
+  ***   at top-level: initrect()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: initrect(w,x,y) ===> plotinit(w,x,y)
+
+plotinit(w,{x},{y},{flag=0}): initialize rectwindow w to size x,y. If flag!=0, 
+x and y express fractions of the size of the current output device. Omitting x 
+or y means use the full size of the device.
+
+
+  ***   at top-level: killrect()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: killrect(w) ===> plotkill(w)
+
+plotkill(w): erase the rectwindow w.
+
+
+  ***   at top-level: line()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: line(w,x2,y2) ===> plotlines(w,x2,y2)
+
+plotlines(w,X,Y,{flag=0}): draws an open polygon in rectwindow w where X and Y 
+contain the x (resp. y) coordinates of the vertices. If X and Y are both single 
+values (i.e not vectors), draw the corresponding line (and move cursor). If 
+(optional) flag is non-zero, close the polygon.
+
+
+  ***   at top-level: lines()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: lines(w,x2,y2) ===> plotlines(w,x2,y2)
+
+plotlines(w,X,Y,{flag=0}): draws an open polygon in rectwindow w where X and Y 
+contain the x (resp. y) coordinates of the vertices. If X and Y are both single 
+values (i.e not vectors), draw the corresponding line (and move cursor). If 
+(optional) flag is non-zero, close the polygon.
+
+
+  ***   at top-level: move()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: move(w,x,y) ===> plotmove(w,x,y)
+
+plotmove(w,x,y): move cursor to position x,y in rectwindow w.
+
+
+  ***   at top-level: ploth2()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: ploth2(X=a,b,expr) ===> ploth(X=a,b,expr,1)
+
+ploth(X=a,b,expr,{flags=0},{n=0}): plot of expression expr, X goes from a to b 
+in high resolution. Both flags and n are optional. Binary digits of flags mean: 
+1=Parametric, 2=Recursive, 4=no_Rescale, 8=no_X_axis, 16=no_Y_axis, 
+32=no_Frame, 64=no_Lines (do not join points), 128=Points_too (plot both lines 
+and points), 256=Splines (use cubic splines), 512=no_X_ticks, 1024= no_Y_ticks, 
+2048=Same_ticks (plot all ticks with the same length), 4096=Complex (the two 
+coordinates of each point are encoded as a complex number). n specifies number 
+of reference points on the graph (0=use default value). Returns a vector for 
+the bounding box.
+
+
+  ***   at top-level: plothmult()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: plothmult(X=a,b,expr) ===> ploth(X=a,b,expr)
+
+ploth(X=a,b,expr,{flags=0},{n=0}): plot of expression expr, X goes from a to b 
+in high resolution. Both flags and n are optional. Binary digits of flags mean: 
+1=Parametric, 2=Recursive, 4=no_Rescale, 8=no_X_axis, 16=no_Y_axis, 
+32=no_Frame, 64=no_Lines (do not join points), 128=Points_too (plot both lines 
+and points), 256=Splines (use cubic splines), 512=no_X_ticks, 1024= no_Y_ticks, 
+2048=Same_ticks (plot all ticks with the same length), 4096=Complex (the two 
+coordinates of each point are encoded as a complex number). n specifies number 
+of reference points on the graph (0=use default value). Returns a vector for 
+the bounding box.
+
+
+  ***   at top-level: point()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: point(w,x,y) ===> plotpoints(w,x,y)
+
+plotpoints(w,X,Y): draws in rectwindow w the points whose x (resp y) 
+coordinates are in X (resp Y). If X and Y are both single values (i.e not 
+vectors), draw the corresponding point (and move cursor).
+
+
+  ***   at top-level: points()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: points(w,x,y) ===> plotpoints(w,x,y)
+
+plotpoints(w,X,Y): draws in rectwindow w the points whose x (resp y) 
+coordinates are in X (resp Y). If X and Y are both single values (i.e not 
+vectors), draw the corresponding point (and move cursor).
+
+
+  ***   at top-level: postdraw()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: postdraw(list) ===> psdraw(list)
+
+psdraw(list, {flag=0}): same as plotdraw, except that the output is a 
+PostScript program in psfile (pari.ps by default), and flag!=0 scales the plot 
+from size of the current output device to the standard PostScript plotting 
+size.
+
+
+  ***   at top-level: postploth()
+  ***                 ^-----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: postploth(X=a,b,expr) ===> psploth(X=a,b,expr)
+
+psploth(X=a,b,expr,{flags=0},{n=0}): same as ploth, except that the output is a 
+PostScript program in psfile (pari.ps by default).
+
+
+  ***   at top-level: postploth2()
+  ***                 ^------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: postploth2(X=a,b,expr) ===> psploth(X=a,b,expr,1)
+
+psploth(X=a,b,expr,{flags=0},{n=0}): same as ploth, except that the output is a 
+PostScript program in psfile (pari.ps by default).
+
+
+  ***   at top-level: postplothraw()
+  ***                 ^--------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: postplothraw(listx,listy) ===> psplothraw(listx,listy)
+
+psplothraw(listx,listy,{flag=0}): same as plothraw, except that the output is a 
+postscript program in psfile (pari.ps by default).
+
+
+  ***   at top-level: pprint()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+This function no longer exists
+
+
+  ***   at top-level: pprint1()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+This function no longer exists
+
+
+
+  ***   at top-level: rbox()
+  ***                 ^------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: rbox(w,dx,dy) ===> plotrbox(w,dx,dy)
+
+plotrbox(w,dx,dy): if the cursor is at (x1,y1), draw a box with diagonal 
+(x1,y1)-(x1+dx,y1+dy) in rectwindow w (cursor does not move).
+
+
+  ***   at top-level: read()
+  ***                 ^------
+  *** read: You never gave me anything to read!.
+  ***   at top-level: rline()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: rline(w,dx,dy) ===> plotrline(w,dx,dy)
+
+plotrline(w,dx,dy): if the cursor is at (x1,y1), draw a line from (x1,y1) to 
+(x1+dx,y1+dy) (and move the cursor) in the rectwindow w.
+
+
+  ***   at top-level: rlines()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+  ***   at top-level: rlines()
+  ***                 ^--------
+  ***   bug in whatnow, please report.
+  ***   at top-level: rmove()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: rmove(w,dx,dy) ===> plotrmove(w,dx,dy)
+
+plotrmove(w,dx,dy): move cursor to position (dx,dy) relative to the present 
+position in the rectwindow w.
+
+
+  ***   at top-level: rpoint()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: rpoint(w,dx,dy) ===> plotrpoint(w,dx,dy)
+
+plotrpoint(w,dx,dy): draw a point (and move cursor) at position dx,dy relative 
+to present position of the cursor in rectwindow w.
+
+
+  ***   at top-level: rpoints()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+  ***   at top-level: rpoints()
+  ***                 ^---------
+  ***   bug in whatnow, please report.
+  ***   at top-level: scale()
+  ***                 ^-------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: scale(w,x1,x2,y1,y2) ===> plotscale(w,x1,x2,y1,y2)
+
+plotscale(w,x1,x2,y1,y2): scale the coordinates in rectwindow w so that x goes 
+from x1 to x2 and y from y1 to y2 (y2<y1 is allowed).
+
+
+  ***   at top-level: setprecision()
+  ***                 ^--------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: setprecision(n) ===> default(realprecision,n)
+
+default({key},{val}): returns the current value of the default key. If val is 
+present, set opt to val first. If no argument is given, print a list of all 
+defaults as well as their values.
+
+
+  ***   at top-level: setserieslength()
+  ***                 ^-----------------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: setserieslength(n) ===> default(seriesprecision,n)
+
+default({key},{val}): returns the current value of the default key. If val is 
+present, set opt to val first. If no argument is given, print a list of all 
+defaults as well as their values.
+
+
+  ***   at top-level: settype()
+  ***                 ^---------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: settype(x,t) ===> type(x,t)
+
+type(x): return the type of the GEN x.
+
+
+  ***   at top-level: string()
+  ***                 ^--------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: string(w,x) ===> plotstring(w,x)
+
+plotstring(w,x,{flags=0}): draw in rectwindow w the string corresponding to x. 
+Bits 1 and 2 of flag regulate horizontal alignment: left if 0, right if 2, 
+center if 1. Bits 4 and 8 regulate vertical alignment: bottom if 0, top if 8, 
+v-center if 4. Can insert additional gap between point and string: horizontal 
+if bit 16 is set, vertical if bit 32 is set.
+
+
+  ***   at top-level: texprint()
+  ***                 ^----------
+  ***   not a function in function call
+A function with that name existed in GP-1.39.15. Please update your script.
+
+New syntax: texprint(x) ===> printtex(x)
+
+printtex({str}*): outputs its string arguments in TeX format.
+
+
+Total time spent: 23
diff --git a/src/test/32/contfrac b/src/test/32/contfrac
index ad42782..4966d87 100644
--- a/src/test/32/contfrac
+++ b/src/test/32/contfrac
@@ -12,9 +12,9 @@
 [;]
 [;]
 
-[1 2]
+[2 1]
 
-[0 1]
+[1 0]
 
 
 [2]
diff --git a/src/test/32/deriv b/src/test/32/deriv
index 41e625c..a5664d1 100644
--- a/src/test/32/deriv
+++ b/src/test/32/deriv
@@ -1,6 +1,16 @@
 -0.65364362086361191463916818309775038142
+0.83373002513114904888388539433509447981 - 0.9888977057628650963821295408926
+8618864*I
+1 - 1/2*x^2 + 1/24*x^4 - 1/720*x^6 + 1/40320*x^8 - 1/3628800*x^10 + 1/479001
+600*x^12 - 1/87178291200*x^14 + 1/20922789888000*x^16 + O(x^17)
+  ***   at top-level: sin'("")
+  ***                 ^--------
+  ***   in function sin: sin'
+  ***                    ^----
+  *** _derivfun: incorrect type in formal derivation (t_STR).
 -0.65364362086361191463916818309775038142
 1 + O(t^2)
+3.5962749997291581980860017516463603814
 0
 Mod(x, x^2 + 1)
 Mod(x, x^2 + 1)
@@ -50,4 +60,4 @@ O(x)
 O(x)
 x
 x
-Total time spent: 0
+Total time spent: 4
diff --git a/src/test/32/diffop b/src/test/32/diffop
index 85c200a..eb4a09a 100644
--- a/src/test/32/diffop
+++ b/src/test/32/diffop
@@ -5,7 +5,7 @@ Mod(((512*C^8 - 130560*C^6 + 1693440*C^4 - 4838400*C^2 + 3628800)/C^11)*S, S
 q^7 + 1123200*q^8 + 1635120*q^9 + 2721600*q^10 + 3516480*q^11 + 5886720*q^12
  + 6857760*q^13 + 10402560*q^14 + 12700800*q^15 + O(q^16)
 Mod(1, x^2 - y)
-0
+Mod(0, x^2 + y)
 ((Mod(2, 3)*llx + Mod(2, 3))*lx^4 + Mod(1, 3)*lx^2 + Mod(2, 3))/(Mod(1, 3)*l
 lx^2*lx^6*x^6)
 Total time spent: 0
diff --git a/src/test/32/digits b/src/test/32/digits
index 79f78fc..a13ff45 100644
--- a/src/test/32/digits
+++ b/src/test/32/digits
@@ -1,8 +1,11 @@
 []
 []
+0
 [7, 8, 8, 8, 6, 0, 9, 0, 5, 2, 2, 1, 0, 1, 1, 8, 0, 5, 4, 1, 1, 7, 2, 8, 5, 
 6, 5, 2, 8, 2, 7, 8, 6, 2, 2, 9, 6, 7, 3, 2, 0, 6, 4, 3, 5, 1, 0, 9, 0, 2, 3
 , 0, 0, 4, 7, 7, 0, 2, 7, 8, 9, 3, 0, 6, 6, 4, 0, 6, 2, 5]
+1234560123456012345601234560123456012345601234560123456012345601234560123456
+012345601234560123456012
 0
 12
 135
@@ -29,4 +32,7 @@
   ***   at top-level: binary(I)
   ***                 ^---------
   *** binary: incorrect type in binary (t_COMPLEX).
-Total time spent: 112
+[16, 21, 21, 21, 19, 27, 43, 45, 45, 39]
+[1, 0, 3]
+4
+Total time spent: 68
diff --git a/src/test/32/dirmul b/src/test/32/dirmul
index 78720ec..8c88eec 100644
--- a/src/test/32/dirmul
+++ b/src/test/32/dirmul
@@ -4,4 +4,28 @@
 [1, 4, 6, 12]
 [1, 0, 0, 0]
 [1/2, 0, 0, 0]
-Total time spent: 8
+[1, 3, 4, 7, 6, 12, 8, 15, 13, 18]
+[]
+[1]
+[1, 3]
+[1, 3, 4]
+[1, 0, 0, 1, 0, 0, 0, 0, 1, 0]
+[1, 1, 1, 0, 1, 1, 1, 1, 0, 1]
+  ***   at top-level: direuler(p=I,10.5,1/((1-X)*(1-p*X)))
+  ***                                   ^------------------
+  ***   incorrect type in gceil (t_COMPLEX).
+  ***   at top-level: direuler(p=2.5,I,1/((1-X)*(1-p*X)))
+  ***                                  ^------------------
+  ***   incorrect type in gfloor (t_COMPLEX).
+  ***   at top-level: direuler(p=2,10,1/((1-X)*(1-p*X)),I)
+  ***                                 ^--------------------
+  ***   incorrect type in gfloor (t_COMPLEX).
+[1]
+[1, 3]
+  ***   at top-level: direuler(p=2,10,1/2)
+  ***                                 ^----
+  ***   domain error in direuler: constant term != 1
+  ***   at top-level: direuler(p=2,10,1/(x-2))
+  ***                                 ^--------
+  ***   domain error in direuler: constant term != 1
+Total time spent: 1
diff --git a/src/test/32/div b/src/test/32/div
index 30fcb20..cc46869 100644
--- a/src/test/32/div
+++ b/src/test/32/div
@@ -297,7 +297,7 @@ error("forbidden division t_FRAC \\ t_INTMOD.")
 1
 [1, 0]~
 * [5, 6]
-0
+Mod(0, x^2 + 1)
 error("forbidden euclidean division t_POL , t_POLMOD.")
 error("forbidden euclidean division t_POL , t_POLMOD.")
 error("forbidden euclidean division t_POL , t_POLMOD.")
@@ -335,13 +335,13 @@ Mod(2, 3)*x^2 + Mod(2, 3)
 * [6, 1]
 Mod(1/3*x, x^2 + 1)
 error("forbidden division t_POLMOD \\ t_INT.")
-0
+Mod(0, x^2 + 1)
 error("forbidden division t_POLMOD \\ t_INT.")
 error("forbidden division t_POLMOD \\ t_INT.")
 * [6, 2]
 Mod(1/4*x, x^2 + 1)
 error("forbidden division t_POLMOD \\ t_INT.")
-0
+Mod(0, x^2 + 1)
 error("forbidden division t_POLMOD \\ t_INT.")
 error("forbidden division t_POLMOD \\ t_INT.")
 * [6, 3]
@@ -357,7 +357,7 @@ error("forbidden division t_POLMOD % t_FRAC.")
 error("incorrect type in gfloor (t_POLMOD).")
 error("incorrect type in gfloor (t_POLMOD).")
 * [6, 5]
-error("impossible inverse in RgXQ_inv: 0.")
+error("impossible inverse in RgXQ_inv: Mod(0, x^2 + 1).")
 error("forbidden euclidean division t_POLMOD , t_POL.")
 Mod(x, x^2 + 1)
 error("forbidden euclidean division t_POLMOD , t_POL.")
@@ -907,4 +907,10 @@ Mat(1)
   *** divrem: forbidden division t_INT \ t_STR.
 2
 x
-Total time spent: 0
+[]
+[]~
+[;]
+  ***   at top-level: [1]/0
+  ***                    ^--
+  *** _/_: impossible inverse in gdiv: 0.
+Total time spent: 4
diff --git a/src/test/32/ell b/src/test/32/ell
index f0e6ab0..0e9fb1b 100644
--- a/src/test/32/ell
+++ b/src/test/32/ell
@@ -63,11 +63,6 @@
 1
 1023
 494
-[4, [2, 2], [[-2147484185, 0], [0, 0]]]
-2
-2
-0
-0
 0
 1728
 j
@@ -81,6 +76,48 @@ a
 a
 8*x^9 + 54*x^8 + 393*x^7 + 2373*x^6 + 6993*x^5 + 15267*x^4 + 19998*x^3 + 473
 4*x^2 - 25880*x - 30932
+[0, 0]
+[x, 1]
+[x^4 - 13*x^2 - 74*x - 41, 4*x^3 + 9*x^2 + 26*x + 37]
+[x^16 - 260*x^14 - 5968*x^13 - 39963*x^12 - 140444*x^11 - 195486*x^10 + 5215
+64*x^9 + 5378114*x^8 + 23699984*x^7 + 74549288*x^6 + 183951360*x^5 + 3366091
+54*x^4 + 444753656*x^3 + 432135644*x^2 + 255731272*x + 49749605, 16*x^15 + 1
+80*x^14 + 1792*x^13 + 14753*x^12 + 84148*x^11 + 414370*x^10 + 1658348*x^9 + 
+4652985*x^8 + 9212312*x^7 + 10904612*x^6 + 434120*x^5 - 24648228*x^4 - 39304
+176*x^3 - 13741184*x^2 + 25100064*x + 25859152]
+[x^25 - 650*x^23 - 23335*x^22 - 259290*x^21 - 1456154*x^20 - 2820445*x^19 + 
+20761370*x^18 + 277111495*x^17 + 2007242185*x^16 + 11282671667*x^15 + 529194
+54495*x^14 + 207385350880*x^13 + 677127946605*x^12 + 1857857835015*x^11 + 43
+12300313262*x^10 + 8526087679330*x^9 + 14394585463670*x^8 + 20512909438825*x
+^7 + 23836827014955*x^6 + 20324637565929*x^5 + 7866409553255*x^4 - 796635515
+1205*x^3 - 15373355872840*x^2 - 10304273387855*x - 2425203075812, 25*x^24 + 
+450*x^23 + 6865*x^22 + 90410*x^21 + 848806*x^20 + 6747580*x^19 + 45352495*x^
+18 + 229321140*x^17 + 838958290*x^16 + 2007441886*x^15 + 1506282910*x^14 - 1
+1941908510*x^13 - 67097680775*x^12 - 197749423840*x^11 - 360107712461*x^10 -
+ 248110872190*x^9 + 863441551840*x^8 + 3852505140470*x^7 + 8796991424540*x^6
+ + 14201708642530*x^5 + 17446507273700*x^4 + 16338035413000*x^3 + 1142822256
+7925*x^2 + 5633997157650*x + 1472351694025]
+[0]
+[-23338430276487649199700397847721116081702650343430925719105465344187224269
+2167848859501069746367317057135733659821516586965453870026354744714986684965
+8323996212283434950398700511439/21452304628477972409549628569820513272484339
+3023834534814913254065684077308619895779034479691808535960623339165042624323
+5345631919723231687684699452030828176986716708998958804636224, -892721634620
+8423324340896231392069270729522715981007828685033969863523382353428674866926
+4734542739355918998020644016664732197288414787069129806148688960193235312780
+7158822883693587635120259554260938849967680317634128924102700969620674883736
+9307779952513049787052947107461/31420343828112469950094830391399473730286380
+5713026983524763427660191121031569408909200906270720147570836507805210795709
+8988916304745235223129078126602318052803199405011168522054272192266092941904
+104143227672460543588095008724194999641591292020853488313837016518733957632]
+[-1, 1]
+[-1, -3]
+[833245230963211172586751702962398963656841653/30025043966406435914574252820
+2802293592821136, -572865877831905829779071583256995923720966703129995025914
+40045201397/5202660393781989115440421988056492168066969880055771334597510887
+616]
+[-10325327/6270016, -17317169781/15700120064]
+[-10325327/6270016, -17317169781/15700120064]
 16*x^33 + 20048*x^30 - 524864*x^27 - 20273280*x^24 - 35051520*x^21 - 1832755
 20*x^18 - 818626560*x^15 - 1017937920*x^12 - 390856704*x^9 + 74973184*x^6 + 
 102760448*x^3 + 4194304
@@ -107,7 +144,7 @@ a
 all([1]), [Vecsmall([128, -1])], [0, 0, 0, 0, 0, 0, 0, [[2, 3]~]]]
 [1/30, -13/150, -1/10, -79/500]
 1
-[36, [36], [[a^2 + 1, a^3 + a^2 + a + 1]]]
+[36, [36], [[a^4 + a^3 + a^2, a^2]]]
 1
 [3, [3], [[0, 2]]]
 1
@@ -122,14 +159,14 @@ all([1]), [Vecsmall([128, -1])], [0, 0, 0, 0, 0, 0, 0, [[2, 3]~]]]
  + 1 + 2*3 + 3^2 + 3^4 + 2*3^5 + O(3^6), 3^-2 + 3^-1 + 2 + 3 + 2*3^2 + 2*3^3
  + 3^4 + 3^5 + O(3^6)]]
 error("incorrect type in obj_check (t_VEC).")
-[2 + 2^6 + 2^10 + O(2^11), Mod(u, u^2 + (2 + 2^2 + 2^3 + 2^4 + 2^5 + 2^7 + 2
+[2 + 2^6 + 2^10 + O(2^11), Mod(x, x^2 + (2 + 2^2 + 2^3 + 2^4 + 2^5 + 2^7 + 2
 ^8 + 2^9 + O(2^11))), 2^3 + 2^4 + O(2^8), [2^-3 + 2^2 + 2^4 + 2^7 + 2^10 + O
 (2^11), 2^-3 + 2^2 + 2^5 + 2^6 + 2^10 + O(2^13)]]
 x^-2 + 31/15*x^2 + 2501/756*x^4 + 961/675*x^6 + 77531/41580*x^8 + O(x^9)
 [-1, -2*w]
-[I, 1]
-[[I, 1], [-3.1415926535897932384626433832795028842*I, 3.14159265358979323846
-26433832795028842]]
+[-1, 1/2*I]
+[[-1, 1/2*I], [0.59200051084078635056480901325155142952, -6.5791855625999796
+522076912731847814832*I]]
 [1, 1]
 x^-2 - 1/5*x^2 - 1/7*x^4 + 1/75*x^6 + 3/385*x^8 + 277/238875*x^10 - 2/5775*x
 ^12 + O(x^14)
@@ -139,25 +176,27 @@ x^-2 - 1/5*x^2 - 1/7*x^4 + 1/75*x^6 + O(x^7)
 0.0070737179180847219897019688523688143761 - 4.54459013280902760664280136539
 71181201*I
 [1, 2]
-x^-2 + 9.4536360064616926146530698267460656697*x^2 + 6.577345622 E-37*x^4 + 
-29.790411247556326629130082765180921498*x^6 + 1.695813583 E-36*x^8 + 43.3273
-39141107674122263886023453990048*x^10 + 3.562578744 E-36*x^12 + O(x^14)
-x^-2 + 9.4536360064616926146530698267460656697*x^2 + 6.577345622 E-37*x^4 + 
-29.790411247556326629130082765180921498*x^6 + O(x^7)
-10.092015307351769584764433105625607145
--10.092015307351769584764433105625607145
-3.2557987470773994635555990212606293690 E-38 - 2.704147351607435273075740713
-3303875089*I
+x^-2 + 103.98999607107861876118376809420672237*x^2 - 649.9550420035218272005
+1926719405777425*x^4 + 3604.6397609543155221247400145868915015*x^6 - 18433.3
+15162997447301537872827568145124*x^8 + 90164.1927526450698484311468148077532
+96*x^10 - 425973.41586156854974946172781042993149*x^12 + O(x^14)
+x^-2 + 103.98999607107861876118376809420672237*x^2 - 649.9550420035218272005
+1926719405777425*x^4 + 3604.6397609543155221247400145868915015*x^6 + O(x^7)
+15.663727422159594482268754503777038256
+-39.480069718736152480166362703315829534
+11.908171148288278998948804099769395642 + 1.97957325252946376553721096563444
+46755*I
 [1, 3]
-x^-2 + 9.4536360064616926146530698267460656697*x^2 + 6.577345622 E-37*x^4 + 
-29.790411247556326629130082765180921498*x^6 + 1.695813583 E-36*x^8 + 43.3273
-39141107674122263886023453990048*x^10 + 3.562578744 E-36*x^12 + O(x^14)
-x^-2 + 9.4536360064616926146530698267460656697*x^2 + 6.577345622 E-37*x^4 + 
-29.790411247556326629130082765180921498*x^6 + O(x^7)
-10.092015307351769584764433105625607145
--10.092015307351769584764433105625607145
-3.2557987470773994635555990212606293690 E-38 - 2.704147351607435273075740713
-3303875089*I
+x^-2 + 103.98999607107861876118376809420672237*x^2 - 649.9550420035218272005
+1926719405777425*x^4 + 3604.6397609543155221247400145868915015*x^6 - 18433.3
+15162997447301537872827568145124*x^8 + 90164.1927526450698484311468148077532
+96*x^10 - 425973.41586156854974946172781042993149*x^12 + O(x^14)
+x^-2 + 103.98999607107861876118376809420672237*x^2 - 649.9550420035218272005
+1926719405777425*x^4 + 3604.6397609543155221247400145868915015*x^6 + O(x^7)
+15.663727422159594482268754503777038256
+-39.480069718736152480166362703315829534
+11.908171148288278998948804099769395642 + 1.97957325252946376553721096563444
+46755*I
 [2, 1]
 x^-1 + 1/15*x^3 + 1/35*x^5 - 1/525*x^7 - 1/1155*x^9 - 277/2627625*x^11 + 2/7
 5075*x^13 + O(x^15)
@@ -167,25 +206,27 @@ x^-1 + 1/15*x^3 + 1/35*x^5 - 1/525*x^7 + O(x^8)
 1.4945837634650773441141478432745008118 - 1.49552579635851441107083905597206
 14467*I
 [2, 2]
-x^-1 - 3.1512120021538975382176899422486885566*x^3 - 1.315469124 E-37*x^5 - 
-4.2557730353651895184471546807401316426*x^7 - 1.884237315 E-37*x^9 - 3.93884
-90128279703747512623657685445499*x^11 - 2.740445188 E-37*x^13 + O(x^15)
-x^-1 - 3.1512120021538975382176899422486885566*x^3 - 1.315469124 E-37*x^5 - 
-4.2557730353651895184471546807401316426*x^7 + O(x^8)
-2.8609969154308155967482927187353233603
--2.8813199850735158607638401394492232764*I
-1.7185329556464940714815988649194112975 - 1.71853295564649407148159886491941
-12976*I
+x^-1 - 34.663332023692872920394589364735574123*x^3 + 129.9910084007043654401
+0385343881155485*x^5 - 514.94853727918793173210571636955592878*x^7 + 2048.14
+61292219385890597636475075716805*x^9 - 8196.74479569500634985737698316434120
+88*x^11 + 32767.185835505273057650902139263840884*x^13 + O(x^15)
+x^-1 - 34.663332023692872920394589364735574123*x^3 + 129.9910084007043654401
+0385343881155485*x^5 - 514.94853727918793173210571636955592878*x^7 + O(x^8)
+2.0876703200272312306836757817491311900
+0
+1.8018229730105461594800210664505892466 - 4.22108966565276293974646245627813
+69159*I
 [2, 3]
-x^-1 - 3.1512120021538975382176899422486885566*x^3 - 1.315469124 E-37*x^5 - 
-4.2557730353651895184471546807401316426*x^7 - 1.884237315 E-37*x^9 - 3.93884
-90128279703747512623657685445499*x^11 - 2.740445188 E-37*x^13 + O(x^15)
-x^-1 - 3.1512120021538975382176899422486885566*x^3 - 1.315469124 E-37*x^5 - 
-4.2557730353651895184471546807401316426*x^7 + O(x^8)
-2.8609969154308155967482927187353233603
--2.8813199850735158607638401394492232764*I
-1.7185329556464940714815988649194112975 - 1.71853295564649407148159886491941
-12976*I
+x^-1 - 34.663332023692872920394589364735574123*x^3 + 129.9910084007043654401
+0385343881155485*x^5 - 514.94853727918793173210571636955592878*x^7 + 2048.14
+61292219385890597636475075716805*x^9 - 8196.74479569500634985737698316434120
+88*x^11 + 32767.185835505273057650902139263840884*x^13 + O(x^15)
+x^-1 - 34.663332023692872920394589364735574123*x^3 + 129.9910084007043654401
+0385343881155485*x^5 - 514.94853727918793173210571636955592878*x^7 + O(x^8)
+2.0876703200272312306836757817491311900
+0
+1.8018229730105461594800210664505892466 - 4.22108966565276293974646245627813
+69159*I
 [3, 1]
 x + 1/60*x^5 + 1/210*x^7 - 1/10080*x^9 - 1/138600*x^11 - 167/259459200*x^13 
 - 19/1513512000*x^15 + O(x^17)
@@ -195,25 +236,27 @@ x + 1/60*x^5 + 1/210*x^7 - 1/10080*x^9 + O(x^10)
 0.33307632454406929865753194192439552171 + 0.3330414840427217068846417452694
 8964209*I
 [3, 2]
-x - 0.78780300053847438455442248556217213914*x^5 - 2.192448541 E-38*x^7 - 0.
-22165484559193695408578930628854852305*x^9 - 1.570197765 E-39*x^11 + 0.00936
-19303173614540570518182056750707483*x^13 + 1.291380487 E-40*x^15 + O(x^17)
-x - 0.78780300053847438455442248556217213914*x^5 - 2.192448541 E-38*x^7 - 0.
-22165484559193695408578930628854852305*x^9 + O(x^10)
-0.33008009031657824359527653587336069208
-0.33008009031657824359527653587336069208*I
-0.34612072856429482856153662202577445445 + 0.3461207285642948285615366220257
-7445446*I
+x - 8.6658330059232182300986473411838935307*x^5 + 21.66516806678406090668397
+5573135259142*x^7 - 26.820236316624371444380506060914371291*x^9 + 17.0678844
+10182821575498030395896430672*x^11 + 0.9724196316598484235781214649285975622
+3*x^13 - 15.440886182405758633317637416815798050*x^15 + O(x^17)
+x - 8.6658330059232182300986473411838935307*x^5 + 21.66516806678406090668397
+5573135259142*x^7 - 26.820236316624371444380506060914371291*x^9 + O(x^10)
+0.30631122697380979289268115078987850649
+0.E-38
+0.53021646242894349905972369056429285872 + 0.3781418838145237834855647058271
+9409288*I
 [3, 3]
-x - 0.78780300053847438455442248556217213914*x^5 - 2.192448541 E-38*x^7 - 0.
-22165484559193695408578930628854852305*x^9 - 1.570197765 E-39*x^11 + 0.00936
-19303173614540570518182056750707483*x^13 + 1.291380487 E-40*x^15 + O(x^17)
-x - 0.78780300053847438455442248556217213914*x^5 - 2.192448541 E-38*x^7 - 0.
-22165484559193695408578930628854852305*x^9 + O(x^10)
-0.33008009031657824359527653587336069208
-0.33008009031657824359527653587336069208*I
-0.34612072856429482856153662202577445445 + 0.3461207285642948285615366220257
-7445446*I
+x - 8.6658330059232182300986473411838935307*x^5 + 21.66516806678406090668397
+5573135259142*x^7 - 26.820236316624371444380506060914371291*x^9 + 17.0678844
+10182821575498030395896430672*x^11 + 0.9724196316598484235781214649285975622
+3*x^13 - 15.440886182405758633317637416815798050*x^15 + O(x^17)
+x - 8.6658330059232182300986473411838935307*x^5 + 21.66516806678406090668397
+5573135259142*x^7 - 26.820236316624371444380506060914371291*x^9 + O(x^10)
+0.30631122697380979289268115078987850649
+0.E-38
+0.53021646242894349905972369056429285872 + 0.3781418838145237834855647058271
+9409288*I
 [4, 1]
 0
 0
@@ -225,19 +268,17 @@ x - 0.78780300053847438455442248556217213914*x^5 - 2.192448541 E-38*x^7 - 0.
 [4, 2]
 0
 0
--1.1084199560389642415209208807828823872
--1.1084199560389642415209208807828823872 + 1.5707963267948966192313216916397
-514421*I
--0.71439404801872849905771074604935970853 + 0.785398163397448309615660845819
-87572105*I
+-1.1831536122930622250712755356827420688
+-1.2506870224867757820652851907990498543
+-0.42886850134944751864186009377385060418 + 0.619519575104929600932212172490
+11490053*I
 [4, 3]
 0
 0
--1.1084199560389642415209208807828823872
--1.1084199560389642415209208807828823872 + 1.5707963267948966192313216916397
-514421*I
--0.71439404801872849905771074604935970853 + 0.785398163397448309615660845819
-87572105*I
+-1.1831536122930622250712755356827420688
+-1.2506870224867757820652851907990498543
+-0.42886850134944751864186009377385060418 + 0.619519575104929600932212172490
+11490053*I
 [2.5135797437238231405782694715779164652, 1.25678987186191157028913473578895
 82326 + 0.78959476569186174055147277865716603189*I]
 [3.1415926535897932384626433832795028842, 9.42477796076937971538793014983850
@@ -245,49 +286,33 @@ x - 0.78780300053847438455442248556217213914*x^5 - 2.192448541 E-38*x^7 - 0.
 (x)->elleisnum(x,2)
 -2.9936282668967606065680548947245432597 - 7.1637767384648910133063235008836
 078048*I
--37.699111843077518861551720599354034610
--37.699111843077518861551720599354034610
-(x)->elleisnum(x,4,1)
--3.9999999999999999999999999999999999999 - 5.48564030 E-38*I
-189.07272012923385229306139653492131339
-189.07272012923385229306139653492131339
-(x)->elleisnum(x,6,1)
--4.0000000000000000000000000000000000000 - 1.253860641 E-37*I
-1.841656774 E-35
-1.841656774 E-35
-(x)->elleisnum(x,10)
--41471.999999999999999999999999999999998 - 7.70371978 E-34*I
--2.818118420 E-30
--2.818118420 E-30
+157.90045350239951165298459055643475560
+157.90045350239951165298459055643475560
+(x)->real(elleisnum(x,4,1))
+-3.9999999999999999999999999999999999999
+2079.7999214215723752236753618841344474
+2079.7999214215723752236753618841344474
+(x)->real(elleisnum(x,6,1))
+-4.0000000000000000000000000000000000000
+-18198.741176098611161614539481433617679
+-18198.741176098611161614539481433617679
+(x)->real(elleisnum(x,10))
+-41471.999999999999999999999999999999998
+98106527293.111533926136928277796284706
+98106527293.111533926136928277796284706
 -1
 [0]
 347813742467679407541/38941611811810745401
-[1, [], []]
-[2, [2], [[15, -8]]]
-[3, [3], [[5, 9]]]
-[4, [4], [[5, -2]]]
-[5, [5], [[5, 5]]]
-[6, [6], [[9, 23]]]
-[7, [7], [[-1, 2]]]
-[8, [8], [[2, 6]]]
-[9, [9], [[-3, 7]]]
-[10, [10], [[0, 9]]]
-[12, [12], [[-9, 49]]]
-[4, [2, 2], [[-29/4, 25/8], [-7, 3]]]
-[8, [4, 2], [[-2, 3], [-1, 0]]]
-[12, [6, 2], [[1, 2], [3, -2]]]
-[16, [8, 2], [[4, 58], [-36, 18]]]
-[16, [8, 2], [[117433600, 6734213027200], [352179456, -176089728]]]
-[4, [2, 2], [[-1377493124511464657, 0], [-691668349248679055, 0]]]
-[0.49999999999999999999999999999999999978 - 2.057115114 E-38*I, 1.9216402159
-513147090074725264936203858 + 0.26019438802828824617801390769760176484*I]
+[0.49999999999999999999999999999999999982 + 0.999999999999999999999999999999
+99999992*I, 1.5617041082089070087003342842479112066 + 0.56028539298876740518
+391807553710802962*I]
 3 + 11^2 + 2*11^3 + 3*11^4 + O(11^5)
-Mod((2 + 3 + O(3^4))*u + (2*3 + 3^2 + O(3^4)), u^2 + (1 + 3 + 2*3^4 + 3^8 + 
+Mod((2 + 3 + O(3^4))*x + (2*3 + 3^2 + O(3^4)), x^2 + (1 + 3 + 2*3^4 + 3^8 + 
 2*3^9 + O(3^10)))
-Mod((1 + 3 + 3^3 + 3^4 + 2*3^6 + 2*3^8 + 2*3^9 + O(3^10))*u + (1 + 3 + 3^2 +
- 3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 3^9 + O(3^10)), u^2 + (3 + 3^3 + 2*3^4 + 3^5 
+Mod((1 + 3 + 3^3 + 3^4 + 2*3^6 + 2*3^8 + 2*3^9 + O(3^10))*x + (1 + 3 + 3^2 +
+ 3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 3^9 + O(3^10)), x^2 + (3 + 3^3 + 2*3^4 + 3^5 
 + 2*3^6 + 3^7 + 2*3^8 + 3^9 + 2*3^10 + 3^11 + 2*3^12 + O(3^13)))
-Mod((2^3 + 2^7 + O(2^8))*u + (1 + 2 + 2^2 + 2^3 + 2^4 + O(2^6)), u^2 + (1 + 
+Mod((2^3 + 2^7 + O(2^8))*x + (1 + 2 + 2^2 + 2^3 + 2^4 + O(2^6)), x^2 + (1 + 
 2^2 + 2^4 + 2^5 + 2^7 + 2^8 + 2^9 + O(2^13)))
 [Mod(0, 11), Mod(0, 11), Mod(0, 11), Mod(1, 11), Mod(1, 11), Mod(0, 11), Mod
 (2, 11), Mod(4, 11), Mod(10, 11), Mod(7, 11), Mod(5, 11), Mod(10, 11), Mod(9
@@ -335,10 +360,10 @@ small([1]), [Vecsmall([128, -1])], [0, 0, 0, 0, 0, 0, 0, [[2, 3]~, [1/2, 0,
 4294985035
 [0, 1, [5, 0, 0, 0], 1]
 1
-1
+0
 [6.2500000000000000000000000000000000000, -140.62500000000000000000000000000
 000000]
-[37247908142/10128208321, 7601802384416381/1019292757217119]
+error("incorrect type in checkell (t_VEC).")
 [0, 0, 0, x^2, x, 0, 2*x^2, 4*x, -x^4, -48*x^2, -864*x, -64*x^6 - 432*x^2, -
 6912*x^4/(-4*x^4 - 27), Vecsmall([0]), [Vecsmall([128, 0])], [0, 0, 0, 0]]
   ***   at top-level: ellminimalmodel(E)
@@ -381,6 +406,7 @@ ecsmall([0, 1]), [Vecsmall([0, 1]), Vecsmall([0]), Vecsmall([0]), Vecsmall([
 1
 -1
 1
+1
 x^-2 + Mod(-1/5*x, x^2 + 5)*x^2 + Mod(-1/15, x^2 + 5)*x^6 + Mod(2/975*x, x^2
  + 5)*x^10 + O(x^14)
 x^-1 + Mod(1/15*x, x^2 + 5)*x^3 + Mod(1/105, x^2 + 5)*x^7 + Mod(-2/10725*x, 
@@ -395,4 +421,46 @@ Mod(1, 1009)*x + Mod(185, 1009)*x^5 + Mod(101, 1009)*x^9 + Mod(990, 1009)*x^
 13 + O(x^17)
 -52760
 -52832
-Total time spent: 1052
+[[1, -1], 2]
+[[509051665/47782462464, -2265512629515497/10444864034930688], 12]
+ellformalw
+t^3 - t^5 + t^6 - t^7 - 3*t^8 + 9*t^9 - 2*t^10 - 21*t^11 + 45*t^12 - 21*t^13
+ - 140*t^14 + 339*t^15 - 91*t^16 - 1051*t^17 + 2394*t^18 + O(t^19)
+x^3 - x^5 + x^6 - x^7 + O(x^8)
+t^3 - t^5 + t^6 - t^7 + O(t^8)
+ellformalpoint
+[t^-2 + 1 - t + 2*t^2 + t^3 - 5*t^4 + 3*t^5 + 5*t^6 - 19*t^7 + 22*t^8 + 33*t
+^9 - 129*t^10 + 111*t^11 + 228*t^12 - 855*t^13 + O(t^14), -t^-3 - t^-1 + 1 -
+ 2*t - t^2 + 5*t^3 - 3*t^4 - 5*t^5 + 19*t^6 - 22*t^7 - 33*t^8 + 129*t^9 - 11
+1*t^10 - 228*t^11 + 855*t^12 + O(t^13)]
+[x^-2 + 1 - x + 2*x^2 + O(x^3), -x^-3 - x^-1 + 1 - 2*x + O(x^2)]
+[t^-2 + 1 - t + 2*t^2 + O(t^3), -t^-3 - t^-1 + 1 - 2*t + O(t^2)]
+ellformaldifferential
+[1 - t^2 + 2*t^3 - 3*t^4 - 6*t^5 + 23*t^6 - 12*t^7 - 53*t^8 + 160*t^9 - 131*
+t^10 - 470*t^11 + 1471*t^12 - 882*t^13 - 4257*t^14 + 12628*t^15 + O(t^16), t
+^-2 + t - 2*t^2 - 2*t^3 + 11*t^4 - 9*t^5 - 18*t^6 + 78*t^7 - 94*t^8 - 175*t^
+9 + 725*t^10 - 676*t^11 - 1603*t^12 + 6293*t^13 + O(t^14)]
+[1 - x^2 + 2*x^3 - 3*x^4 + O(x^5), x^-2 + x - 2*x^2 + O(x^3)]
+[1 - t^2 + 2*t^3 - 3*t^4 + O(t^5), t^-2 + t - 2*t^2 + O(t^3)]
+ellformallog
+t - 1/3*t^3 + 1/2*t^4 - 3/5*t^5 - t^6 + 23/7*t^7 - 3/2*t^8 - 53/9*t^9 + 16*t
+^10 - 131/11*t^11 - 235/6*t^12 + 1471/13*t^13 - 63*t^14 - 1419/5*t^15 + 3157
+/4*t^16 + O(t^17)
+x - 1/3*x^3 + 1/2*x^4 - 3/5*x^5 + O(x^6)
+t - 1/3*t^3 + 1/2*t^4 - 3/5*t^5 + O(t^6)
+ellformalexp
+t + 1/3*t^3 - 1/2*t^4 + 14/15*t^5 - 1/6*t^6 - 76/315*t^7 - 7/10*t^8 + 7547/1
+1340*t^9 + 977/3780*t^10 - 5116/22275*t^11 - 78977/113400*t^12 + 3069607/608
+1075*t^13 + 1651/2970*t^14 - 526660427/2554051500*t^15 - 5754943993/68108040
+00*t^16 + O(t^17)
+x + 1/3*x^3 - 1/2*x^4 + 14/15*x^5 + O(x^6)
+t + 1/3*t^3 - 1/2*t^4 + 14/15*t^5 + O(t^6)
+  ***   at top-level: ellformalw(e,0)
+  ***                 ^---------------
+  *** ellformalw: domain error in ellformalw: precision <= 0
+  ***   at top-level: ellformalw(e,-1)
+  ***                 ^----------------
+  *** ellformalw: domain error in ellformalw: precision <= 0
+242.47010035195076100129810400142304776
+0
+Total time spent: 476
diff --git a/src/test/32/ellanal b/src/test/32/ellanal
index 218e706..82445c8 100644
--- a/src/test/32/ellanal
+++ b/src/test/32/ellanal
@@ -1,14 +1,24 @@
 [0, 0.25384186085591068433775892335090946105]
-[1, 0.30599977383405230182048368332167647444]
-[2, 1.5186330005768535404603852157894440392]
-[3, 10.391099400715804138751850510360917049]
-[5, 9997.0334671722554999496820788093288504]
+[1, 0.30599977383405230182048368332167647445]
+[2, 1.5186330005768535404603852157894440381]
+[3, 10.391099400715804138751850510360917070]
+[5, 9997.0334671722554999496820788093288480]
 [-339/16, 691/64]
 [-3, 12]
 [69648970982596494254458225/166136231668185267540804, 5389624350896046150780
 04307258785218335/67716816556077455999228495435742408]
 [553/17424, 25469/2299968]
 35
-  ***   Warning: new stack size = 30000000 (28.610 Mbytes).
 [1317254400, 19916886528000]
-Total time spent: 13904
+0
+2.8053554406276820682921020105298729343
+-11.896004833586082242416037296368976713
+1.5186330005768535404603852157894440381
+0
+2.80535544062768206829210201052987293427393419289431401051573873877896370606
+9444052334712747100820315923332165307854
+-11.896004833586082242416037296368976714435763715221464992944563773201706595
+82985109754671351911693790517073338635203
+1.51863300057685354046038521578944403815619503298984870317161018509598214549
+5561104880431870004657718333754298413640
+Total time spent: 2188
diff --git a/src/test/32/ellff b/src/test/32/ellff
index f093026..ba5c1ff 100644
--- a/src/test/32/ellff
+++ b/src/test/32/ellff
@@ -1,6 +1,9 @@
+[[Mod(325254531735269032, 18446744073709551557), Mod(2692423357974964052, 18
+446744073709551557)]]
+18446744078921414430
 93
 88
 [0]
 [0]
 Mod(1, 2)*a1^2*x^2 + Mod(1, 2)*a3^2
-Total time spent: 8029
+Total time spent: 7632
diff --git a/src/test/32/elliptic b/src/test/32/elliptic
index 95eed6d..7d9b956 100644
--- a/src/test/32/elliptic
+++ b/src/test/32/elliptic
@@ -26,7 +26,7 @@ mall([128, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]
 , -4, -18, 0, 4, 24, 2, 4, 12, 18, 0, -24, 4, 12, -30, -2]
 ? ellap(acurve,10007)
 66
-? deu=direuler(p=2,100,1/(1-ellap(acurve,p)*x+if(acurve[12]%p,p,0)*x^2))
+? deu=direuler(p=2,100,1/(1-ellap(acurve,p)*x+if(acurve.disc%p,p,0)*x^2))
 [1, -2, -3, 2, -2, 6, -1, 0, 6, 4, -5, -6, -2, 2, 6, -4, 0, -12, 0, -4, 3, 1
 0, 2, 0, -1, 4, -9, -2, 6, -12, -4, 8, 15, 0, 2, 12, -1, 0, 6, 0, -9, -6, 2,
  -10, -12, -4, -9, 12, -6, 2, 0, -4, 1, 18, 10, 0, 0, -12, 8, 12, -8, 8, -6,
@@ -47,8 +47,6 @@ mall([128, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]
 [37, [1, -1, 2, 2], 1, Mat([37, 1]), [[1, 5, 0, 1]]]
 ? ellheight(acurve,apoint)
 0.81778253183950144377417759611107234575
-? ellheight(acurve,apoint,1)
-0.81778253183950144377417759611107234575
 ? ellordinate(acurve,1)
 [8, 3]
 ? ellpointtoz(acurve,apoint)
@@ -98,13 +96,10 @@ small([128, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]
 6
 ? elltors(tcurve)
 [12, [6, 2], [[1, 2], [3, -2]]]
-? mcurve=ellinit([-17,0])
-[0, 0, 0, -17, 0, 0, -34, 0, -289, 816, 0, 314432, 1728, Vecsmall([1]), [Vec
-small([128, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]
-? mpoints=[[-1,4],[-4,2]]~
-[[-1, 4], [-4, 2]]~
+? mcurve=ellinit([-17,0]);
+? mpoints=[[-1,4],[-4,2]]~;
 ? mhbi=ellbil(mcurve,mpoints,[9,24])
-[-0.72448571035980184146215805860545027441, 1.307328627832055544492943428892
+[-0.72448571035980184146215805860545027440, 1.307328627832055544492943428892
 1943056]~
 ? ma=ellheightmatrix(mcurve,mpoints)
 
@@ -126,4 +121,4 @@ small([128, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]
  28*w))]
 ? if(getheap()!=HEAP,getheap())
 ? print("Total time spent: ",gettime);
-Total time spent: 32
+Total time spent: 24
diff --git a/src/test/32/ellisogeny b/src/test/32/ellisogeny
new file mode 100644
index 0000000..aefeadd
--- /dev/null
+++ b/src/test/32/ellisogeny
@@ -0,0 +1,7 @@
+  ***   at top-level: ellisogenyapply(x,x)
+  ***                 ^--------------------
+  *** ellisogenyapply: incorrect type in checkellisog (t_POL).
+  ***   at top-level: ellisogenyapply([f,g
+  ***                 ^--------------------
+  *** ellisogenyapply: incorrect type in checkellpt (t_INT).
+Total time spent: 112
diff --git a/src/test/32/ellnf b/src/test/32/ellnf
new file mode 100644
index 0000000..8b4297d
--- /dev/null
+++ b/src/test/32/ellnf
@@ -0,0 +1,16 @@
+1
+[Mod(5/2*t^2 - 3/8*t + 7/4, t^3 - 2), Mod(3/8*t^2 - 67/16*t - 123/16, t^3 - 
+2)]
+[Mod(21112/25281*t^2 + 33953/25281*t + 54736/25281, t^3 - 2), Mod(2829824/13
+39893*t^2 + 5014079/1339893*t + 5473088/1339893, t^3 - 2)]
+[Mod(-t, t^3 - 2), Mod(t, t^3 - 2)]
+[]
+3*x^4 + Mod(6*t + 6, t^3 - 2)*x^2 + Mod(-12*t - 24, t^3 - 2)*x + Mod(-t^2 - 
+2*t - 1, t^3 - 2)
+[0, 0, 0, Mod(-3*t^2 + 5184*t, t^3 - 2), Mod(-6912*t^2 + 5971968*t + 4, t^3 
+- 2)]
+[]
+[Mod(0, 5), Mod(0, 5), Mod(0, 5), Mod(4, 5), Mod(0, 5), Mod(0, 5), Mod(3, 5)
+, Mod(0, 5), Mod(4, 5), Mod(3, 5), Mod(0, 5), Mod(4, 5), Mod(3, 5), Vecsmall
+([3]), [5, [4, 0, [1, 0, 0, 0]]], [0, 0, 0, 0]]
+Total time spent: 156
diff --git a/src/test/32/ellpadic b/src/test/32/ellpadic
new file mode 100644
index 0000000..0b1a6e0
--- /dev/null
+++ b/src/test/32/ellpadic
@@ -0,0 +1,80 @@
+  ***   Warning: new stack size = 40000000 (38.147 Mbytes).
+[2^-2 + 2^-1 + 1 + 2 + O(2^2), 1 + 2 + 2^2 + 2^3 + O(2^4)]
+[3 + 2*3^2 + 3^4 + O(3^5), 2*3^4 + 3^5 + O(3^8)]
+[3*5 + 5^2 + 2*5^3 + 3*5^4 + O(5^5), 5^2 + 4*5^4 + O(5^6)]
+[0, 0]
+  ***   at top-level: ellpadicheight(E,19,
+  ***                 ^--------------------
+  *** ellpadicheight: domain error in ellpadicheight: precision <= 0
+[2^-1 + 2 + 2^2 + O(2^5), 2^-1 + 2^2 + 2^3 + O(2^5)]
+[2^-1 + 1 + 2^2 + 2^4 + O(2^5), 1 + 2^2 + 2^4 + O(2^6)]
+[2*3^2 + 2*3^3 + 3^4 + 3^5 + 3^6 + O(3^7), 2*3^2 + 3^4 + 2*3^5 + 3^6 + O(3^7
+)]
+  ***   at top-level: ellpadiclog(E,3,5,P)
+  ***                 ^--------------------
+  *** ellpadiclog: domain error in ellpadiclog: P not in the kernel of reduction at 3
+2*3 + 2*3^2 + 3^5 + O(3^6)
+[2^3 + 2^5 + O(2^7), 2^5 + 2^6 + O(2^7)]
+[2^3 + 2^5 + O(2^6), O(2^5)]
+
+[[4 + 2*5 + 4*5^2 + 3*5^3 + 3*5^4 + O(5^5), 4*5^2 + 5^3 + 3*5^5 + 5^6 + O(5^
+7)] [4*5^2 + 4*5^3 + 4*5^4 + O(5^5), 4*5^2 + 3*5^6 + O(5^7)] [4 + 5 + 5^3 + 
+5^4 + O(5^5), 5^2 + 2*5^3 + 3*5^4 + 5^5 + 2*5^6 + O(5^7)]]
+
+[[4*5^2 + 4*5^3 + 4*5^4 + O(5^5), 4*5^2 + 3*5^6 + O(5^7)] [4 + 3*5 + 4*5^2 +
+ 4*5^3 + 4*5^4 + O(5^5), 4*5^2 + 4*5^3 + 3*5^4 + 4*5^5 + 3*5^6 + O(5^7)] [2 
++ 5^2 + 2*5^3 + 5^4 + O(5^5), 5^2 + 3*5^3 + 2*5^4 + 5^5 + 5^6 + O(5^7)]]
+
+[[4 + 5 + 5^3 + 5^4 + O(5^5), 5^2 + 2*5^3 + 3*5^4 + 5^5 + 2*5^6 + O(5^7)] [2
+ + 5^2 + 2*5^3 + 5^4 + O(5^5), 5^2 + 3*5^3 + 2*5^4 + 5^5 + 5^6 + O(5^7)] [2*
+5^2 + 2*5^3 + 5^4 + 5^5 + 5^6 + O(5^7), 4*5^2 + 3*5^3 + 5^4 + 4*5^5 + 3*5^6 
++ O(5^7)]]
+
+3 + 3^2 + 3^3 + 3^4 + 3^5 + O(3^6)
+2*3^2 + 3^4 + O(3^6)
+
+[4 + 2*5 + 4*5^2 + 3*5^3 + 3*5^4 + O(5^5) 4*5^2 + 4*5^3 + 4*5^4 + O(5^5) 4 +
+ 5 + 5^3 + 5^4 + O(5^5)]
+
+[4*5^2 + 4*5^3 + 4*5^4 + O(5^5) 4 + 3*5 + 4*5^2 + 4*5^3 + 4*5^4 + O(5^5) 2 +
+ 5^2 + 2*5^3 + 5^4 + O(5^5)]
+
+[4 + 5 + 5^3 + 5^4 + O(5^5) 2 + 5^2 + 2*5^3 + 5^4 + O(5^5) 2*5^2 + 2*5^3 + 5
+^4 + 5^5 + 5^6 + O(5^7)]
+
+
+[4*5^2 + 5^3 + 3*5^5 + 5^6 + O(5^7) 4*5^2 + 3*5^6 + O(5^7) 5^2 + 2*5^3 + 3*5
+^4 + 5^5 + 2*5^6 + O(5^7)]
+
+[4*5^2 + 3*5^6 + O(5^7) 4*5^2 + 4*5^3 + 3*5^4 + 4*5^5 + 3*5^6 + O(5^7) 5^2 +
+ 3*5^3 + 2*5^4 + 5^5 + 5^6 + O(5^7)]
+
+[5^2 + 2*5^3 + 3*5^4 + 5^5 + 2*5^6 + O(5^7) 5^2 + 3*5^3 + 2*5^4 + 5^5 + 5^6 
++ O(5^7) 4*5^2 + 3*5^3 + 5^4 + 4*5^5 + 3*5^6 + O(5^7)]
+
+5 + 5^2 + 4*5^3 + 2*5^4 + O(5^5)
+O(5^7)
+2 + 4*43 + 19*43^2 + 15*43^3 + 35*43^4 + 3*43^5 + O(43^6)
+4 + 3*5^2 + 4*5^3 + 5^4 + 2*5^5 + O(5^6)
+4 + 3*5 + 3*5^3 + 3*5^4 + 4*5^5 + O(5^6)
+
+[4*5 + 4*5^2 + 2*5^3 + 5^4 + 2*5^5 + 3*5^6 + O(5^7) 4 + 5^2 + 2*5^4 + 5^5 + 
+5^6 + O(5^7)]
+
+[5 + 2*5^2 + 3*5^3 + 4*5^4 + 5^5 + 5^6 + O(5^7) 5 + 2*5^3 + 3*5^4 + 2*5^5 + 
+5^6 + O(5^7)]
+
+
+[          2*3^4 + O(3^5) 1 + 3 + 2*3^2 + 3^3 + 3^4 + O(3^5)]
+
+[2*3 + 3^3 + 3^4 + O(3^5)                       3^4 + O(3^5)]
+
+[2*3^-1 + 1 + 3 + 3^2 + O(3^3), 3^-1 + 1 + 3 + 3^2 + O(3^3)]
+[1 + 2*3 + 2*3^3 + O(3^4), O(3^4)]~
+[1 + O(3^4), O(3^4)]~
+4 + 3*5 + 4*5^2 + 2*5^3 + O(5^4)
+1 + O(5^4)
+[1 + O(3^4), O(3^4)]~
+[1 + O(3^4), O(3^5)]~
+[O(3^3), O(3^3)]
+Total time spent: 2124
diff --git a/src/test/32/ellsea b/src/test/32/ellsea
index d947038..d7f4bb6 100644
--- a/src/test/32/ellsea
+++ b/src/test/32/ellsea
@@ -10,4 +10,12 @@
 9: 1854715558584444
 10: 20420247695
 11: -4742075250
-Total time spent: 11668
+1:896615193897208487551655423042
+2:1160030981035862058695525039892
+3:529656639561669286549173325490
+4:817701636704152445708337225413
+5:983440823277044783790077069060
+6:383857664397975740685677977539
+-40969318
+71537967059636
+Total time spent: 5852
diff --git a/src/test/32/elltors b/src/test/32/elltors
new file mode 100644
index 0000000..30569d8
--- /dev/null
+++ b/src/test/32/elltors
@@ -0,0 +1,85 @@
+[1, [], []]
+[2, [2], [[15, -8]]]
+[3, [3], [[5, 9]]]
+[4, [4], [[5, -2]]]
+[5, [5], [[5, 5]]]
+[6, [6], [[9, 23]]]
+[7, [7], [[-1, 2]]]
+[8, [8], [[2, 6]]]
+[9, [9], [[-3, 7]]]
+[10, [10], [[0, 9]]]
+[12, [12], [[-9, 49]]]
+[4, [2, 2], [[-29/4, 25/8], [-7, 3]]]
+[8, [4, 2], [[-2, 3], [-1, 0]]]
+[12, [6, 2], [[1, 2], [3, -2]]]
+[16, [8, 2], [[4, 58], [-36, 18]]]
+[16, [8, 2], [[117433600, 6734213027200], [352179456, -176089728]]]
+[4, [2, 2], [[-1377493124511464657, 0], [-691668349248679055, 0]]]
+[16, [8, 2], [[0, Mod(0, t^2 - 5)], [Mod(3/5*t + 17/15, t^2 - 5), Mod(209/22
+5*t + 97/45, t^2 - 5)]]]
+8
+2
+[1, [], []]
+[1, [], []]
+[25, [25], [[Mod(-t^7 - t^6 - t^5 - t^4 + 1, t^10 + t^9 + t^8 + t^7 + t^6 + 
+t^5 + t^4 + t^3 + t^2 + t + 1), Mod(-t^9 - 2*t^8 - 2*t^7 - 3*t^6 - 3*t^5 - 2
+*t^4 - 2*t^3 - t^2 - 1, t^10 + t^9 + t^8 + t^7 + t^6 + t^5 + t^4 + t^3 + t^2
+ + t + 1)]]]
+[11, [11], [[-78848, Mod(-5992448*y - 15454208, y^2 + 7)]]]
+[15, [15], [[Mod(0, y^2 + 7), Mod(-26*y + 14, y^2 + 7)]]]
+[20, [10, 2], [[831474369/262144, 519671480625/4194304], [Mod(-59375/256*y +
+ 261214369/262144, y^2 + 2), Mod(0, y^2 + 2)]]]
+-536129/8192*y + 15673889/65536
+-2001779325/262144*y + 115490749725/4194304
+[24, [12, 2], [[Mod(-20655/8192*y + 15795/2048, y^2 - 13), Mod(300055185/209
+7152*y - 270394605/524288, y^2 - 13)], [Mod(221/8*y - 6461/64, y^2 - 13), Mo
+d(0, y^2 - 13)]]]
+-313766195076761969526071169866614175160*y + 1735663223649526033628839600302
+712469280
+[14, [14], [[Mod(358950904714175557651106659750101468600*y - 224800911486294
+2058383152194083021128800, y^2 + 11), Mod(-623358463905364610014856551413519
+5275639238995135197696000*y + 7068212904273547655621435172436672299424081219
+4549767368000, y^2 + 11)]]]
+[32, [16, 2], [[Mod(-5089/81696780*y^3 - 7/21780*y^2 - 898639/7426980*y - 12
+37/1980, y^4 + 2002*y^2 + 116281), Mod(-8470441/296559311400*y^3 - 41923/790
+61400*y^2 - 1494908191/26959937400*y - 7401793/7187400, y^4 + 2002*y^2 + 116
+281)], [-1/900, 0]]]
+[9, [3, 3], [[-2, Mod(-3*y + 1, y^2 + 3)], [1, -5]]]
+[20, [20], [[Mod(-2*y^2 + 12*y + 12, y^3 - y^2 - 2*y - 2), Mod(52*y^2 - 8*y 
++ 16, y^3 - y^2 - 2*y - 2)]]]
+[36, [6, 6], [[Mod(-7/32, y^4 + 5*y^2 + 1), Mod(7/512*y^3 + 7/128*y + 35/512
+, y^4 + 5*y^2 + 1)], [Mod(1/128*y^3 + 3/64*y - 21/128, y^4 + 5*y^2 + 1), Mod
+(-1/512*y^3 - 3/256*y + 21/512, y^4 + 5*y^2 + 1)]]]
+[32, [8, 4], [[0, 0], [Mod(-37/3570750*y^3 - 30007/3570750*y + 222/575, y^4 
++ 541*y^2 + 72900), Mod(-731971/2463817500*y^3 - 888/1520875*y^2 - 194058451
+/2463817500*y - 51282/1520875, y^4 + 541*y^2 + 72900)]]]
+[64, [8, 8], [[Mod(-3/7*y^15 + 34/7*y^14 - 191/7*y^13 + 97*y^12 - 241*y^11 +
+ 446*y^10 - 4639/7*y^9 + 5844/7*y^8 - 6441/7*y^7 + 6214/7*y^6 - 751*y^5 + 38
+25/7*y^4 - 2313/7*y^3 + 1054/7*y^2 - 317/7*y + 45/7, y^16 - 8*y^15 + 36*y^14
+ - 104*y^13 + 220*y^12 - 368*y^11 + 516*y^10 - 624*y^9 + 664*y^8 - 624*y^7 +
+ 516*y^6 - 368*y^5 + 220*y^4 - 104*y^3 + 36*y^2 - 8*y + 1), Mod(-41/7*y^15 +
+ 304/7*y^14 - 1269/7*y^13 + 3317/7*y^12 - 895*y^11 + 9434/7*y^10 - 1737*y^9 
++ 13604/7*y^8 - 13345/7*y^7 + 11526/7*y^6 - 8663/7*y^5 + 5395/7*y^4 - 2675/7
+*y^3 + 984/7*y^2 - 223/7*y + 12/7, y^16 - 8*y^15 + 36*y^14 - 104*y^13 + 220*
+y^12 - 368*y^11 + 516*y^10 - 624*y^9 + 664*y^8 - 624*y^7 + 516*y^6 - 368*y^5
+ + 220*y^4 - 104*y^3 + 36*y^2 - 8*y + 1)], [Mod(-1006/329*y^15 + 763/47*y^14
+ - 17540/329*y^13 + 4104/47*y^12 - 29994/329*y^11 + 11747/329*y^10 + 2568/47
+*y^9 - 60499/329*y^8 + 92956/329*y^7 - 16937/47*y^6 + 118390/329*y^5 - 10387
+8/329*y^4 + 70088/329*y^3 - 5507/47*y^2 + 11498/329*y - 2228/329, y^16 - 8*y
+^15 + 36*y^14 - 104*y^13 + 220*y^12 - 368*y^11 + 516*y^10 - 624*y^9 + 664*y^
+8 - 624*y^7 + 516*y^6 - 368*y^5 + 220*y^4 - 104*y^3 + 36*y^2 - 8*y + 1), Mod
+(-4412/329*y^15 + 35995/329*y^14 - 22978/47*y^13 + 459612/329*y^12 - 134990/
+47*y^11 + 1532149/329*y^10 - 2078812/329*y^9 + 2438613/329*y^8 - 358218/47*y
+^7 + 2277477/329*y^6 - 256916/47*y^5 + 1211712/329*y^4 - 660116/329*y^3 + 27
+1037/329*y^2 - 9730/47*y + 10205/329, y^16 - 8*y^15 + 36*y^14 - 104*y^13 + 2
+20*y^12 - 368*y^11 + 516*y^10 - 624*y^9 + 664*y^8 - 624*y^7 + 516*y^6 - 368*
+y^5 + 220*y^4 - 104*y^3 + 36*y^2 - 8*y + 1)]]]
+[27, [9, 3], [[-3, -5], [Mod(-x^4 + 3*x^2, x^6 + 3), Mod(-3/2*x^5 + 1/2*x^4 
++ 9/2*x^3 - 3/2*x^2 - 3/2*x - 1/2, x^6 + 3)]]]
+[4, [2, 2], [[-2147484185, 0], [0, 0]]]
+2
+2
+0
+0
+[1, [], []]
+Total time spent: 280
diff --git a/src/test/32/ellweilpairing b/src/test/32/ellweilpairing
index 6f55675..e3da8f9 100644
--- a/src/test/32/ellweilpairing
+++ b/src/test/32/ellweilpairing
@@ -293,4 +293,5 @@ t^5 + t^4 + 1
 [4, 4, 3, 3, 1]:[2, 2]
 [4, 4, 4, 1, 3]:[2, 2]
 [4, 4, 4, 4, 1]:[4, 2]
-Total time spent: 40
+[36893488147419103364, 36893488147419103364]
+Total time spent: 108
diff --git a/src/test/32/equal b/src/test/32/equal
index c4ed67d..79b0e0a 100644
--- a/src/test/32/equal
+++ b/src/test/32/equal
@@ -14,4 +14,53 @@
 [0, 1]
 [0, 0, 0, 1]
 [1, 1]
+1
+1
+0
+[0, 1]
+[0, 1]
+1
+0
+[0, 1]
+[0, 1]
+1
+0
+0
+1
+0
+[0, 0]
+[1, 1]
+[1, 1]
+[0, 0]
+[1, 0]
+[0, 1]
+[0, 0]
+[1, 0]
+[0, 1]
+[0, 0]
+[0, 0]
+[1, 0]
+[0, 1]
+[1, 0]
+[0, 0]
+[1, 0]
+[0, 0]
+[1, 0]
+[0, 1]
+[0, 0]
+[0, 0]
+[0, 0]
+[1, 1]
+[1, 0]
+[0, 0]
+[0, 0]
+[1, 0]
+[0, 1]
+[1, 1]
+[1, 0]
+[0, 0]
+[1, 0]
+[0, 0]
+[0, 0]
+[0, 1]
 Total time spent: 0
diff --git a/src/test/32/err b/src/test/32/err
index 62f7d17..81b68cb 100644
--- a/src/test/32/err
+++ b/src/test/32/err
@@ -344,6 +344,12 @@
   ***   at top-level: polroots(x^2+Mod(1,2
   ***                 ^--------------------
   *** polroots: incorrect type in roots (t_INTMOD).
+  ***   at top-level: polroots(0)
+  ***                 ^-----------
+  *** polroots: zero polynomial in roots.
+  ***   at top-level: polroots(Mod(1,2))
+  ***                 ^------------------
+  *** polroots: incorrect type in roots (t_INTMOD).
   ***   at top-level: prime(-2)
   ***                 ^---------
   *** prime: domain error in prime: n <= 0
@@ -532,9 +538,7 @@
   ***   at top-level: modreverse(Mod(-x^3+
   ***                 ^--------------------
   *** modreverse: domain error in modreverse: deg(minpoly(z)) < 4
-  ***   at top-level: rnfnormgroup(bnrinit
-  ***                 ^--------------------
-  *** rnfnormgroup: domain error in rnfnormgroup: rnfisabelian(bnr,pol) = 0
+[;]
   ***   at top-level: concat([1,2],[3,4]~)
   ***                 ^--------------------
   *** concat: inconsistent concatenation t_VEC (2 elts) , t_COL (2 elts).
@@ -547,8 +551,8 @@
   ***   at top-level: mathnfmod([1;2],2)
   ***                 ^------------------
   *** mathnfmod: domain error in ZM_hnfmod: nb lines > nb columns
-  ***   at top-level: polsturm(x^2)
-  ***                 ^-------------
+  ***   at top-level: polsturm(x^2*1.)
+  ***                 ^----------------
   *** polsturm: domain error in polsturm: issquarefree(pol) = 0
   ***   at top-level: removeprimes(2)
   ***                 ^---------------
@@ -581,10 +585,13 @@
   ***                             ^------
   ***   domain error in solve: f(a)f(b) > 0
   ***   user warning: 1
+  ***   at top-level: iferr(1/0,E,1,errnam
+  ***                 ^--------------------
+  *** iferr: impossible inverse in gdiv: 0.
 (x)->trap(e_INV,INFINITY,1/x)
 1/2
 INFINITY
   ***   at top-level: trap(e_INV,INFINITY,log(0))
   ***                                     ^-------
   *** log: domain error in log: argument = 0
-Total time spent: 20
+Total time spent: 12
diff --git a/src/test/32/eval b/src/test/32/eval
new file mode 100644
index 0000000..546d357
--- /dev/null
+++ b/src/test/32/eval
@@ -0,0 +1,3 @@
+  ***   syntax error, unexpected '=', expecting $end: =
+  ***                                                 ^-
+Total time spent: 0
diff --git a/src/test/32/extract b/src/test/32/extract
index 9ba9ea6..dd8d7bd 100644
--- a/src/test/32/extract
+++ b/src/test/32/extract
@@ -305,4 +305,34 @@ x + 1
 0
 y + O(y^2)
 Vecsmall([4, 5, 3])
-Total time spent: 0
+  ***   at top-level: vecextract([1],11)
+  ***                 ^------------------
+  *** vecextract: incorrect type in vecextract [mask too large] (t_INT).
+  ***   at top-level: vecextract([1],"1..2
+  ***                 ^--------------------
+  *** vecextract: incorrect type in vecextract [incorrect range] (t_STR).
+  ***   at top-level: vecextract([1],1/2)
+  ***                 ^-------------------
+  *** vecextract: incorrect type in vecextract [mask] (t_FRAC).
+  ***   at top-level: vecextract(1,1)
+  ***                 ^---------------
+  *** vecextract: incorrect type in extract (t_INT).
+  ***   at top-level: vecextract(matid(2),
+  ***                 ^--------------------
+  *** vecextract: incorrect type in vecextract [incorrect mask] (t_VEC).
+  ***   at top-level: [1][2..3]
+  ***                 ^---------
+  *** _[_.._]: inconsistent dimensions in _[..].
+  ***   at top-level: [1][-10..3]
+  ***                 ^-----------
+  *** _[_.._]: inconsistent dimensions in _[..].
+  ***   at top-level: 1[1..2]
+  ***                 ^-------
+  *** _[_.._]: incorrect type in _[_.._] (t_INT).
+  ***   at top-level: [1/2..1]
+  ***                     ^----
+  *** [_.._]: incorrect type in [_.._] (t_FRAC).
+  ***   at top-level: [1..1/2]
+  ***                   ^------
+  *** [_.._]: incorrect type in [_.._] (t_FRAC).
+Total time spent: 4
diff --git a/src/test/32/factormod b/src/test/32/factormod
index 2413925..863dac5 100644
--- a/src/test/32/factormod
+++ b/src/test/32/factormod
@@ -248,4 +248,7 @@ Mod(38, 41), Mod(40, 41)]~
 [;]
 1
 0
-Total time spent: 56
+
+[Mod(1, 100000000000000000039)*x + Mod(1, 100000000000000000039) 2]
+
+Total time spent: 68
diff --git a/src/test/32/ff b/src/test/32/ff
index 9735799..df1b630 100644
--- a/src/test/32/ff
+++ b/src/test/32/ff
@@ -17,12 +17,12 @@ a^2 + a, a^16 + a^12 + a^9 + a^8 + a^6 + a^4 + a^3 + a^2 + a + 1, a^12 + a^9
 16 + a^12 + a^9 + a^6 + a^4 + a^3 + a^2 + 1, a^16 + a^12 + a^9 + a^6 + a^4 +
  a^3 + a, a^16 + a^12 + a^9 + a^6 + a^3 + a^2 + a + 1, a^16 + a^12 + a^9 + a
 ^8 + a^6 + a^4 + a^3 + a^2 + a]~, [x^3 + (a^17 + a^16 + a^10 + a^7 + a^3), 1
-; x^3 + (a^17 + a^16 + a^10 + a^7 + a^3 + a), 1], [], a/x, 1, a^19 + a^18 + 
-a^17 + a^13 + a^10 + a^6 + a^4, 1048575, a, [x + (a^18 + a^16 + a^13 + a^9 +
- a^8 + a^7 + a^6 + a^4 + a^2 + a), 1; x + (a^18 + a^16 + a^13 + a^9 + a^8 + 
-a^7 + a^6 + a^4 + a^2 + a + 1), 1], [a^18 + a^16 + a^13 + a^9 + a^8 + a^7 + 
-a^6 + a^4 + a^2 + a, a^18 + a^16 + a^13 + a^9 + a^8 + a^7 + a^6 + a^4 + a^2 
-+ a + 1]~]
+; x^3 + (a^17 + a^16 + a^10 + a^7 + a^3 + a), 1], [], a/x, 1, a^18 + a^16 + 
+a^14 + a^13 + a^12 + a^11 + a^9 + a^8 + a^7 + a^3 + a^2 + a + 1, 1048575, a,
+ [x + (a^18 + a^16 + a^13 + a^9 + a^8 + a^7 + a^6 + a^4 + a^2 + a), 1; x + (
+a^18 + a^16 + a^13 + a^9 + a^8 + a^7 + a^6 + a^4 + a^2 + a + 1), 1], [a^18 +
+ a^16 + a^13 + a^9 + a^8 + a^7 + a^6 + a^4 + a^2 + a, a^18 + a^16 + a^13 + a
+^9 + a^8 + a^7 + a^6 + a^4 + a^2 + a + 1]~]
 ? test(7,7)
 [a^2 + 3*a + 1, a^6 + 2*a^4 + 5*a^3 + 2*a^2 + 5*a + 1, 3*a + 3, a + 3, 5*a^6
  + 3*a^4 + 4*a^3 + 3*a^2 + 4*a, 2*a + 2, 2*a + 2, 4*a + 4, 6*a^6 + 6*a^5 + 5
@@ -34,13 +34,10 @@ od(1, 7), Mod(1, 7)*x^7 + Mod(1, 7)*x^6 + Mod(2, 7)*x^5 + Mod(5, 7)*x + Mod(
  3*a^6 + 5*a^2 + 5, 6*a^6 + 2*a^5 + 5*a^4 + 5*a^3 + 5*a^2 + a + 5, 2*a^6 + 5
 *a^2 + 6, 6*a^6 + a^5 + 2*a^4 + 2*a^2]~, [x^2 + (a^6 + 6*a^5 + 4*a^4 + 5*a^3
  + 4)*x + 4, 1; x^2 + (2*a^6 + 5*a^5 + a^4 + 3*a^3 + 1)*x + 2, 1; x^2 + (4*a
-^6 + 3*a^5 + 2*a^4 + 6*a^3 + 2)*x + 1, 1], [0, 0, 0, a, 1, 0, 2*a, 4, 6*a^2,
- a, 4, 6*a^3 + 2, a^6 + 4*a^5 + 4*a^4 + 6*a^2 + a + 4, Vecsmall([4]), [a, [V
-ecsmall([131072, 0, 1]), Vecsmall([131072, 1]), [Vecsmall([131072, 6]), Vecs
-mall([131072]), Vecsmall([131072]), Vecsmall([131072])]]], [0, 0, 0, 0]], a/
-x, (x + a)/(x + 6*a), 6*a^6 + 4*a^5 + 4*a^4 + 4*a^3 + 5*a^2 + 6*a + 3, 27451
-4, a, [x + (2*a^6 + 6*a^5 + 5*a^2 + 2*a + 1), 1; x + (5*a^6 + a^5 + 2*a^2 + 
-5*a), 1], [2*a^6 + 6*a^5 + 5*a^2 + 2*a, 5*a^6 + a^5 + 2*a^2 + 5*a + 6]~]
+^6 + 3*a^5 + 2*a^4 + 6*a^3 + 2)*x + 1, 1], a^6 + 4*a^5 + 4*a^4 + 6*a^2 + a +
+ 4, a/x, (x + a)/(x + 6*a), 4*a^6 + 4*a^5 + 2*a^4 + 3*a^3 + a^2 + a + 6, 274
+514, a, [x + (2*a^6 + 6*a^5 + 5*a^2 + 2*a + 1), 1; x + (5*a^6 + a^5 + 2*a^2 
++ 5*a), 1], [2*a^6 + 6*a^5 + 5*a^2 + 2*a, 5*a^6 + a^5 + 2*a^2 + 5*a + 6]~]
 ? test(precprime(2^32),3)
 [a^2 + 3*a + 1, 3435973833*a^2 + 3435973833, 2863311528*a + 2863311528, a + 
 3435973833, 3579139409*a^2 + 2863311528, 3579139410*a + 3579139410, 1024*a +
@@ -54,49 +51,93 @@ a, a^2 + a + 4294967288, 4294967290*a^2 + 4294967289*a + 2]~, [x + (34444702
 3*a^2 + 1616586690*a + 252460086), 1; x + (3340051543*a^2 + 1627577691*a + 2
 021233148), 1; x^2 + (954915748*a^2 + 2667389600*a + 2273734143)*x + (816322
 992*a^2 + 830924795*a + 1995175223), 1; x^2 + (3950520268*a^2 + 2678380601*a
- + 4042507205)*x + (1642837480*a^2 + 2548350348*a + 1670376662), 1], [0, 0, 
-0, a, 1, 0, 2*a, 4, 4294967290*a^2, 4294967243*a, 4294966427, 64*a^2 + 42949
-67035*a + 4294966923, 3618892287*a^2 + 1482857269*a + 1021597254, Vecsmall([
-4]), [a, [Vecsmall([131072, 0, 1296]), Vecsmall([131072, 46656]), [Vecsmall(
-[131072, 6]), Vecsmall([131072]), Vecsmall([131072]), Vecsmall([131072])]]],
- [0, 0, 0, 0]], a/x, (x + a)/(x + 4294967290*a), 904302895*a^2 + 515242178*a
- + 1663190800, 36893488070109691946, a, [x + (1365670490*a^2 + 3373566631*a 
-+ 4083593885), 1; x + (2929296801*a^2 + 921400660*a + 211373407), 1], [13656
-70490*a^2 + 3373566631*a + 4083593884, 2929296801*a^2 + 921400660*a + 211373
-406]~]
+ + 4042507205)*x + (1642837480*a^2 + 2548350348*a + 1670376662), 1], 3618892
+287*a^2 + 1482857269*a + 1021597254, a/x, (x + a)/(x + 4294967290*a), 402008
+2597*a^2 + 70712658*a + 4018965070, 36893488070109691946, a, [x + (136567049
+0*a^2 + 3373566631*a + 4083593885), 1; x + (2929296801*a^2 + 921400660*a + 2
+11373407), 1], [1365670490*a^2 + 3373566631*a + 4083593884, 2929296801*a^2 +
+ 921400660*a + 211373406]~]
 ? test(nextprime(2^32),3)
 [a^2 + 3*a + 1, a^2 + 4294967310, 1431655771*a + 1431655771, a + 3435973849,
  3579139425*a^2 + 1431655772, 715827886*a + 715827886, 1024*a + 1024, 114504
 4996*a + 1145044996, a^2 + a + 4294967309, 4294967310*a, a^2, 264190711*a^2 
-+ 2629464558*a + 2494776416, 2086193154*a^2 + 2086193154*a + 2086193154, 208
-6193154*a^2 + 2086193154*a + 2086193154, 2208774156, 996804783*a^2 + 2908221
++ 2629464558*a + 2494776416, 2086193154*a^2 + 2086193154*a + 2086193154, 220
+8774156*a^2 + 2208774156*a + 2208774156, 2086193154, 996804783*a^2 + 2908221
 018*a + 1206110100, Mod(13, 4294967311), Mod(4294967310, 4294967311), Mod(1,
  4294967311)*x^3 + Mod(1, 4294967311)*x^2 + Mod(4294967309, 4294967311)*x + 
 Mod(4294967310, 4294967311), Mod(1, 4294967311)*x^3 + Mod(1, 4294967311)*x^2
  + Mod(4294967309, 4294967311)*x + Mod(4294967310, 4294967311), [a, a^2 + 42
 94967309, 4294967310*a^2 + 4294967310*a + 1]~, [x^2 + (2086193155*a^2 + 1225
 81001)*x + 2086193154, 1; x^2 + (2208774157*a^2 + 4172386308)*x + 2208774156
-, 1; x^2 + (4294967310*a^2 + 2)*x + 1, 1], [0, 0, 0, a, 1, 0, 2*a, 4, 429496
-7310*a^2, 4294967263*a, 4294966447, 64*a^2 + 4294967183*a + 4294966815, 1484
-088443*a^2 + 1141114953*a + 4283364322, Vecsmall([4]), [a, [1296*a, 46656, [
-6, 0, 0, 0]]], [0, 0, 0, 0]], a/x, (x + a)/(x + 4294967310*a), 2425092325*a^
-2 + 865514605*a + 1871360732, 6148914735617846011, a, [x + (268392743*a^2 + 
-2459390605*a + 1304316255), 1; x + (4026574568*a^2 + 1835576706*a + 29906510
-57), 1], [268392743*a^2 + 2459390605*a + 1304316254, 4026574568*a^2 + 183557
-6706*a + 2990651056]~]
-? test2(p)=ffgen(x*Mod(1,p));g=ffprimroot(ffgen((x+1)*Mod(1,p)),&o);print([g,o]);fflog(g^17,g,o);
-? test2(2)
-[1, [1, matrix(0,2)]]
-0
-? test2(3)
-[2, [2, Mat([2, 1])]]
-1
-? test2(46744073709551653)
-[2, [46744073709551652, [2, 2; 3, 1; 7, 1; 37, 1; 1036513, 1; 14510113, 1]]]
-[]
-? test2(precprime(1<<32))
-[2, [4294967290, [2, 1; 5, 1; 19, 1; 22605091, 1]]]
-17
+, 1; x^2 + (4294967310*a^2 + 2)*x + 1, 1], 1484088443*a^2 + 1141114953*a + 4
+283364322, a/x, (x + a)/(x + 4294967310*a), 4204026293*a^2 + 2068287144*a + 
+232863018, 6148914735617846011, a, [x + (268392743*a^2 + 2459390605*a + 1304
+316255), 1; x + (4026574568*a^2 + 1835576706*a + 2990651057), 1], [268392743
+*a^2 + 2459390605*a + 1304316254, 4026574568*a^2 + 1835576706*a + 2990651056
+]~]
+? ffgen(ffinit(2^32-5,101),'a)^10000
+2904925334*a^100 + 700105542*a^99 + 1727200511*a^98 + 1173808205*a^97 + 9542
+0994*a^96 + 3202419959*a^95 + 2481924190*a^94 + 3126863204*a^93 + 2955970830
+*a^92 + 2548647191*a^91 + 1047527349*a^90 + 1607847794*a^89 + 1136036718*a^8
+8 + 2224103182*a^87 + 234809824*a^86 + 1334629770*a^85 + 3694521682*a^84 + 2
+888958800*a^83 + 2981717284*a^82 + 3586954794*a^81 + 956529198*a^80 + 193357
+785*a^79 + 2461870083*a^78 + 2884929899*a^77 + 2136433918*a^76 + 3711607228*
+a^75 + 332814573*a^74 + 2094440266*a^73 + 933657478*a^72 + 2778340755*a^71 +
+ 3169750773*a^70 + 2171979949*a^69 + 1221433421*a^68 + 901860002*a^67 + 2970
+90232*a^66 + 3539970492*a^65 + 2076910613*a^64 + 2401092275*a^63 + 171183351
+4*a^62 + 3584831951*a^61 + 2855998596*a^60 + 347617911*a^59 + 2423948087*a^5
+8 + 2221962383*a^57 + 2749975174*a^56 + 1550735992*a^55 + 2529466701*a^54 + 
+2598855843*a^53 + 4023905766*a^52 + 1486945524*a^51 + 2441781373*a^50 + 1138
+122930*a^49 + 2066584358*a^48 + 1722922056*a^47 + 3744247345*a^46 + 29285190
+73*a^45 + 1223452975*a^44 + 2713760803*a^43 + 2142407081*a^42 + 756824586*a^
+41 + 3732788422*a^40 + 1164553813*a^39 + 771729217*a^38 + 3634297024*a^37 + 
+2421113272*a^36 + 2598325671*a^35 + 3513778816*a^34 + 1539027125*a^33 + 3689
+734857*a^32 + 4188593390*a^31 + 2825758998*a^30 + 3192363801*a^29 + 36501544
+35*a^28 + 1334480978*a^27 + 2009094380*a^26 + 151875699*a^25 + 3435707889*a^
+24 + 661453301*a^23 + 416421795*a^22 + 3246563523*a^21 + 985317917*a^20 + 33
+10261776*a^19 + 4234321367*a^18 + 380085156*a^17 + 1049653093*a^16 + 6266755
+65*a^15 + 1603594749*a^14 + 3130157282*a^13 + 844750099*a^12 + 3495279283*a^
+11 + 1036502501*a^10 + 576151557*a^9 + 1040168751*a^8 + 1714788152*a^7 + 234
+0199159*a^6 + 4175283296*a^5 + 2975302344*a^4 + 2428563952*a^3 + 443574314*a
+^2 + 3215614405*a + 2183237283
+? ffgen(ffinit(2^64-59,101),'a)^10000
+11357361951151958121*a^100 + 5792035517727999732*a^99 + 7489923161672088612*
+a^98 + 198291789480115765*a^97 + 7027135568582861768*a^96 + 7299386875942518
+369*a^95 + 10681924511986429849*a^94 + 14721409711812770068*a^93 + 177845253
+02221024156*a^92 + 7804341282953434235*a^91 + 6253292858501893536*a^90 + 375
+2205311837838488*a^89 + 12205965799946763222*a^88 + 7579185967234550243*a^87
+ + 7660231629286376323*a^86 + 8927589722637637677*a^85 + 6783475681455269614
+*a^84 + 11968255844292754829*a^83 + 5819238353489370105*a^82 + 6918133330273
+010048*a^81 + 8900778062932659277*a^80 + 15250824442906974876*a^79 + 2484274
+759583929736*a^78 + 12662494501202465352*a^77 + 1658627870779087936*a^76 + 1
+3011592420351927994*a^75 + 1429162280240510446*a^74 + 8085544061123262008*a^
+73 + 12999730205733779276*a^72 + 14782490105219029716*a^71 + 970562341709006
+1989*a^70 + 10676813376503700642*a^69 + 13433094161603852463*a^68 + 17199289
+874783012603*a^67 + 4285333119776358644*a^66 + 16021251868058308047*a^65 + 1
+5495498503350376322*a^64 + 5966197018829209744*a^63 + 12345332784539353625*a
+^62 + 14865549204004875095*a^61 + 8272995682833482264*a^60 + 121032254702015
+79677*a^59 + 17479835254811511245*a^58 + 3057285969116272639*a^57 + 14559795
+162132711775*a^56 + 13046944472429221491*a^55 + 1019495020975929944*a^54 + 1
+6803291081324517730*a^53 + 17710829803474400119*a^52 + 2594650197306879903*a
+^51 + 12847996295434431851*a^50 + 9729674550253550622*a^49 + 109429518884359
+53217*a^48 + 508631243443378452*a^47 + 4416164175737874514*a^46 + 4138550054
+669964040*a^45 + 91535476336245596*a^44 + 11254247175995051473*a^43 + 336718
+1085033412978*a^42 + 11302910178987761836*a^41 + 14219471129414354857*a^40 +
+ 3472640334363308855*a^39 + 44279726220391285*a^38 + 8772473950884549985*a^3
+7 + 6773120702751407339*a^36 + 6996688466561413845*a^35 + 546584401725025696
+5*a^34 + 7818703010175000236*a^33 + 13304920141834573258*a^32 + 114357960485
+84276*a^31 + 4331469251417299625*a^30 + 17686902244060347692*a^29 + 17607783
+19947200401*a^28 + 3012511890706784509*a^27 + 18319341252918336566*a^26 + 10
+018340880050704466*a^25 + 3681292000887380307*a^24 + 6241896558174496327*a^2
+3 + 9334414729239110374*a^22 + 14900454697774091776*a^21 + 77193581568725477
+10*a^20 + 7957196232563221737*a^19 + 14008909657978711585*a^18 + 43480361564
+79613902*a^17 + 1768274872694937073*a^16 + 6926632468462411736*a^15 + 138466
+31025657876514*a^14 + 16445358444805977559*a^13 + 3015896265596741617*a^12 +
+ 3099427746327195442*a^11 + 7091419183460950797*a^10 + 13541704365745256080*
+a^9 + 9319609099157088592*a^8 + 3845681432811214920*a^7 + 380965757660125686
+6*a^6 + 14250915374958368396*a^5 + 5948030384875855137*a^4 + 434385110189972
+4971*a^3 + 16736030436363202463*a^2 + 11764704170600631014*a + 1394491261297
+3941130
 ? for(i=1,10,print(ffnbirred(11,i)));
 11
 55
@@ -126,8 +167,6 @@ Mod(4294967310, 4294967311), Mod(1, 4294967311)*x^3 + Mod(1, 4294967311)*x^2
 [t, t^2 + 1, -t^2 - t + 1]~
 ? polrootsff(x^4+1,2,y^2+y+1)
 [Mod(Mod(1, 2), Mod(1, 2)*y^2 + Mod(1, 2)*y + Mod(1, 2))]~
-? t=ffgen(7^4);fflog(t^6,t^2)
-3
 ? t=ffgen(2^64)^((2^64-1)\5);1/t
 x^58 + x^57 + x^56 + x^52 + x^51 + x^49 + x^46 + x^45 + x^42 + x^39 + x^36 +
  x^35 + x^32 + x^30 + x^29 + x^25 + x^23 + x^22 + x^21 + x^20 + x^19 + x^12 
@@ -158,14 +197,6 @@ Mod(6687681666819568403, 18446744073944432641)
 ^2 - 10, x^2 - 8, x^2 - 3, x^2 - 2]~
 ? #polrootsff(x^107+2*x^3+1,3,ffinit(3,107,'a))
 107
-? t=ffprimroot(ffgen(2^61));fflog(t^1234567891012345678,t)
-1234567891012345678
-? t=ffprimroot(ffgen(3^23));fflog(t^12345678910,t)
-12345678910
-? t=ffprimroot(ffgen(5^23));fflog(t^1234567891012345,t)
-1234567891012345
-? t=ffprimroot(ffgen(5^17));fflog(t^123456789101,t)
-123456789101
 ? ffgen(x^2+x+Mod(1,3))
   ***   at top-level: ffgen(x^2+x+Mod(1,3)
   ***                 ^--------------------
@@ -265,16 +296,14 @@ t^4 + t^2
 [3*t^2 + 3*t, 18446744073709551628*t^4 + 5*t^3 + 4*t^2 + 1844674407370955162
 7*t + 18446744073709551628, 18446744073709551628*t^4 + 5*t^3 + 4*t^2 + 18446
 744073709551628*t]~
-? p=2^64+13;g=ffprimroot(ffgen(p^2),&o);a=2*g^0;
-? v=[I,-1,Mat(1),matid(2)/2];
-? for(i=1,#v,print(iferr(fflog(a,g,v[i]),E,E)));
-error("incorrect type in generic discrete logarithm (order factorization) (t
-_COMPLEX).")
-error("incorrect type in generic discrete logarithm (order factorization) (t
-_INT).")
-error("incorrect type in factorback [not a factorization] (t_MAT).")
-error("incorrect type in factorback [not an exponent vector] (t_COL).")
-? g^fflog(a,g,o)==a
+? test(q)=my(t=ffgen(q,'t),M=matrix(10,10,i,j,random(t)));subst(charpoly(M),'x,M)==0;
+? test(nextprime(2^7)^5)
+1
+? test(nextprime(2^15)^5)
+1
+? test(nextprime(2^31)^5)
+1
+? test(nextprime(2^63)^5)
 1
 ? print("Total time spent: ",gettime);
-Total time spent: 2356
+Total time spent: 1440
diff --git a/src/test/32/fflog b/src/test/32/fflog
new file mode 100644
index 0000000..c910d4f
--- /dev/null
+++ b/src/test/32/fflog
@@ -0,0 +1,26 @@
+[1, [1, matrix(0,2)]]
+0
+[2, [2, Mat([2, 1])]]
+1
+[2, [4294967290, [2, 1; 5, 1; 19, 1; 22605091, 1]]]
+17
+[2, [18446744073709551628, [2, 2; 7, 1; 658812288346769701, 1]]]
+17
+3
+1234567891012345678
+12345678910
+1234567891012345
+123456789101
+1
+1
+1
+1
+1
+1
+error("incorrect type in generic discrete logarithm (order factorization) (t
+_COMPLEX).")
+error("incorrect type in generic discrete logarithm (order factorization) (t
+_INT).")
+error("incorrect type in factorback [not a factorization] (t_MAT).")
+error("incorrect type in factorback [not an exponent vector] (t_COL).")
+Total time spent: 3068
diff --git a/src/test/32/for b/src/test/32/for
deleted file mode 100644
index 6cb8b27..0000000
--- a/src/test/32/for
+++ /dev/null
@@ -1,17 +0,0 @@
-18446744073709551614
-18446744073709551615
-18446744073709551616
-18446744073709551617
-18446744073709551618
--18446744073709551618
--18446744073709551617
--18446744073709551616
--18446744073709551615
--18446744073709551614
-4294967279
-4294967291
-4294967311
-18446744073709551557
-18446744073709551629
-18446744073709551653
-Total time spent: 0
diff --git a/src/test/32/forvec b/src/test/32/forvec
new file mode 100644
index 0000000..1b897aa
--- /dev/null
+++ b/src/test/32/forvec
@@ -0,0 +1,96 @@
+[3/2, 3/2, 3/2]
+[3/2, 3/2, 5/2]
+[3/2, 5/2, 3/2]
+[3/2, 5/2, 5/2]
+[5/2, 3/2, 3/2]
+[5/2, 3/2, 5/2]
+[5/2, 5/2, 3/2]
+[5/2, 5/2, 5/2]
+
+[3/2, 3/2, 3/2]
+[3/2, 3/2, 5/2]
+[3/2, 3/2, 7/2]
+[3/2, 5/2, 5/2]
+[3/2, 5/2, 7/2]
+[3/2, 7/2, 7/2]
+[5/2, 5/2, 5/2]
+[5/2, 5/2, 7/2]
+[5/2, 7/2, 7/2]
+[7/2, 7/2, 7/2]
+
+[3/2, 5/2, 7/2]
+[1, 1, 1]
+[1, 1, 2]
+[1, 1, 3]
+[1, 2, 1]
+[1, 2, 2]
+[1, 2, 3]
+[1, 3, 1]
+[1, 3, 2]
+[1, 3, 3]
+[2, 1, 1]
+[2, 1, 2]
+[2, 1, 3]
+[2, 2, 1]
+[2, 2, 2]
+[2, 2, 3]
+[2, 3, 1]
+[2, 3, 2]
+[2, 3, 3]
+[3, 1, 1]
+[3, 1, 2]
+[3, 1, 3]
+[3, 2, 1]
+[3, 2, 2]
+[3, 2, 3]
+[3, 3, 1]
+[3, 3, 2]
+[3, 3, 3]
+
+[1, 1, 1]
+[1, 1, 2]
+[1, 1, 3]
+[1, 2, 2]
+[1, 2, 3]
+[1, 3, 3]
+[2, 2, 2]
+[2, 2, 3]
+[2, 3, 3]
+[3, 3, 3]
+
+[1, 2, 3]
+[1, 1]
+[3/2, 3/2, 3/2]
+[3/2, 3/2, 5/2]
+[3/2, 3/2, 7/2]
+[3/2, 5/2, 5/2]
+[3/2, 5/2, 7/2]
+[3/2, 7/2, 7/2]
+[5/2, 5/2, 5/2]
+[5/2, 5/2, 7/2]
+[5/2, 7/2, 7/2]
+[7/2, 7/2, 7/2]
+
+[3/2, 2, 5/2]
+[3/2, 2, 7/2]
+[3/2, 2, 9/2]
+[3/2, 3, 7/2]
+[3/2, 3, 9/2]
+[3/2, 4, 9/2]
+[5/2, 3, 7/2]
+[5/2, 3, 9/2]
+[5/2, 4, 9/2]
+[]
+  ***   at top-level: forvec(v=[1],)
+  ***                 ^--------------
+  *** forvec: incorrect type in forvec [expected vector not of type [min,MAX]] (t_INT).
+  ***   at top-level: forvec(v=[[1]],)
+  ***                 ^----------------
+  *** forvec: incorrect type in forvec [expected vector not of type [min,MAX]] (t_VEC).
+  ***   at top-level: forvec(v=[[1,I]],)
+  ***                 ^------------------
+  *** forvec: incorrect type in gfloor (t_COMPLEX).
+  ***   at top-level: forvec(v=[[1,1],[1,1
+  ***                 ^--------------------
+  *** forvec: invalid flag in forvec.
+Total time spent: 1
diff --git a/src/test/32/galoisinit b/src/test/32/galoisinit
index 69bd633..2f6dcd1 100644
--- a/src/test/32/galoisinit
+++ b/src/test/32/galoisinit
@@ -92,11 +92,11 @@ x^2 + x - 4
 , 1, 2, 3, 4]), Vecsmall([6, 7, 8, 5, 2, 3, 4, 1]), Vecsmall([7, 8, 5, 6, 3,
  4, 1, 2]), Vecsmall([8, 5, 6, 7, 4, 1, 2, 3])], [Vecsmall([2, 3, 4, 1, 6, 7
 , 8, 5]), Vecsmall([5, 6, 7, 8, 1, 2, 3, 4])], Vecsmall([4, 2])]
-[[x, 0], [x^2 + 1, Mod(-x^5, x^8 - x^6 + x^4 - x^2 + 1)], [x^2 - 2*x - 4, Mo
-d(-2*x^6 + 2*x^4 + 2, x^8 - x^6 + x^4 - x^2 + 1)], [x^2 + 5, Mod(2*x^7 - x^5
- + 2*x^3, x^8 - x^6 + x^4 - x^2 + 1)], [x^4 + 3*x^2 + 1, Mod(x^7 - x^5 + x^3
-, x^8 - x^6 + x^4 - x^2 + 1)], [x^4 - 2*x^3 + 4*x^2 - 8*x + 16, Mod(2*x^2, x
-^8 - x^6 + x^4 - x^2 + 1)], [x^4 - 5*x^2 + 5, Mod(-x^7 + x^5 - x^3 + 2*x, x^
-8 - x^6 + x^4 - x^2 + 1)], [x^8 - x^6 + x^4 - x^2 + 1, Mod(x, x^8 - x^6 + x^
-4 - x^2 + 1)]]
-Total time spent: 2392
+[[x, Mod(0, x^8 - x^6 + x^4 - x^2 + 1)], [x^2 + 1, Mod(-x^5, x^8 - x^6 + x^4
+ - x^2 + 1)], [x^2 - 2*x - 4, Mod(-2*x^6 + 2*x^4 + 2, x^8 - x^6 + x^4 - x^2 
++ 1)], [x^2 + 5, Mod(2*x^7 - x^5 + 2*x^3, x^8 - x^6 + x^4 - x^2 + 1)], [x^4 
++ 3*x^2 + 1, Mod(x^7 - x^5 + x^3, x^8 - x^6 + x^4 - x^2 + 1)], [x^4 - 2*x^3 
++ 4*x^2 - 8*x + 16, Mod(2*x^2, x^8 - x^6 + x^4 - x^2 + 1)], [x^4 - 5*x^2 + 5
+, Mod(-x^7 + x^5 - x^3 + 2*x, x^8 - x^6 + x^4 - x^2 + 1)], [x^8 - x^6 + x^4 
+- x^2 + 1, Mod(x, x^8 - x^6 + x^4 - x^2 + 1)]]
+Total time spent: 2312
diff --git a/src/test/32/gamma b/src/test/32/gamma
index 94ebee7..d8e27bf 100644
--- a/src/test/32/gamma
+++ b/src/test/32/gamma
@@ -3,7 +3,7 @@
 2349794265298068695525*I)*x + (0.090862784286733058570355592072096462602 + 0
 .21088392899265350361451872767550590408*I)*x^2 + (0.034253752000523576920016
 074597694397590 + 0.15168994440796279268955277197772465641*I)*x^3 + (-0.0093
-139210540785894159197859484392067433 + 0.03306465179643991397682862055127742
+139210540785894159197859484392067432 + 0.03306465179643991397682862055127742
 8299*I)*x^4 + (0.0066762623841895560506752315759505427095 + 0.01516404667566
 6586697065188398143396917*I)*x^5 + O(x^6)
 1 - 0.57721566490153286060651209008240243104*x + 0.9890559953279725553953956
@@ -47,6 +47,10 @@ x^5 + O(x^6)
 991759756896 + 2.8949340668482264364724151666460251892*x - 0.077056903159594
 285399738161511449990765*x^2 + 2.1448232337111381915160036965411679028*x^3 +
  O(x^4)
+-3.5449077018110320545963349666822903656 - 0.1293535897955400553154795370758
+8123112*x - 15.838884621997332891305490359174586834*x^2 - 0.0882351409230713
+74511750322744686276244*x^3 - 63.934119924167817737375290277713885431*x^4 - 
+0.042848354492868684268292005312709223076*x^5 + O(x^6)
 -1.0000000000000000000000000000000000000*x^-1 - 0.57721566490153286060651209
 008240243104 + 1.6449340668482264364724151666460251892*x - 1.202056903159594
 2853997381615114499908*x^2 + 1.0823232337111381915160036965411679028*x^3 - 1
@@ -83,4 +87,4 @@ x^-1 - 0.57721566490153286060651209008240243104 + 0.989055995327972555395395
 432 + 417274.602697087076269173737117822293981451080884873662980649365715022
 9604257562187947297228515985952270200052467287642139293693997776338197086953
 142287383*I
-Total time spent: 12
+Total time spent: 20
diff --git a/src/test/32/genus2red b/src/test/32/genus2red
index fd0880a..9ff3873 100644
--- a/src/test/32/genus2red
+++ b/src/test/32/genus2red
@@ -643,76 +643,76 @@ ge 184", [9]]]]
 [59049, Mat([3, 10]), x^6 - 6*x^3 + 81*x^2 + 9, [3, [5, [Mod(0, 3), Mod(0, 3
 )]], ["[III{8}] page 184", [9]]]]
    echo = 1 (on)
-? genus2red(0,-x^6-6*x^2-7,3)
+? genus2red(-x^6-6*x^2-7,3)
 [81, Mat([3, 4]), -x^6 - 6*x^2 - 7, [3, [7, []], ["(tame) [I*{1}-I*{1}-0] pa
 ge 180", [4, 4]]]]
-? genus2red(0,-9*x^6+6*x^5-8*x^4-5*x^3+5*x^2-10*x+3,3)
+? genus2red(-9*x^6+6*x^5-8*x^4-5*x^3+5*x^2-10*x+3,3)
 [9, Mat([3, 2]), -9*x^6 + 6*x^5 - 8*x^4 - 5*x^3 + 5*x^2 - 10*x + 3, [3, [3, 
 []], ["(tame) [I{2-8-0}] page 179", [8, 2]]]]
-? genus2red(0,3*x^6+3*x^4+3*x^3+x^2-5*x-5,3)
+? genus2red(3*x^6+3*x^4+3*x^3+x^2-5*x-5,3)
 [27, Mat([3, 3]), -5*x^6 - 5*x^5 + x^4 + 3*x^3 + 3*x^2 + 3, [3, [2, [Mod(0, 
 3)]], ["(tame) [III-II{4}] page 177", [9]]]]
-? genus2red(0,-3*x^6+6*x^5-1*x^4+6*x^3-6*x^2-1*x-6,3)
+? genus2red(-3*x^6+6*x^5-1*x^4+6*x^3-6*x^2-1*x-6,3)
 [3, Mat([3, 1]), -2187*x^6 - 2430*x^5 - 1089*x^4 - 242*x^3 - 26*x^2 - x, [3,
  [6, [Mod(2, 3)]], ["(tame) [I{1}-I{0}-1] page 170", []]]]
-? genus2red(0,(x^3+2*x+1)*(x^3+3^2*x^2+3^8),3)
+? genus2red((x^3+2*x+1)*(x^3+3^2*x^2+3^8),3)
 [3, Mat([3, 1]), 729*x^6 + 729*x^5 + 18*x^4 + 6580*x^3 + x^2 + 162*x + 9, [3
 , [6, [Mod(1, 3)]], ["(tame) [I{2}-I{0}-1] page 170", [2]]]]
 ? P=x^6+4*x^5-24*x^4-16*x^3-52*x^2-48*x;
-? genus2red(0,P,3)
+? genus2red(P,3)
 [9, Mat([3, 2]), 729*x^6 + 2268*x^5 + 2664*x^4 + 1520*x^3 + 428*x^2 + 48*x, 
 [3, [7, []], ["(tame) [I{2}-I{2}-1] page 179", [2, 2]]]]
 ? P=x^6+4*x^5+24*x^4+32*x^3+56*x^2+48*x+24;
-? genus2red(0,P,3)
+? genus2red(P,3)
 [9, Mat([3, 2]), 729*x^6 + 2268*x^5 + 3096*x^4 + 2336*x^3 + 1016*x^2 + 240*x
  + 24, [3, [7, []], ["(tame) [I{1}-I{1}-1] page 179", []]]]
 ? P=24*x^5+56*x^4+76*x^3+33*x^2-4*x-20;
-? genus2red(0,P,3)
+? genus2red(P,3)
 [9, Mat([3, 2]), 1944*x^5 + 5904*x^4 + 7196*x^3 + 4397*x^2 + 1346*x + 165, [
 3, [7, []], ["(tame) [I{2}-I{2}-1] page 179", [2, 2]]]]
 ? P=-3*x^6+6*x^5-25*x^4+36*x^3-69*x^2+38*x-39;
-? genus2red(0,P,3)
+? genus2red(P,3)
 [9, Mat([3, 2]), -2187*x^6 - 6804*x^5 - 9000*x^4 - 6464*x^3 - 2656*x^2 - 592
 *x - 56, [3, [7, []], ["(tame) [I{1}-I{1}-1] page 179", []]]]
 ? P=-5*x^5+5*x^4+10*x^3-7;
-? genus2red(1,P,3)
+? genus2red([P,1],3)
 [9, Mat([3, 2]), -1620*x^5 - 2520*x^4 - 1520*x^3 - 440*x^2 - 60*x - 3, [3, [
 7, []], ["(tame) [I{1}-I{2}-1] page 179", [2]]]]
 ? P=-5*x^6-3*x^5-10*x^4-10*x^3-7;
-? genus2red(1,P,3)
+? genus2red([P,1],3)
 [3, Mat([3, 1]), -14580*x^6 - 59292*x^5 - 100800*x^4 - 91720*x^3 - 47120*x^2
  - 12960*x - 1491, [3, [6, [Mod(1, 3)]], ["(tame) [I{1}-I{0}-1] page 170", [
 ]]]]
 ? P=3*x^5+5*x^4+5*x-4;
-? genus2red(1,P,3)
+? genus2red([P,1],3)
 [3, Mat([3, 1]), 972*x^5 + 1260*x^4 + 640*x^3 + 160*x^2 + 20*x + 1, [3, [6, 
 [Mod(1, 3)]], ["(tame) [I{2}-I{0}-1] page 170", [2]]]]
 ? Q=x^2+x;P=-9*x^6+6*x^5-8*x^4-5*x^3+5*x^2-10*x+3;
-? genus2red(Q,P,3)
+? genus2red([P,Q],3)
 [3, Mat([3, 1]), -26244*x^6 - 138024*x^5 - 302679*x^4 - 354290*x^3 - 233475*
 x^2 - 82136*x - 12052, [3, [6, [Mod(0, 3)]], ["(tame) [I{12}-I{0}-1] page 17
 0", [12]]]]
 ? Q=x^3+1;P=-7*x^6+5*x^3+5*x^2-6*x+1;
-? genus2red(Q,P,3)
+? genus2red([P,Q],3)
 [3, Mat([3, 1]), -27*x^6 + 22*x^3 + 20*x^2 - 24*x + 5, [3, [6, [Mod(2, 3)]],
  ["(tame) [I{1}-I{0}-1] page 170", []]]]
-? genus2red(0,27*x^5+97*x^4+118*x^3+60*x^2+13*x+1,3)
+? genus2red(27*x^5+97*x^4+118*x^3+60*x^2+13*x+1,3)
 [729, Mat([3, 6]), 27*x^5 + 367*x^4 + 1974*x^3 + 5256*x^2 + 6933*x + 3627, [
 3, [6, [Mod(0, 3)]], ["[IV-II{6}] page 175", [20]]]]
-? genus2red(x,-x^6-3*x^4-10*x^2-1,3)
+? genus2red([-x^6-3*x^4-10*x^2-1,x],3)
 [729, Mat([3, 6]), -4*x^6 - 12*x^4 - 39*x^2 - 4, [3, [5, [Mod(0, 3), Mod(0, 
 3)]], ["[IV*-IV*-0] pages 160-175", [3, 3]]]]
-? genus2red(x^3+x^2+x+1,-60*x^6-203*x^5-291*x^4-244*x^3-129*x^2-41*x-7)
+? genus2red([-60*x^6-203*x^5-291*x^4-244*x^3-129*x^2-41*x-7,x^3+x^2+x+1])
 [729, [2, -1; 3, 6], -239*x^6 - 810*x^5 - 1161*x^4 - 972*x^3 - 513*x^2 - 162
 *x - 27, [[2, [5, [Mod(0, 2), Mod(0, 2)]], []], [3, [5, [Mod(0, 3), Mod(0, 3
 )]], ["[2IV*-0] page 165", [3]]]]]
-? genus2red(0,6*x^6+5*x^4+x^2+1,7)
+? genus2red(6*x^6+5*x^4+x^2+1,7)
 [2401, Mat([7, 4]), 6*x^6 + 180*x^5 + 2255*x^4 + 15100*x^3 + 57001*x^2 + 115
 010*x + 96901, [7, [5, [Mod(0, 7), Mod(0, 7)]], ["(tame) [II-II-0] page 163"
 , []]]]
-? genus2red(x^3-1,1)
+? genus2red([1,x^3-1])
 [18225, [3, 6; 5, 2], x^6 - 2*x^3 + 5, [[3, [5, [Mod(0, 3), Mod(0, 3)]], ["[
 II-II-0] pages 159-174", []]], [5, [5, [Mod(0, 5), Mod(0, 5)]], ["[I{0}-II-0
 ] page 159", []]]]]
 ? print("Total time spent: ",gettime);
-Total time spent: 72
+Total time spent: 116
diff --git a/src/test/32/help b/src/test/32/help
index eb17c23..118e565 100644
--- a/src/test/32/help
+++ b/src/test/32/help
@@ -15,6 +15,10 @@ new is aliased to:
 
 sin(x): sine of x.
 
+addii: installed function
+library name: addii
+prototype: GG
+
 test1
 
 test2
@@ -36,13 +40,15 @@ Help topics: for a list of relevant subtopics, type ?n for n in
   3: TRANSCENDENTAL functions
   4: NUMBER THEORETICAL functions
   5: Functions related to ELLIPTIC CURVES
-  6: Functions related to general NUMBER FIELDS
-  7: POLYNOMIALS and power series
-  8: Vectors, matrices, LINEAR ALGEBRA and sets
-  9: SUMS, products, integrals and similar functions
- 10: GRAPHIC functions
- 11: PROGRAMMING under GP
- 12: The PARI community
+  6: Functions related to MODULAR FORMS and MODULAR SYMBOLS
+  7: Functions related to general NUMBER FIELDS
+  8: Functions related to central simple ALGEBRAS
+  9: POLYNOMIALS and power series
+ 10: Vectors, matrices, LINEAR ALGEBRA and sets
+ 11: SUMS, products, integrals and similar functions
+ 12: GRAPHIC functions
+ 13: PROGRAMMING under GP
+ 14: The PARI community
 
 Also:
   ? functionname (short on-line help)
@@ -117,8 +123,10 @@ zkst : structure of (Z_K/m)*         bid,                     bnr
 {f}=optional filename. {n}=optional integer
 
 
-cmp      divrem   lex      max      min      shift    shiftmul sign
-vecmax   vecmin   
+cmp      divrem   lex      max      min      powers   shift    shiftmul
+sign     vecmax   vecmin   
+
+test6
 
 List of the PARI types:
   t_INT    : long integers     [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ]
@@ -145,5 +153,12 @@ List of the PARI types:
   t_CLOSURE: functions [ code ] [ arity ] [ code ] [ operand ] [ data ] [ te
 xt ]
   t_ERROR  : error context     [ code ] [ errnum ] [ dat_1 ] ... [ dat_k ]
+  t_INFINITY: a*infinity       [ code ] [ a ]
+
+f =
+  ()->1
+
+g =
+  ()->0
 
 Total time spent: 0
diff --git a/src/test/32/history b/src/test/32/history
index 2e56d9c..daeee45 100644
--- a/src/test/32/history
+++ b/src/test/32/history
@@ -2,17 +2,20 @@
 3
 4
 5
-  ***   History result %-1 not available [%1-%5]
-
+  ***   at top-level: %``````
+  ***                 ^-------
+  *** %: History result %-1 not available [%1-%5].
 0
 3
 3
 1
 1
 1
-  ***   History result %11 not available [%13-%13]
-
-  ***   History result %12 has been deleted (histsize changed)
-
+  ***   at top-level: %``
+  ***                 ^---
+  *** %: History result %11 not available [%13-%13].
+  ***   at top-level: %``
+  ***                 ^---
+  *** %: History result %12 has been deleted (histsize changed).
 1
-Total time spent: 4
+Total time spent: 0
diff --git a/src/test/32/hyperell b/src/test/32/hyperell
new file mode 100644
index 0000000..9226f3b
--- /dev/null
+++ b/src/test/32/hyperell
@@ -0,0 +1,101 @@
+1:1:x - 4
+1:2:x - 4
+2:1:x^2 - x - 20
+2:2:x^2 - 5*x - 20
+2:3:x^2 - x - 60
+2:4:x^2 + 5*x - 20
+3:1:x^3 - 55*x - 68
+3:2:x^3 - 5*x^2 - 26*x + 128
+3:3:x^3 + 2*x^2 - 51*x + 48
+3:4:x^3 - 8*x^2 + 7*x + 30
+3:5:x^3 - x^2 - 38*x + 72
+3:6:x^3 + 6*x^2 - 13*x - 42
+4:1:x^4 - 8*x^3 - 36*x^2 + 360*x - 464
+4:2:x^4 - 10*x^3 + x^2 + 144*x - 136
+4:3:x^4 + 8*x^3 - 21*x^2 - 116*x + 128
+4:4:x^4 + 10*x^3 - 5*x^2 - 200*x - 208
+4:5:x^4 - 8*x^3 - 41*x^2 + 246*x + 584
+4:6:x^4 + 10*x^3 - 51*x^2 - 764*x - 1856
+4:7:x^4 - 8*x^3 - 17*x^2 + 156*x + 24
+4:8:x^4 - 10*x^3 - 18*x^2 + 320*x - 430
+5:1:x^5 + 8*x^4 - 47*x^3 - 356*x^2 + 361*x + 1596
+5:2:x^5 - 99*x^3 + 72*x^2 + 2085*x - 2968
+5:3:x^5 - x^4 - 103*x^3 + 40*x^2 + 2464*x + 1536
+5:4:x^5 - x^4 - 91*x^3 + 114*x^2 + 1761*x - 1496
+5:5:x^5 - 8*x^4 - 68*x^3 + 500*x^2 + 1084*x - 6160
+5:6:x^5 - 2*x^4 - 62*x^3 + 36*x^2 + 838*x + 616
+5:7:x^5 + 5*x^4 - 75*x^3 - 250*x^2 + 1321*x + 852
+5:8:x^5 - 5*x^4 - 57*x^3 + 254*x^2 + 372*x - 1168
+5:9:x^5 + 2*x^4 - 65*x^3 - 162*x^2 + 509*x + 986
+5:10:x^5 - 10*x^4 - 25*x^3 + 398*x^2 - 443*x - 1482
+6:1:x^6 - 8*x^5 - 83*x^4 + 742*x^3 + 547*x^2 - 11058*x + 10184
+6:2:x^6 - 10*x^5 - 71*x^4 + 900*x^3 - 193*x^2 - 14820*x + 25460
+6:3:x^6 + 2*x^5 - 118*x^4 - 184*x^3 + 4023*x^2 + 4302*x - 35264
+6:4:x^6 - 95*x^4 - 2*x^3 + 1927*x^2 - 720*x - 2992
+6:5:x^6 + 5*x^5 - 112*x^4 - 583*x^3 + 2693*x^2 + 16639*x + 17196
+6:6:x^6 + 6*x^5 - 76*x^4 - 405*x^3 + 1226*x^2 + 6194*x + 3960
+6:7:x^6 - 114*x^4 + 27*x^3 + 3176*x^2 - 1940*x - 16768
+6:8:x^6 + x^5 - 116*x^4 - 39*x^3 + 3557*x^2 - 849*x - 19852
+6:9:x^6 + 2*x^5 - 115*x^4 - 108*x^3 + 3251*x^2 - 2214*x - 7692
+6:10:x^6 + 8*x^5 - 84*x^4 - 640*x^3 + 1637*x^2 + 10084*x - 11062
+6:11:x^6 + 8*x^5 - 89*x^4 - 750*x^3 + 1343*x^2 + 14698*x + 9316
+6:12:x^6 + 2*x^5 - 117*x^4 - 240*x^3 + 3607*x^2 + 6492*x - 17696
+1:1:x + 6
+1:2:x - 2
+1:3:x - 6
+2:1:x^2 + 8*x - 2
+2:2:x^2 - 18*x + 81
+2:3:x^2 - 36
+2:4:x^2 + 18*x + 81
+2:5:x^2 + 8*x - 2
+3:1:x^3 + 3*x^2 - 74*x - 48
+3:2:x^3 - 2*x^2 - 76*x + 312
+3:3:x^3 - 12*x^2 - 17*x + 346
+3:4:x^3 + 6*x^2 + 12*x + 8
+3:5:x^3 + 12*x^2 - 17*x - 346
+3:6:x^3 + 2*x^2 - 76*x - 312
+3:7:x^3 + 3*x^2 - 74*x - 48
+4:1:x^4 + 7*x^3 - 69*x^2 - 314*x + 927
+4:2:x^4 - 6*x^3 - 115*x^2 + 468*x + 2592
+4:3:x^4 - 6*x^3 - 54*x^2 + 221*x - 70
+4:4:x^4 + 6*x^3 - 44*x^2 - 320*x - 480
+4:5:x^4 - 60*x^2 + 400
+4:6:x^4 + 6*x^3 - 44*x^2 - 320*x - 480
+4:7:x^4 + 6*x^3 - 54*x^2 - 221*x - 70
+4:8:x^4 - 6*x^3 - 115*x^2 + 468*x + 2592
+4:9:x^4 + 7*x^3 - 69*x^2 - 314*x + 927
+5:1:x^5 + 12*x^4 - 81*x^3 - 1217*x^2 - 15*x + 19944
+5:2:x^5 - 2*x^4 - 118*x^3 + 136*x^2 + 3304*x + 792
+5:3:x^5 - 6*x^4 - 84*x^3 + 504*x^2 + 9*x - 54
+5:4:x^5 + 22*x^4 + 46*x^3 - 2156*x^2 - 18639*x - 44874
+5:5:x^5 + 3*x^4 - 115*x^3 - 123*x^2 + 3194*x - 2760
+5:6:x^5 + 2*x^4 - 40*x^3 - 80*x^2 + 144*x + 288
+5:7:x^5 + 3*x^4 - 115*x^3 - 123*x^2 + 3194*x - 2760
+5:8:x^5 - 22*x^4 + 46*x^3 + 2156*x^2 - 18639*x + 44874
+5:9:x^5 + 6*x^4 - 84*x^3 - 504*x^2 + 9*x + 54
+5:10:x^5 - 2*x^4 - 118*x^3 + 136*x^2 + 3304*x + 792
+5:11:x^5 - 12*x^4 - 81*x^3 + 1217*x^2 - 15*x - 19944
+x^2 + 3*x
+x^2 - 5
+x^2 + x - 5
+x^4 - 20*x^2 - 10*x + 50
+x^4 + 4*x^3 - 14*x^2 - 42*x + 14
+x^4 + 3*x^3 - 27*x^2 - 26*x + 47
+x^2 - 54
+x^2 + 25*x + 125
+x^2 + 23*x - 265
+x^2 - 47*x - 5490
+x^2 + 47*x - 5490
+x^2 - 47*x - 5490
+x^2 - 42*x - 2356
+x^2 + 42*x - 2356
+x^3 + 4*x^2 - 164*x - 180
+x^3 - 10*x^2 - 154*x + 1508
+x^2 + 9*x - 135
+  ***   at top-level: hyperellcharpoly((25
+  ***                 ^--------------------
+  *** hyperellcharpoly: domain error in hyperellpadicfrobenius: H is singular at 5
+  ***   at top-level: hyperellcharpoly((25
+  ***                 ^--------------------
+  *** hyperellcharpoly: domain error in hyperellpadicfrobenius: H is singular at 5
+Total time spent: 3264
diff --git a/src/test/32/ideal b/src/test/32/ideal
index 3193053..9d792ee 100644
--- a/src/test/32/ideal
+++ b/src/test/32/ideal
@@ -142,6 +142,11 @@
 [249/2401, 1644/2401]~
 [-7, -14]~
 [14, 0]~
+[1, 0]
+[2, [0, -4]~]
+[3, [8/125, 0]~]
+[4, [0, 1]~]
+[]
   *** nfinit: Warning: non-monic polynomial. Result of the form [nf,c].
 [[2, [0, 1]~, 2, 1, [0, -2; 1, 0]]]
 Total time spent: 8
diff --git a/src/test/32/idealramgroups b/src/test/32/idealramgroups
index 07c4a14..2ac1b97 100644
--- a/src/test/32/idealramgroups
+++ b/src/test/32/idealramgroups
@@ -10,7 +10,7 @@
 29:[[2, 1]]
 31:[[15, 1]]
 37:[[15, 1], [3, 1]]
-[Vecsmall([5, 6, 4, 3, 1, 2]), [[[Vecsmall([5, 6, 4, 3, 1, 2])], Vecsmall([2
+[Vecsmall([6, 3, 2, 5, 4, 1]), [[[Vecsmall([6, 3, 2, 5, 4, 1])], Vecsmall([2
 ])]]]
 [[[Vecsmall([2, 1, 4, 3, 6, 5, 8, 7]), Vecsmall([3, 4, 1, 2, 7, 8, 5, 6]), V
 ecsmall([5, 6, 7, 8, 1, 2, 3, 4])], Vecsmall([2, 2, 2])], [[Vecsmall([2, 1, 
@@ -18,4 +18,4 @@ ecsmall([5, 6, 7, 8, 1, 2, 3, 4])], Vecsmall([2, 2, 2])], [[Vecsmall([2, 1,
 [[Vecsmall([2, 1, 4, 3, 6, 5, 8, 7]), Vecsmall([3, 4, 1, 2, 7, 8, 5, 6])], V
 ecsmall([2, 2])], [[Vecsmall([2, 1, 4, 3, 6, 5, 8, 7])], Vecsmall([2])], [[V
 ecsmall([2, 1, 4, 3, 6, 5, 8, 7])], Vecsmall([2])]]
-Total time spent: 1188
+Total time spent: 996
diff --git a/src/test/32/incgam b/src/test/32/incgam
index 952c47f..6bfddc1 100644
--- a/src/test/32/incgam
+++ b/src/test/32/incgam
@@ -8,8 +8,12 @@
    10 - I,          -100: 5.8 e-37
 1 + 128*I,       -1/10*I: 8.6 e-37
 1 + 128*I, 1/10 - 1/10*I: 2.1 e-37
-      1/2,          -100: 4.7 e-43
-   10 - I,          -100: 7.9 e-56
+        0,          -100: 8.4 e-95
+      1/2,          -100: 3.4 e-43
+   10 - I,    19 + 236*I: 9.0 e-95
+   10 - I,          -100: 9.2 e-56
+1 + 128*I,       -1/10*I: 6.2 e-95
+1 + 128*I, 1/10 - 1/10*I: 1.6 e-94
 1: -37
 2: -37
 3: -38
@@ -66,8 +70,8 @@
 1645655068324986893656866348640914630478382436361571896386505720797343025328
 1801089025819604231751731641093222001525360979162684147070957434471241677012
 3171321323534000876101297696945758112884328591356813522962187412618386959055
-56983544264467232044835043 E-68
+56983544264467232044835371 E-68
   ***   at top-level: eint1(0)
   ***                 ^--------
   *** eint1: domain error in eint1: x = 0
-Total time spent: 188
+Total time spent: 112
diff --git a/src/test/32/intnum b/src/test/32/intnum
index 235b013..cfce8c1 100644
--- a/src/test/32/intnum
+++ b/src/test/32/intnum
@@ -1,7 +1,6 @@
 ? allocatemem(20*10^6);
   ***   Warning: new stack size = 20000000 (19.073 Mbytes).
-? check(a,b)=my(t=abs((a-b)/b));if(t,ceil(log(t)/log(10)),"-oo");
-? oo=[1];
+? check(a,b)=my(t=abs((a-b)/b));if(t,ceil(log(t)/log(10)),-oo);
 ? \p96
    realprecision = 96 significant digits
 ? check(intcirc(s=1,0.5,zeta(s)),1)
@@ -23,19 +22,30 @@
 ? F=truncate(f(t+O(t^7)));
 ? g(x)=if(x>1e-18,f(x),subst(F,t,x));
 ? check(intnum(x=0,[oo,1],f(x)),Euler)
-"-oo"
+-oo
 ? check(intnum(x=0,[oo,1],g(x)),Euler)
-"-oo"
+-oo
 ? check(intnum(x=0,1,1/sqrt(x)),2)
 -59
 ? check(intnum(x=[0,-1/2],1,1/sqrt(x)),2)
-"-oo"
+-oo
+? check(intnum(x=[0,-1/2],[oo,-3/2],1/(sqrt(x)+x^(3/2))),Pi)
+-oo
+? check(intnum(x=[-oo,-3/2],[oo,-3/2],1/(1+abs(x)^(3/2))),8*Pi/sqrt(27))
+-oo
+? f(x)=if(x<0,1/(1+(-x)^(3/2)),1/(1+x^(5/2)));
+? a=4*Pi/sqrt(27)+2*(Pi/5)/sin(2*Pi/5);
+? check(intnum(x=[-oo,-3/2],[oo,-5/2],f(x)),a)
+-oo
+? f(x)=if(x<0,1/(1+(-x)^(3/2)),exp(-x));
+? check(intnum(x=[-oo,-3/2],[oo,1],f(x)),1+4*Pi/sqrt(27))
+-oo
 ? check(intnum(x=0,[oo,1],sin(x)/x),Pi/2)
 -2
 ? check(intnum(x=0,[oo,-I],sin(x)/x),Pi/2)
-"-oo"
+-oo
 ? check(intnum(x=0,[oo,-2*I],sin(2*x)/x),Pi/2)
-"-oo"
+-oo
 ? A=intnum(x=0,1,(1-cos(x))/x^2)+intnum(x=1,oo,1/x^2)-intnum(x=1,[oo,I],cos(x)/x^2);
 ? check(A,Pi/2)
 -96
@@ -47,22 +57,28 @@
 ? check(intnum(x=0,oo,sin(x)^3*exp(-x),tab),3/10)
 -96
 ? check(intnum(x=0,[oo,-I],x^2*sin(x)),-2)
-"-oo"
+-oo
 ? tab=intnuminit(-1,1);
 ? check(intnum(x=-1,1,intnum(y=-sqrt(1-x^2),sqrt(1-x^2),x^2+y^2,tab),tab),Pi/2)
 -93
 ? \p308
    realprecision = 308 significant digits
 ? a=sumpos(n=1,1/(n^3+n+1));
+? b=sumpos(n=1,1/(n^3+n+1),1);
+? check(a,b)
+-307
 ? tab=sumnuminit(2);
 ? b=sumnum(n=1,2,1/(n^3+n+1),tab);
 ? check(a,b)
--305
+-306
 ? check(sumnum(n=1,2,1/(n^3+n+1),tab,1),a)
--305
-? c=sumnum(n=1,2,1/(n^2+1),tab,1);
-? d=sumpos(n=1,1/(n^2+1));
-? check(c,d)
+-306
+? a=sumpos(n=1,1/(n^2+1));
+? b=sumpos(n=1,1/(n^2+1),1);
+? check(a,b)
+-307
+? b=sumnum(n=1,2,1/(n^2+1),tab,1);
+? check(a,b)
 -305
 ? check(sumnum(n=1,2,n^(-4/3),,1),zeta(4/3))
 -110
@@ -84,10 +100,10 @@
    realprecision = 96 significant digits
 ? T=intnuminitgen(t,0,[1],exp(2*sinh(t)));
 ? check(intnum(x=0,[1],1/(1+x^2),T),Pi/2)
-"-oo"
+-oo
 ? T=intnuminitgen(t,0,[[1],1],exp(t-exp(-t)));
 ? check(intnum(x=0,[[1],1],exp(-x),T),1)
-"-oo"
+-oo
 ? intfourierexp(t=0,[[1],1],1/2,exp(-t^2))
 0.07515645001618094506724269142337819200573257288846457257682421833136020654
 01315089580450881170413 - 0.408148557374490719018171389392074027664154880556
@@ -108,10 +124,25 @@
 0.13940279264033098824961630553871957887
 ? intnumromb(x=0,1,sin(x)/x,3)
 0.94608307036718301494135331382317964743
+? intnumromb(x=2,1,x,1)
+-1.4999999999999999999999999999999999999
 ? f(x)=-log(cos(x));
 ? F=truncate(f(t+O(t^16)));
 ? g(x)=if(x>1e-2,f(x),subst(F,t,x));
 ? sumpos(n=1,g(1/n))
-0.94536905472633293526609521540827019810
+0.94536905472633293526609521540827019813
+? sumpos(n=0,0)
+0.E-37
+? intnuminit([oo,1+I],[oo,""])
+  *** intnuminit: Warning: real(z)*imag(z)!=0 in endpoint code, real(z) ignored.
+  ***   at top-level: intnuminit([oo,1+I],
+  ***                 ^--------------------
+  *** intnuminit: incorrect type in intnum [incorrect b] (t_VEC).
+? intnum(x=oo,oo,1)
+  ***   Warning: integral from oo to oo.
+0
+? intnum(x=-oo,-oo,1)
+  ***   Warning: integral from -oo to -oo.
+0
 ? print("Total time spent: ",gettime);
-Total time spent: 20736
+Total time spent: 8489
diff --git a/src/test/32/io b/src/test/32/io
index e25df43..6ef846d 100644
--- a/src/test/32/io
+++ b/src/test/32/io
@@ -2,7 +2,8 @@
 [1, 3]
 1
 setting x
+setting y
 setting F
 setting del
 ()->system(Str("rm -f ",F))
-Total time spent: 4
+Total time spent: 0
diff --git a/src/test/32/ispower b/src/test/32/ispower
index 267ae14..e9e822b 100644
--- a/src/test/32/ispower
+++ b/src/test/32/ispower
@@ -1130,6 +1130,9 @@
 [508, 2044406843184]
 [274, 3873816255479006870044]
 [228, 34028236692093846346337460743176821665314]
+10
+10
+1267650600228229401496703205653
 121
 1
 [0, 0, 1, 0]
@@ -1170,6 +1173,13 @@ t^2 + t + 1
 0
 1
 1
+1/2
+x + 1/2
+1/2
+1
+  ***   at top-level: issquare(Mod(1,4)*(x
+  ***                 ^--------------------
+  *** issquare: sorry, issquare for even characteristic != 2 is not yet implemented.
 0
 -2
 1
@@ -1191,4 +1201,4 @@ x + 2
 121
 187
 1
-Total time spent: 5192
+Total time spent: 3280
diff --git a/src/test/32/isprime b/src/test/32/isprime
index f81e289..bec8f11 100644
--- a/src/test/32/isprime
+++ b/src/test/32/isprime
@@ -20,4 +20,5 @@
 [1, 1, 0]
 [0, 1, 0, 1]
 1
-Total time spent: 17128
+1
+Total time spent: 3000
diff --git a/src/test/32/iterator b/src/test/32/iterator
index 70892cc..a8e3bd4 100644
--- a/src/test/32/iterator
+++ b/src/test/32/iterator
@@ -1,3 +1,31 @@
+18446744073709551614
+18446744073709551615
+18446744073709551616
+18446744073709551617
+18446744073709551618
+-18446744073709551618
+-18446744073709551617
+-18446744073709551616
+-18446744073709551615
+-18446744073709551614
+4294967279
+4294967291
+4294967311
+18446744073709551557
+18446744073709551629
+18446744073709551653
+0.50000000000000000000000000000000000000
+1.5000000000000000000000000000000000000
+2.5000000000000000000000000000000000000
+3
+6
+9
+12
+5 3 1 
+1 2 5 6 9 10 
+  ***   at top-level: forprime(p=2,10,p=4)
+  ***                                   ^--
+  ***   prime index read-only: was changed to 4.
 4
 6
 8
@@ -19,4 +47,13 @@
   ***   at top-level: forcomposite(a=6,12,print(a);a=1)
   ***                                     ^-------------
   ***   index read-only: was changed to 1.
+[1, 5]
+[1, 6]
+[1, 7]
+[1, 8]
+[2, 5]
+[2, 7]
+[2, 8]
+[3, 5]
+[4, 5]
 Total time spent: 0
diff --git a/src/test/32/kernel b/src/test/32/kernel
index 9a23dd7..b462b03 100644
--- a/src/test/32/kernel
+++ b/src/test/32/kernel
@@ -1,23 +1,23 @@
 INT: 187654321
-conv:40000003  0b2f60b1  
-+:40000003  0a72ff63  
--:40000003  0bebc1ff  
-*:c0000004  00083b0b  5e0e86ee  
-/:c0000003  0000000f  
-rem:40000003  0025ad1f  
+conv:signe: 1, 0b2f60b1  
++:signe: 1, 0a72ff63  
+-:signe: 1, 0bebc1ff  
+*:signe: -1, 00083b0b  5e0e86ee  
+/:signe: -1, 0000000f  
+rem:signe: 1, 0025ad1f  
 pow:
-40000004  007d1b13  db833a61  
-40000006  00003d23  74418fff  02bee98c  c29618c1  
-40000009  0e99ea50  3d586253  467c3cea  a7f1a742  85bba548  639e3a9d  8890c181  
-40000010  00d5322a  b115c7b2  9cf0c571  1679c253  8cea7ca0  1cbe7596  78ae7d09  c969dc26  cd42e2ad  51204d31  635bced8  66d36dbb  0351ebad  5363c301  
-4000001e  0000b18c  84df6289  66df9491  766a39a4  0685a8a3  cfc68c74  4d9dcb91  02634462  b398839e  1a6892ef  5efe0281  bcae4afb  eb64fcab  f930fa7a  00f01335  2a5dc7c3  4295b5c3  b031c96e  a5c19079  8e647dac  09e2091e  67abbc58  c118d1b7  76f5e31c  e97a9180  140e859c  64a53cad  0d508601  
-invmod:4000001e  000089fe  3c4ba859  b9472dac  d0585e64  b5311881  edf8024b  aaf6ce9e  98d94a2d  b253c748  bc185be1  6de1e5f8  831bbecd  a3d629dc  0fc9440e  b0ab325d  53dd21c5  9fb7fc20  cc22d98c  e8fe6eca  928c7f4f  a3861061  a7ab0bdc  71deda26  17a28387  77487563  9f0f88ac  424ca4d5  3dcae2a5  
+signe: 1, 007d1b13  db833a61  
+signe: 1, 00003d23  74418fff  02bee98c  c29618c1  
+signe: 1, 0e99ea50  3d586253  467c3cea  a7f1a742  85bba548  639e3a9d  8890c181  
+signe: 1, 00d5322a  b115c7b2  9cf0c571  1679c253  8cea7ca0  1cbe7596  78ae7d09  c969dc26  cd42e2ad  51204d31  635bced8  66d36dbb  0351ebad  5363c301  
+signe: 1, 0000b18c  84df6289  66df9491  766a39a4  0685a8a3  cfc68c74  4d9dcb91  02634462  b398839e  1a6892ef  5efe0281  bcae4afb  eb64fcab  f930fa7a  00f01335  2a5dc7c3  4295b5c3  b031c96e  a5c19079  8e647dac  09e2091e  67abbc58  c118d1b7  76f5e31c  e97a9180  140e859c  64a53cad  0d508601  
+invmod:signe: 1, 000089fe  3c4ba859  b9472dac  d0585e64  b5311881  edf8024b  aaf6ce9e  98d94a2d  b253c748  bc185be1  6de1e5f8  831bbecd  a3d629dc  0fc9440e  b0ab325d  53dd21c5  9fb7fc20  cc22d98c  e8fe6eca  928c7f4f  a3861061  a7ab0bdc  71deda26  17a28387  77487563  9f0f88ac  424ca4d5  3dcae2a5  
 
 REAL: 187654321.000000
-conv1:6000001b  b2f60b10  00000000  
-conv2:6000001b  b2f60b10  00000000  
-+:6000001b  a72ff630  00000000  
--:6000001b  bebc1ff0  00000000  
-*:e0000033  83b0b5e0  e86ee000  
-/:e0000003  f3333482  0be1df0a  
-gcc bug?:60000000  c0000000  00000000  
+conv1:signe: 1, expo: 27, b2f60b10  00000000  
+conv2:signe: 1, expo: 27, b2f60b10  00000000  
++:signe: 1, expo: 27, a72ff630  00000000  
+-:signe: 1, expo: 27, bebc1ff0  00000000  
+*:signe: -1, expo: 51, 83b0b5e0  e86ee000  
+/:signe: -1, expo: 3, f3333482  0be1df0a  
+gcc bug?:signe: 1, expo: 0, c0000000  00000000  
diff --git a/src/test/32/krasner b/src/test/32/krasner
index db79096..6b466b7 100644
--- a/src/test/32/krasner
+++ b/src/test/32/krasner
@@ -1,4 +1,3 @@
-  ***   Warning: new stack size = 20000000 (19.073 Mbytes).
 [[0, 1, 3, 0], [2, 3, 1, 2]]
 [[0, 1, 5, 0], [4, 5, 1, 4]]
 [[0, 1, 7, 0], [6, 7, 1, 6]]
@@ -86,15 +85,11 @@
 15, 90], [90, 7, 15, 90], [98, 15, 7, 98], [100, 21, 5, 100], [102, 35, 3, 1
 02], [102, 35, 3, 102], [102, 35, 3, 102], [104, 105, 1, 104]]
 [[0, 1, 21, 0], [14, 3, 7, 14], [18, 7, 3, 18], [20, 21, 1, 20]]
-[[0, 1, 55, 0], [44, 5, 11, 44], [50, 11, 5, 50], [50, 11, 5, 50], [50, 11, 
-5, 50], [50, 11, 5, 50], [50, 11, 5, 50], [50, 11, 5, 50], [50, 11, 5, 50], 
-[50, 11, 5, 50], [50, 11, 5, 50], [50, 11, 5, 50], [50, 11, 5, 50], [54, 55,
- 1, 54], [54, 55, 1, 54], [54, 55, 1, 54], [54, 55, 1, 54], [54, 55, 1, 54],
- [54, 55, 1, 54], [54, 55, 1, 54], [54, 55, 1, 54], [54, 55, 1, 54], [54, 55
-, 1, 54], [54, 55, 1, 54]]
-[[0, 1, 12, 0], [6, 2, 6, 6], [6, 2, 6, 6], [8, 3, 4, 8], [8, 3, 4, 8], [9, 
-4, 3, 9], [9, 4, 3, 9], [10, 6, 2, 10], [10, 6, 2, 10], [10, 6, 2, 10], [10,
- 6, 2, 10], [11, 12, 1, 11], [11, 12, 1, 11]]
+[[0, 1, 75, 0], [50, 3, 25, 50], [60, 5, 15, 60], [70, 15, 5, 70], [72, 25, 
+3, 72], [74, 75, 1, 74]]
+[[0, 1, 18, 0], [9, 2, 9, 9], [9, 2, 9, 9], [12, 3, 6, 12], [12, 3, 6, 12], 
+[15, 6, 3, 15], [15, 6, 3, 15], [16, 9, 2, 16], [16, 9, 2, 16], [17, 18, 1, 
+17], [17, 18, 1, 17]]
 [[12, 2, 4, 12], [12, 2, 4, 12], [12, 2, 4, 12], [12, 2, 4, 12], [12, 2, 4, 
 12], [12, 2, 4, 12], [12, 2, 4, 12], [12, 2, 4, 12], [12, 2, 4, 12], [12, 2,
  4, 12], [12, 2, 4, 12], [12, 2, 4, 12], [12, 4, 2, 12], [12, 4, 2, 12], [12
@@ -102,8 +97,19 @@
  [12, 4, 2, 12], [12, 4, 2, 12], [12, 4, 2, 12], [12, 4, 2, 12], [12, 4, 2, 
 12], [12, 8, 1, 12], [12, 8, 1, 12], [12, 8, 1, 12], [12, 8, 1, 12], [12, 8,
  1, 12], [12, 8, 1, 12]]
-15
+[[0, 1, 30, 0], [15, 2, 15, 15], [15, 2, 15, 15], [20, 3, 10, 20], [20, 3, 1
+0, 20], [20, 3, 10, 20], [24, 5, 6, 24], [24, 5, 6, 24], [24, 5, 6, 24], [25
+, 6, 5, 25], [25, 6, 5, 25], [25, 6, 5, 25], [25, 6, 5, 25], [25, 6, 5, 25],
+ [25, 6, 5, 25], [27, 10, 3, 27], [27, 10, 3, 27], [28, 15, 2, 28], [28, 15,
+ 2, 28], [28, 15, 2, 28], [28, 15, 2, 28], [28, 15, 2, 28], [28, 15, 2, 28],
+ [28, 15, 2, 28], [28, 15, 2, 28], [28, 15, 2, 28], [29, 30, 1, 29], [29, 30
+, 1, 29], [29, 30, 1, 29], [29, 30, 1, 29], [29, 30, 1, 29], [29, 30, 1, 29]
+]
+[[0, 1, 8, 0], [4, 2, 4, 4], [4, 2, 4, 4], [6, 4, 2, 6], [6, 4, 2, 6], [6, 4
+, 2, 6], [6, 4, 2, 6], [7, 8, 1, 7], [7, 8, 1, 7], [7, 8, 1, 7], [7, 8, 1, 7
+]]
 [[0, 1, 2, 0], [1, 2, 1, 1], [1, 2, 1, 1]]
+15
 [[0, 1, 4, 0], [4, 2, 2, 4], [4, 2, 2, 4], [4, 2, 2, 4], [4, 2, 2, 4], [4, 4
 , 1, 4], [6, 2, 2, 6], [6, 2, 2, 6], [6, 2, 2, 6], [6, 2, 2, 6], [6, 2, 2, 6
 ], [6, 2, 2, 6], [6, 4, 1, 6], [6, 4, 1, 6], [6, 4, 1, 6], [8, 4, 1, 8], [8,
@@ -116,4 +122,5 @@
 , 11], [11, 4, 1, 11], [11, 4, 1, 11], [11, 4, 1, 11], [11, 4, 1, 11], [11, 
 4, 1, 11], [11, 4, 1, 11], [11, 4, 1, 11], [11, 4, 1, 11], [11, 4, 1, 11], [
 11, 4, 1, 11], [11, 4, 1, 11], [11, 4, 1, 11]]
-Total time spent: 2896
+[0, 2]
+Total time spent: 4184
diff --git a/src/test/32/lambert b/src/test/32/lambert
index d01050f..f7cba91 100644
--- a/src/test/32/lambert
+++ b/src/test/32/lambert
@@ -12,4 +12,7 @@
 0.99999999999999999999999999999999999999999999999999999999999999999999999999
 9999999999999999999999999999999999999999999999999999999999999999999999999999
 9999999999999999999999999999999999999999999999999999999999999
-Total time spent: 0
+  ***   at top-level: lambertw(1/x)
+  ***                 ^-------------
+  *** lambertw: domain error in lambertw: valuation < 0
+Total time spent: 12
diff --git a/src/test/32/lex b/src/test/32/lex
index 5a2307c..1629710 100644
--- a/src/test/32/lex
+++ b/src/test/32/lex
@@ -26,4 +26,14 @@
 [6, 6, 0]
 [6, 7, -1]
 [7, 7, 0]
-Total time spent: 0
+0
+1
+-1
+-1
+1
+-1
+1
+1
+1
+-1
+Total time spent: 4
diff --git a/src/test/32/lindep b/src/test/32/lindep
index bb7d035..26a1368 100644
--- a/src/test/32/lindep
+++ b/src/test/32/lindep
@@ -15,5 +15,5 @@ x^2 + (-y^3 - y^2 - 5*y - 1)
   ***                 ^------------
   *** algdep: domain error in algdep: degree < 0
 x^2 - 2
-[0, 0, 0]~
-Total time spent: 0
+[Mod(0, E^3), Mod(0, E^3), Mod(0, E^3)]~
+Total time spent: 4
diff --git a/src/test/32/linear b/src/test/32/linear
index b757898..1c7e970 100644
--- a/src/test/32/linear
+++ b/src/test/32/linear
@@ -270,37 +270,37 @@ Vecsmall([3])
 
 ? matkerint(matrix(4,4,x,y,x*y))
 
-[-1 -1 -1]
+[ 1 -1 -1]
 
-[-1  0  1]
+[ 0 -1  1]
 
-[ 1 -1  1]
+[ 1  1  1]
 
-[ 0  1 -1]
+[-1  0 -1]
 
 ? matkerint(matrix(4,4,x,y,x*y),1)
 
-[-1 -1 -1]
+[ 1 -1 -1]
 
-[-1  0  1]
+[ 0 -1  1]
 
-[ 1 -1  1]
+[ 1  1  1]
 
-[ 0  1 -1]
+[-1  0 -1]
 
 ? matkerint(matrix(4,6,x,y,2520/(x+y)))
 
-[   3    1]
+[ -3   -1]
 
-[ -30  -15]
+[ 30   15]
 
-[  70   70]
+[-70  -70]
 
-[   0 -140]
+[  0  140]
 
-[-126  126]
+[126 -126]
 
-[  84  -42]
+[-84   42]
 
 ? matmuldiagonal(amat,[1,2,3,4,5,6,7])
 
@@ -515,33 +515,33 @@ Vecsmall([3])
 
 [1 1 27 -27 69   0 141]
 
-[0 1  5 -23 35 -24  50]
+[0 1  4 -23 34 -24  49]
 
-[0 1  4 -22 19 -24  24]
+[0 1  3 -22 18 -24  23]
 
-[0 1  4 -21 11 -19  14]
+[0 1  3 -21 10 -19  13]
 
-[0 1  4 -20  7 -14   9]
+[0 1  3 -20  6 -14   8]
 
-[0 1  4 -19  5 -10   6]
+[0 1  3 -19  4 -10   5]
 
-[0 1  4 -18  4  -7   4]
+[0 1  3 -18  3  -7   3]
 
 ? qflllgram(m,1)
 
 [1 1 27 -27 69   0 141]
 
-[0 1  5 -23 35 -24  50]
+[0 1  4 -23 34 -24  49]
 
-[0 1  4 -22 19 -24  24]
+[0 1  3 -22 18 -24  23]
 
-[0 1  4 -21 11 -19  14]
+[0 1  3 -21 10 -19  13]
 
-[0 1  4 -20  7 -14   9]
+[0 1  3 -20  6 -14   8]
 
-[0 1  4 -19  5 -10   6]
+[0 1  3 -19  4 -10   5]
 
-[0 1  4 -18  4  -7   4]
+[0 1  3 -18  3  -7   3]
 
 ? qflllgram(mp~*mp,4)
 [[-420, -420, 840, 630, 2982, -1092, 757; -210, -280, 630, 504, 2415, -876, 
@@ -676,4 +676,4 @@ Vecsmall([4, 3, 2, 1])
 [1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10]
 ? if(getheap()!=HEAP,getheap())
 ? print("Total time spent: ",gettime);
-Total time spent: 12
+Total time spent: 7
diff --git a/src/test/32/list b/src/test/32/list
index 368fa62..51397a2 100644
--- a/src/test/32/list
+++ b/src/test/32/list
@@ -23,4 +23,10 @@ List([y, y*x])
 1
 Mod(1, 3)
 Mod(22, 30)
+List([0, 1])
+1
+2
+List([2, 2, 3])
+3
+List([3, 2, 3])
 Total time spent: 28
diff --git a/src/test/32/mat b/src/test/32/mat
index e7c1b62..cae2cf9 100644
--- a/src/test/32/mat
+++ b/src/test/32/mat
@@ -4,6 +4,8 @@ error("impossible inverse in gdiv: [Mod(0, 2), Mod(0, 2); Mod(0, 2), Mod(0,
 [0, 2]
 1
 1
+[[;], [;]]
+[[], [;]]
   ***   at top-level: mathouseholder(1,1)
   ***                 ^-------------------
   *** mathouseholder: incorrect type in mathouseholder (t_INT).
@@ -322,6 +324,11 @@ Mod(18446744073709551628, 18446744073709551629)
 
 [                                         1]
 
+
+[-1]
+
+[ 1]
+
 3
 0
 error("inconsistent dimensions in gtrace.")
@@ -358,4 +365,88 @@ od(0, 18446744073709551629); Mod(7, 18446744073709551629), Mod(8, 1844674407
 0
 2
 17
-Total time spent: 56
+  ***   at top-level: vecsum(1)
+  ***                 ^---------
+  *** vecsum: incorrect type in vecsum (t_INT).
+  ***   at top-level: 1~
+  ***                 ^--
+  *** _~: incorrect type in gtrans (t_INT).
+0
+0
+0
+Vecsmall([0, 0, 0])
+Vecsmall([3, 12, 27])
+3
+0
+Vecsmall([2, 2, 0, -4, -10])
+2
+  ***   at top-level: vectorsmall(3,i,i^100)
+  ***                                 ^------
+  ***   overflow in t_INT-->long assignment.
+
+[1 0 0]
+
+[0 0 1]
+
+
+[1 0 0]
+
+[0 0 1]
+
+
+[1 0 0]
+
+[0 0 1]
+
+
+[1 0]
+
+[1 0]
+
+
+[1 2]
+
+[0 1]
+
+
+[1 2]
+
+[3 4]
+
+
+[1 0 0]
+
+[0 0 1]
+
+
+[1 0 0]
+
+[0 0 1]
+
+
+[1 0 0]
+
+[0 0 1]
+
+  ***   at top-level: m[1,]=[1,2]
+  ***                 ^-----------
+  ***   inconsistent dimensions in matrix row assignment.
+  ***   at top-level: m[1,]=[1,2,3,4]
+  ***                 ^---------------
+  ***   inconsistent dimensions in matrix row assignment.
+  ***   at top-level: m[1,]=[1,2,3]~
+  ***                 ^--------------
+  ***   incorrect type in matrix row assignment (t_COL).
+[1, 2, 3]
+
+[1 2 3]
+
+[1 2 3]
+
+[2, 4, 6]
+
+[2 4 6]
+
+[1 2 3]
+
+Total time spent: 60
diff --git a/src/test/32/matsnf b/src/test/32/matsnf
index 487131a..42a7653 100644
--- a/src/test/32/matsnf
+++ b/src/test/32/matsnf
@@ -5,322 +5,118 @@ x^2 + 10*a*x + 27*a^2
 [2, 1]
 [X^2 + 10*X + 27, X^2 + 10*X + 27, 1, 1]
 x^2 - 2*a*x + (a^2 - d^2)
-[Mat(1), Mat(1)]
-[[0, -1; 1, 2], [1, -1; 0, 1]]
-[[0, 0, 1; 1, 0, -3; 0, 1, 3], [1, -2, 1; 0, 3, -2; 0, -1, 1]]
-[[0, 0, 0, -1; 1, 0, 0, 4; 0, 1, 0, -6; 0, 0, 1, 4], [1, -3, 3, -1; 0, 6, -8
-, 3; 0, -4, 7, -3; 0, 1, -2, 1]]
-[[0, 0, 0, 0, 1; 1, 0, 0, 0, -5; 0, 1, 0, 0, 10; 0, 0, 1, 0, -10; 0, 0, 0, 1
-, 5], [1, -4, 6, -4, 1; 0, 10, -20, 15, -4; 0, -10, 25, -21, 6; 0, 5, -14, 1
-3, -4; 0, -1, 3, -3, 1]]
-[[0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 6; 0, 1, 0, 0, 0, -15; 0, 0, 1, 0, 0, 20
-; 0, 0, 0, 1, 0, -15; 0, 0, 0, 0, 1, 6], [1, -5, 10, -10, 5, -1; 0, 15, -40,
- 45, -24, 5; 0, -20, 65, -81, 46, -10; 0, 15, -54, 73, -44, 10; 0, -6, 23, -
-33, 21, -5; 0, 1, -4, 6, -4, 1]]
-[[0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, -7; 0, 1, 0, 0, 0, 0, 21; 0, 0, 1, 
-0, 0, 0, -35; 0, 0, 0, 1, 0, 0, 35; 0, 0, 0, 0, 1, 0, -21; 0, 0, 0, 0, 0, 1,
- 7], [1, -6, 15, -20, 15, -6, 1; 0, 21, -70, 105, -84, 35, -6; 0, -35, 140, 
--231, 196, -85, 15; 0, 35, -154, 273, -244, 110, -20; 0, -21, 98, -183, 171,
- -80, 15; 0, 7, -34, 66, -64, 31, -6; 0, -1, 5, -10, 10, -5, 1]]
-[[0, 0, 0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 0, 0, 8; 0, 1, 0, 0, 0, 0, 0, -28;
- 0, 0, 1, 0, 0, 0, 0, 56; 0, 0, 0, 1, 0, 0, 0, -70; 0, 0, 0, 0, 1, 0, 0, 56;
- 0, 0, 0, 0, 0, 1, 0, -28; 0, 0, 0, 0, 0, 0, 1, 8], [1, -7, 21, -35, 35, -21
-, 7, -1; 0, 28, -112, 210, -224, 140, -48, 7; 0, -56, 266, -546, 616, -400, 
-141, -21; 0, 70, -364, 798, -944, 635, -230, 35; 0, -56, 308, -708, 871, -60
-5, 225, -35; 0, 28, -160, 381, -484, 346, -132, 21; 0, -8, 47, -115, 150, -1
-10, 43, -7; 0, 1, -6, 15, -20, 15, -6, 1]]
-[[0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, -9; 0, 1, 0, 0, 0, 0, 0
-, 0, 36; 0, 0, 1, 0, 0, 0, 0, 0, -84; 0, 0, 0, 1, 0, 0, 0, 0, 126; 0, 0, 0, 
-0, 1, 0, 0, 0, -126; 0, 0, 0, 0, 0, 1, 0, 0, 84; 0, 0, 0, 0, 0, 0, 1, 0, -36
-; 0, 0, 0, 0, 0, 0, 0, 1, 9], [1, -8, 28, -56, 70, -56, 28, -8, 1; 0, 36, -1
-68, 378, -504, 420, -216, 63, -8; 0, -84, 462, -1134, 1596, -1380, 729, -217
-, 28; 0, 126, -756, 1974, -2904, 2595, -1406, 427, -56; 0, -126, 798, -2178,
- 3321, -3055, 1695, -525, 70; 0, 84, -552, 1557, -2444, 2306, -1308, 413, -5
-6; 0, -36, 243, -703, 1130, -1090, 631, -203, 28; 0, 9, -62, 183, -300, 295,
- -174, 57, -8; 0, -1, 7, -21, 35, -35, 21, -7, 1]]
-[[0, 0, 0, 0, 0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 10; 0, 1, 0, 0, 
-0, 0, 0, 0, 0, -45; 0, 0, 1, 0, 0, 0, 0, 0, 0, 120; 0, 0, 0, 1, 0, 0, 0, 0, 
-0, -210; 0, 0, 0, 0, 1, 0, 0, 0, 0, 252; 0, 0, 0, 0, 0, 1, 0, 0, 0, -210; 0,
- 0, 0, 0, 0, 0, 1, 0, 0, 120; 0, 0, 0, 0, 0, 0, 0, 1, 0, -45; 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 10], [1, -9, 36, -84, 126, -126, 84, -36, 9, -1; 0, 45, -240, 6
-30, -1008, 1050, -720, 315, -80, 9; 0, -120, 750, -2142, 3612, -3900, 2745, 
--1225, 316, -36; 0, 210, -1428, 4326, -7608, 8475, -6110, 2779, -728, 84; 0,
- -252, 1806, -5706, 10377, -11875, 8751, -4053, 1078, -126; 0, 210, -1560, 5
-085, -9500, 11126, -8364, 3941, -1064, 126; 0, -120, 915, -3055, 5834, -6970
-, 5335, -2555, 700, -84; 0, 45, -350, 1191, -2316, 2815, -2190, 1065, -296, 
-36; 0, -10, 79, -273, 539, -665, 525, -259, 73, -9; 0, 1, -8, 28, -56, 70, -
-56, 28, -8, 1]]
-[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -11; 0, 1, 
-0, 0, 0, 0, 0, 0, 0, 0, 55; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -165; 0, 0, 0, 1, 
-0, 0, 0, 0, 0, 0, 330; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -462; 0, 0, 0, 0, 0, 1,
- 0, 0, 0, 0, 462; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -330; 0, 0, 0, 0, 0, 0, 0, 1
-, 0, 0, 165; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -55; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
-, 11], [1, -10, 45, -120, 210, -252, 210, -120, 45, -10, 1; 0, 55, -330, 990
-, -1848, 2310, -1980, 1155, -440, 99, -10; 0, -165, 1155, -3762, 7392, -9570
-, 8415, -5005, 1936, -441, 45; 0, 330, -2508, 8646, -17688, 23595, -21230, 1
-2859, -5048, 1164, -120; 0, -462, 3696, -13266, 28017, -38335, 35211, -21693
-, 8638, -2016, 210; 0, 462, -3828, 14157, -30668, 42878, -40116, 25109, -101
-36, 2394, -252; 0, -330, 2805, -10615, 23474, -33430, 31795, -20195, 8260, -
-1974, 210; 0, 165, -1430, 5511, -12396, 17935, -17310, 11145, -4616, 1116, -
-120; 0, -55, 484, -1893, 4319, -6335, 6195, -4039, 1693, -414, 45; 0, 11, -9
-8, 388, -896, 1330, -1316, 868, -368, 91, -10; 0, -1, 9, -36, 84, -126, 126,
- -84, 36, -9, 1]]
-[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12; 
-0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -66; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 220; 
-0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -495; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 792;
- 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -924; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 792
-; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -495; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 22
-0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -66; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 12
-], [1, -11, 55, -165, 330, -462, 462, -330, 165, -55, 11, -1; 0, 66, -440, 1
-485, -3168, 4620, -4752, 3465, -1760, 594, -120, 11; 0, -220, 1705, -6237, 1
-3992, -21120, 22275, -16555, 8536, -2916, 595, -55; 0, 495, -4158, 16071, -3
-7488, 58245, -62810, 47509, -24848, 8589, -1770, 165; 0, -792, 6996, -28116,
- 67617, -107635, 118371, -90993, 48238, -16866, 3510, -330; 0, 924, -8448, 3
-4947, -86108, 139898, -156540, 122129, -65576, 23184, -4872, 462; 0, -792, 7
-425, -31405, 78914, -130450, 148219, -117215, 63700, -22764, 4830, -462; 0, 
-495, -4730, 20361, -51996, 87235, -100470, 80445, -44216, 15966, -3420, 330;
- 0, -220, 2134, -9318, 24119, -40985, 47775, -38689, 21493, -7839, 1695, -16
-5; 0, 66, -648, 2863, -7496, 12880, -15176, 12418, -6968, 2566, -560, 55; 0,
- -12, 119, -531, 1404, -2436, 2898, -2394, 1356, -504, 111, -11; 0, 1, -10, 
-45, -120, 210, -252, 210, -120, 45, -10, 1]]
-[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- -13; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 
-0, 0, -286; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 715; 0, 0, 0, 0, 1, 0, 0, 0,
- 0, 0, 0, 0, -1287; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1716; 0, 0, 0, 0, 0,
- 0, 1, 0, 0, 0, 0, 0, -1716; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1287; 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -715; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 286
-; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -78; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-1, 13], [1, -12, 66, -220, 495, -792, 924, -792, 495, -220, 66, -12, 1; 0, 7
-8, -572, 2145, -5148, 8580, -10296, 9009, -5720, 2574, -780, 143, -12; 0, -2
-86, 2431, -9867, 24882, -42900, 52767, -47047, 30316, -13806, 4225, -781, 66
-; 0, 715, -6578, 28171, -73788, 130845, -164450, 149149, -97448, 44889, -138
-70, 2585, -220; 0, -1287, 12441, -55341, 149292, -270985, 347061, -319683, 2
-11588, -98541, 30735, -5775, 495; 0, 1716, -17160, 78507, -216788, 401258, -
-522444, 488033, -326936, 153864, -48432, 9174, -792; 0, -1716, 17589, -82225
-, 231374, -435370, 575107, -544103, 368620, -175224, 55650, -10626, 924; 0, 
-1287, -13442, 63921, -182676, 348595, -466374, 446349, -305576, 146646, -469
-80, 9042, -792; 0, -715, 7579, -36543, 105794, -204335, 276465, -267379, 184
-843, -89514, 28920, -5610, 495; 0, 286, -3068, 14963, -43796, 85480, -116816
-, 114058, -79568, 38866, -12660, 2475, -220; 0, -78, 845, -4161, 12294, -242
-16, 33390, -32886, 23136, -11394, 3741, -737, 66; 0, 13, -142, 705, -2100, 4
-170, -5796, 5754, -4080, 2025, -670, 133, -12; 0, -1, 11, -55, 165, -330, 46
-2, -462, 330, -165, 55, -11, 1]]
-[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-, 0, 0, 14; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -91; 0, 0, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 364; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1001; 0, 0, 
-0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2002; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0
-, -3003; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3432; 0, 0, 0, 0, 0, 0, 0, 1
-, 0, 0, 0, 0, 0, -3003; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2002; 0, 0, 0
-, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1001; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0
-, 364; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -91; 0, 0, 0, 0, 0, 0, 0, 0, 0
-, 0, 0, 0, 1, 14], [1, -13, 78, -286, 715, -1287, 1716, -1716, 1287, -715, 2
-86, -78, 13, -1; 0, 91, -728, 3003, -8008, 15015, -20592, 21021, -16016, 900
-9, -3640, 1001, -168, 13; 0, -364, 3367, -15015, 42042, -81510, 114543, -119
-119, 92092, -52416, 21385, -5929, 1002, -78; 0, 1001, -10010, 47047, -136708
-, 272415, -390962, 413413, -323960, 186459, -76790, 21461, -3652, 286; 0, -2
-002, 21021, -102531, 306592, -624910, 913341, -980343, 777868, -452466, 1880
-35, -52965, 9075, -715; 0, 3003, -32604, 163449, -499928, 1038323, -1541748,
- 1677221, -1346240, 790929, -331572, 94116, -16236, 1287; 0, -3432, 38181, -
-195481, 608894, -1284790, 1934179, -2129687, 1727692, -1024644, 433170, -123
-882, 21516, -1716; 0, 3003, -34034, 177177, -560196, 1198015, -1825446, 2031
-933, -1664648, 996066, -424500, 122298, -21384, 1716; 0, -2002, 23023, -1214
-85, 388934, -841400, 1295769, -1456567, 1204147, -726579, 312060, -90552, 15
-939, -1287; 0, 1001, -11648, 62153, -201096, 439405, -683096, 774718, -64584
-8, 392791, -169960, 49665, -8800, 715; 0, -364, 4277, -23037, 75214, -165786
-, 259902, -297150, 249648, -152964, 66661, -19613, 3498, -286; 0, 91, -1078,
- 5853, -19260, 42780, -67572, 77826, -65856, 40635, -17830, 5281, -948, 78; 
-0, -14, 167, -913, 3025, -6765, 10758, -12474, 10626, -6600, 2915, -869, 157
-, -13; 0, 1, -12, 66, -220, 495, -792, 924, -792, 495, -220, 66, -12, 1]]
-[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, -15; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105; 0, 0, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -455; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-0, 1365; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3003; 0, 0, 0, 0, 0, 1, 
-0, 0, 0, 0, 0, 0, 0, 0, 5005; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -643
-5; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 6435; 0, 0, 0, 0, 0, 0, 0, 0, 1
-, 0, 0, 0, 0, 0, -5005; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3003; 0, 0
-, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1365; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-, 1, 0, 0, 455; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -105; 0, 0, 0, 0, 
-0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 15], [1, -14, 91, -364, 1001, -2002, 3003, -34
-32, 3003, -2002, 1001, -364, 91, -14, 1; 0, 105, -910, 4095, -12012, 25025, 
--38610, 45045, -40040, 27027, -13650, 5005, -1260, 195, -14; 0, -455, 4550, 
--22113, 68068, -146575, 231660, -275275, 248248, -169533, 86450, -31955, 810
-0, -1261, 91; 0, 1365, -14742, 75439, -240812, 532675, -859430, 1038037, -94
-8584, 654927, -337050, 125565, -32044, 5018, -364; 0, -3003, 34034, -180609,
- 592878, -1340625, 2201628, -2698059, 2495584, -1740753, 903750, -339251, 87
-153, -13728, 1001; 0, 5005, -58630, 319605, -1072500, 2469753, -4118322, 511
-2653, -4781672, 3367503, -1763002, 666688, -172392, 27313, -2002; 0, -6435, 
-77220, -429715, 1467752, -3431935, 5799040, -7282835, 6880840, -4889505, 258
-0315, -982740, 255750, -40755, 3003; 0, 6435, -78650, 444873, -1541748, 3651
-895, -6242430, 7921245, -7553960, 5413050, -2878380, 1103850, -289080, 46332
-, -3432; 0, -5005, 62062, -355719, 1247792, -2988545, 5160630, -6609715, 635
-7295, -4591440, 2459205, -949410, 250173, -40326, 3003; 0, 3003, -37674, 218
-309, -773668, 1870835, -3259670, 4210150, -4081280, 2969365, -1601390, 62223
-7, -164956, 26741, -2002; 0, -1365, 17290, -101115, 361500, -881501, 1548189
-, -2014866, 1967364, -1441251, 782376, -305899, 81576, -13299, 1001; 0, 455,
- -5810, 34245, -123364, 303040, -536040, 702450, -690480, 509103, -278090, 1
-09385, -29340, 4810, -364; 0, -105, 1350, -8011, 29051, -71830, 127875, -168
-630, 166782, -123717, 67980, -26895, 7255, -1196, 91; 0, 15, -194, 1158, -42
-24, 10505, -18810, 24948, -24816, 18513, -10230, 4070, -1104, 183, -14; 0, -
-1, 13, -78, 286, -715, 1287, -1716, 1716, -1287, 715, -286, 78, -13, 1]]
-[[0, -1; 1, 2], [1, -1; 0, 1]]
-[[0, 0, 1; 1, 0, -3; 0, 1, 3], [1, -3/2, 1/2; 0, 2, -1; 0, -1/2, 1/2]]
-[[0, 0, 0, -1; 1, 0, 0, 4; 0, 1, 0, -6; 0, 0, 1, 4], [1, -11/6, 1, -1/6; 0, 
-3, -5/2, 1/2; 0, -3/2, 2, -1/2; 0, 1/3, -1/2, 1/6]]
-[[0, 0, 0, 0, 1; 1, 0, 0, 0, -5; 0, 1, 0, 0, 10; 0, 0, 1, 0, -10; 0, 0, 0, 1
-, 5], [1, -25/12, 35/24, -5/12, 1/24; 0, 4, -13/3, 3/2, -1/6; 0, -3, 19/4, -
-2, 1/4; 0, 4/3, -7/3, 7/6, -1/6; 0, -1/4, 11/24, -1/4, 1/24]]
-[[0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 6; 0, 1, 0, 0, 0, -15; 0, 0, 1, 0, 0, 20
-; 0, 0, 0, 1, 0, -15; 0, 0, 0, 0, 1, 6], [1, -137/60, 15/8, -17/24, 1/8, -1/
-120; 0, 5, -77/12, 71/24, -7/12, 1/24; 0, -5, 107/12, -59/12, 13/12, -1/12; 
-0, 10/3, -13/2, 49/12, -1, 1/12; 0, -5/4, 61/24, -41/24, 11/24, -1/24; 0, 1/
-5, -5/12, 7/24, -1/12, 1/120]]
-[[0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, -7; 0, 1, 0, 0, 0, 0, 21; 0, 0, 1, 
-0, 0, 0, -35; 0, 0, 0, 1, 0, 0, 35; 0, 0, 0, 0, 1, 0, -21; 0, 0, 0, 0, 0, 1,
- 7], [1, -49/20, 203/90, -49/48, 35/144, -7/240, 1/720; 0, 6, -87/10, 29/6, 
--31/24, 1/6, -1/120; 0, -15/2, 117/8, -461/48, 137/48, -19/48, 1/48; 0, 20/3
-, -127/9, 31/3, -121/36, 1/2, -1/36; 0, -15/4, 33/4, -307/48, 107/48, -17/48
-, 1/48; 0, 6/5, -27/10, 13/6, -19/24, 2/15, -1/120; 0, -1/6, 137/360, -5/16,
- 17/144, -1/48, 1/720]]
-[[0, 0, 0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 0, 0, 8; 0, 1, 0, 0, 0, 0, 0, -28;
- 0, 0, 1, 0, 0, 0, 0, 56; 0, 0, 0, 1, 0, 0, 0, -70; 0, 0, 0, 0, 1, 0, 0, 56;
- 0, 0, 0, 0, 0, 1, 0, -28; 0, 0, 0, 0, 0, 0, 1, 8], [1, -363/140, 469/180, -
-967/720, 7/18, -23/360, 1/180, -1/5040; 0, 7, -223/20, 319/45, -37/16, 59/14
-4, -3/80, 1/720; 0, -21/2, 879/40, -3929/240, 71/12, -9/8, 13/120, -1/240; 0
-, 35/3, -949/36, 389/18, -1219/144, 247/144, -25/144, 1/144; 0, -35/4, 41/2,
- -2545/144, 22/3, -113/72, 1/6, -1/144; 0, 21/5, -201/20, 134/15, -185/48, 6
-9/80, -23/240, 1/240; 0, -7/6, 1019/360, -1849/720, 41/36, -19/72, 11/360, -
-1/720; 0, 1/7, -7/20, 29/90, -7/48, 5/144, -1/240, 1/5040]]
-[[0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, -9; 0, 1, 0, 0, 0, 0, 0
-, 0, 36; 0, 0, 1, 0, 0, 0, 0, 0, -84; 0, 0, 0, 1, 0, 0, 0, 0, 126; 0, 0, 0, 
-0, 1, 0, 0, 0, -126; 0, 0, 0, 0, 0, 1, 0, 0, 84; 0, 0, 0, 0, 0, 0, 1, 0, -36
-; 0, 0, 0, 0, 0, 0, 0, 1, 9], [1, -761/280, 29531/10080, -267/160, 1069/1920
-, -9/80, 13/960, -1/1120, 1/40320; 0, 8, -481/35, 349/36, -329/90, 115/144, 
--73/720, 1/144, -1/5040; 0, -14, 621/20, -18353/720, 15289/1440, -179/72, 23
-9/720, -17/720, 1/1440; 0, 56/3, -2003/45, 797/20, -268/15, 71/16, -149/240,
- 11/240, -1/720; 0, -35/2, 691/16, -1457/36, 10993/576, -179/36, 209/288, -1
-/18, 1/576; 0, 56/5, -141/5, 4891/180, -1193/90, 2581/720, -391/720, 31/720,
- -1/720; 0, -14/3, 2143/180, -187/16, 2803/480, -13/8, 61/240, -1/48, 1/1440
-; 0, 8/7, -103/35, 527/180, -67/45, 61/144, -49/720, 29/5040, -1/5040; 0, -1
-/8, 363/1120, -469/1440, 967/5760, -7/144, 23/2880, -1/1440, 1/40320]]
-[[0, 0, 0, 0, 0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 10; 0, 1, 0, 0, 
-0, 0, 0, 0, 0, -45; 0, 0, 1, 0, 0, 0, 0, 0, 0, 120; 0, 0, 0, 1, 0, 0, 0, 0, 
-0, -210; 0, 0, 0, 0, 1, 0, 0, 0, 0, 252; 0, 0, 0, 0, 0, 1, 0, 0, 0, -210; 0,
- 0, 0, 0, 0, 0, 1, 0, 0, 120; 0, 0, 0, 0, 0, 0, 0, 1, 0, -45; 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 10], [1, -7129/2520, 6515/2016, -4523/2268, 95/128, -3013/17280
-, 5/192, -29/12096, 1/8064, -1/362880; 0, 9, -4609/280, 14139/1120, -7667/14
-40, 7807/5760, -77/360, 59/2880, -11/10080, 1/40320; 0, -18, 5869/140, -2083
-7/560, 24901/1440, -6787/1440, 563/720, -7/90, 43/10080, -1/10080; 0, 28, -6
-289/90, 72569/1080, -4013/120, 13873/1440, -401/240, 31/180, -7/720, 1/4320;
- 0, -63/2, 6499/80, -6519/80, 122249/2880, -36769/2880, 3313/1440, -353/1440
-, 41/2880, -1/2880; 0, 126/5, -265/4, 1091/16, -5273/144, 32773/2880, -305/1
-44, 67/288, -1/72, 1/2880; 0, -14, 6709/180, -84307/2160, 10279/480, -9823/1
-440, 313/240, -53/360, 13/1440, -1/4320; 0, 36/7, -967/70, 4101/280, -2939/3
-60, 3817/1440, -373/720, 151/2520, -19/5040, 1/10080; 0, -9/8, 3407/1120, -1
-823/560, 10579/5760, -3487/5760, 347/2880, -41/2880, 37/40320, -1/40320; 0, 
-1/9, -761/2520, 29531/90720, -89/480, 1069/17280, -1/80, 13/8640, -1/10080, 
-1/362880]]
-[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -11; 0, 1, 
-0, 0, 0, 0, 0, 0, 0, 0, 55; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -165; 0, 0, 0, 1, 
-0, 0, 0, 0, 0, 0, 330; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -462; 0, 0, 0, 0, 0, 1,
- 0, 0, 0, 0, 462; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -330; 0, 0, 0, 0, 0, 0, 0, 1
-, 0, 0, 165; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -55; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
-, 11], [1, -7381/2520, 177133/50400, -84095/36288, 341693/362880, -8591/3456
-0, 7513/172800, -121/24192, 11/30240, -11/725760, 1/3628800; 0, 10, -4861/25
-2, 79913/5040, -663941/90720, 6041/2880, -6709/17280, 67/1440, -211/60480, 1
-/6720, -1/362880; 0, -45/2, 6121/112, -115923/2240, 264767/10080, -92771/115
-20, 18047/11520, -1123/5760, 607/40320, -53/80640, 1/80640; 0, 40, -6541/63,
- 400579/3780, -433739/7560, 13349/720, -5419/1440, 349/720, -97/2520, 13/756
-0, -1/30240; 0, -105/2, 6751/48, -71689/480, 728587/8640, -163313/5760, 3434
-3/5760, -2281/2880, 31/480, -17/5760, 1/17280; 0, 252/5, -6877/50, 1197/8, -
-62549/720, 43319/1440, -93773/14400, 8/9, -107/1440, 1/288, -1/14400; 0, -35
-, 6961/72, -461789/4320, 273431/4320, -129067/5760, 28603/5760, -1999/2880, 
-19/320, -49/17280, 1/17280; 0, 120/7, -1003/21, 22439/420, -242639/7560, 832
-1/720, -1253/480, 1877/5040, -41/1260, 1/630, -1/30240; 0, -45/8, 3533/224, 
--39867/2240, 435893/40320, -45449/11520, 10427/11520, -757/5760, 59/5040, -4
-7/80640, 1/80640; 0, 10/9, -263/84, 161353/45360, -197741/90720, 6947/8640, 
--3229/17280, 119/4320, -151/60480, 23/181440, -1/362880; 0, -1/10, 7129/2520
-0, -1303/4032, 4523/22680, -19/256, 3013/172800, -1/384, 29/120960, -1/80640
-, 1/3628800]]
-[Mat(1), Mat(1)]
-[[0, -1/12; 1, 4/3], [1, -2; 0, 2]]
-[[0, 0, 1/2160; 1, 0, -127/720; 0, 1, 23/15], [1, -154/27, 50/9; 0, 42, -60;
- 0, -80/3, 40]]
-[[0, 0, 0, -1/6048000; 1, 0, 0, 41/23625; 0, 1, 0, -3341/12600; 0, 0, 1, 176
-/105], [1, -1421/125, 27513/1000, -4487/250; 0, 279797/250, -522126/125, 416
-871/125; 0, -34704/5, 131814/5, -106344/5; 0, 20664/5, -78624/5, 63504/5]]
-[[0, 0, 0, 0, 1/266716800000; 1, 0, 0, 0, -61501/53343360000; 0, 1, 0, 0, 85
-2401/222264000; 0, 0, 1, 0, -735781/2116800; 0, 0, 0, 1, 563/315], [1, -4158
-38/21875, 63349974/765625, -19249072/153125, 9456222/153125; 0, 5784458/175,
- -282462084/1225, 538108488/1225, -60617472/245; 0, -2580562224/875, 6365089
-50552/30625, -244100163456/6125, 138115393056/6125; 0, 15152256, -106838784,
- 204933888, -115983360; 0, -42384384/5, 1494360576/25, -573308928/5, 3244769
-28/5]]
-[[0, 0, 0, 0, 0, -1/186313420339200000; 1, 0, 0, 0, 0, 3529/70573265280000; 
-0, 1, 0, 0, 0, -10828423/2688505344000; 0, 0, 1, 0, 0, 18344719/2750517000; 
-0, 0, 0, 1, 0, -14806217/34927200; 0, 0, 0, 0, 1, 6508/3465], [1, -113705672
-62/397065375, 51367426213/264710250, -200591528282/397065375, 26582711207/47
-647845, -698502310/3176523; 0, 26892406032994/26471025, -100223794140728/882
-3675, 1000761213157984/26471025, -154200190180144/3176523, 22461031505440/10
-58841; 0, -11956428602368/7203, 44866837991366/2401, -450093250332248/7203, 
-1739649716044700/21609, -254051753060600/7203; 0, 1265964151819744/12005, -1
-4255235800309184/12005, 47676508772317984/12005, -36859404825081920/7203, 53
-83325127369200/2401; 0, -22893136773120/49, 257789598088320/49, -86218471948
-0320/49, 1110955189536000/49, -486768934080000/49; 0, 12188747704320/49, -13
-7252461547520/49, 459045508331520/49, -591496874496000/49, 259166666880000/4
-9]]
-[[0, 0, 0, 0, 0, 0, 1/2067909047925770649600000; 1, 0, 0, 0, 0, 0, -8237351/
-59083115655022018560000; 0, 1, 0, 0, 0, 0, 509709971/1758426061161369600; 0,
- 0, 1, 0, 0, 0, -126867217979/12687056718336000; 0, 0, 0, 1, 0, 0, 280412388
-5/276900047424; 0, 0, 0, 0, 1, 0, -197708437/399567168; 0, 0, 0, 0, 0, 1, 88
-069/45045], [1, -2105183226479/52298274672, 10204001676775/26149137336, -379
-5959134735/2490394032, 110012661902975/39223706004, -28250835545377/11621838
-816, 5977827829649/7471182096; 0, 694154228498195/21781872, -567779093797712
-5/10890936, 19203290942517085/7260624, -13361594883135815/2333772, 268719450
-14192725/4840416, -6176666319494645/3111696; 0, -48323938697783864125/444713
-22, 1588963999041773969375/88942644, -96306745655113424950/1058841, 26337479
-589176600409625/133413966, -473905474639530537050/2470629, 21821995843038607
-4825/3176523; 0, 377327226220357400/343, -6204414565597298000/343, 315912214
-44969069000/343, -29387968974963236000/147, 66632096787393901500/343, -34092
-94728736153400/49; 0, -903376448781904680000/16807, 14854370951794001100000/
-16807, -10804977525060138816000/2401, 164173623814473593240000/16807, -15952
-9759706768415120000/16807, 8162510430881545440000/2401; 0, 14866788313713600
-00/7, -24445722399278400000/7, 124471715219042400000/7, -3859706030495040000
-0, 262537102163437200000/7, -13432993354329120000; 0, -37259471250144000000/
-343, 612664107014044800000/343, -445648264430054400000/49, 67712971287424320
-00000/343, -6579763803550080000000/343, 336660704216179200000/49]]
-[[0, 0, 0, 0, 0, 0, 0, -1/365356847125734485878112256000000; 1, 0, 0, 0, 0, 
-0, 0, 442037/17839689801061254193267200000; 0, 1, 0, 0, 0, 0, 0, -1258152740
-869/906142974022158943150080000; 0, 0, 1, 0, 0, 0, 0, 725120398661/668862621
-366980040000; 0, 0, 0, 1, 0, 0, 0, -3571285252517/176488178798131200; 0, 0, 
-0, 0, 1, 0, 0, 85934726089/6093243231075; 0, 0, 0, 0, 0, 1, 0, -6070382321/1
-0821610800; 0, 0, 0, 0, 0, 0, 1, 91072/45045], [1, -42500337230198189/789037
-335136512, 1485561263561785385/2104099560364032, -2464043972606130965/642919
-310111232, 718262854403191163375/69435285492013056, -56581509496159888799/38
-57515860667392, 9878887530104754629/944697761796096, -149549670813037235/506
-08808667648; 0, 1597795988934645006308365/1578074670273024, -299836399161675
-7631524325/131506222522752, 52351244773959107312090215/321459655055616, -566
-606430091427159033910455/1084926335812704, 402649158744516505072233775/48218
-9482583424, -2401721270189620785803345/3690225632016, 3116622818176389995970
-25/1581525270864; 0, -810133477962910968828875/1035416844, 16278035944517515
-917941125/920370528, -961904309558071374658162075/7593056856, 45797400660388
-5374127196125/1124897312, -9902444332568340060689566775/15186113712, 2103043
-69107054866754822725/413227584, -3415235346455446300557875/22137192; 0, 4319
-362769093923379127587825/295833384, -8137191631206765936749175625/24652782, 
-47493879724607616186085748625/20087452, -3090987614443956021375650065250/406
-770903, 1100195852610318620167150387625/90393534, -2628709950385259668939964
-2900/2767149, 3415205806974130682543927000/1185921; 0, -54848998853756143562
-10000/539, 123995581243617591167763750/539, -9770214869603157247861659000/59
-29, 31400712562043027405220098750/5929, -50295067308334909983004777500/5929,
- 801137981304080453838309375/121, -242861544697294090465625000/121; 0, 21815
-8654361365089166145000/539, -4931851901883773788541100000/539, 3886046471450
-08366217993250000/5929, -1248945312265946216389327600000/5929, 2000457585111
-261976697403900000/5929, -31864807885065137436311520000/121, 965968044382624
-9833287200000/121; 0, -1458806909788672329600000, 32978841764920871648400000
-, -236233063370670130814400000, 759234820879813379166000000, -12160797209842
-05624924000000, 949161438034641498303000000, -287734238270502040180800000; 0
-, 721538527935067128000000, -16311620707236185760000000, 1168429189411405078
-56000000, -375524117964065416320000000, 601483562848427369760000000, -469463
-468662526817024000000, 142315846641335937024000000]]
+(M)->my([F,B]=matfrobenius(M,2));if(M!=B^-1*F*B,error("matfrobenius:",M));F
+Mat(1)
+[0, -1; 1, 2]
+[0, 0, 1; 1, 0, -3; 0, 1, 3]
+[0, 0, 0, -1; 1, 0, 0, 4; 0, 1, 0, -6; 0, 0, 1, 4]
+[0, 0, 0, 0, 1; 1, 0, 0, 0, -5; 0, 1, 0, 0, 10; 0, 0, 1, 0, -10; 0, 0, 0, 1,
+ 5]
+[0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 6; 0, 1, 0, 0, 0, -15; 0, 0, 1, 0, 0, 20;
+ 0, 0, 0, 1, 0, -15; 0, 0, 0, 0, 1, 6]
+[0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, -7; 0, 1, 0, 0, 0, 0, 21; 0, 0, 1, 0
+, 0, 0, -35; 0, 0, 0, 1, 0, 0, 35; 0, 0, 0, 0, 1, 0, -21; 0, 0, 0, 0, 0, 1, 
+7]
+[0, 0, 0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 0, 0, 8; 0, 1, 0, 0, 0, 0, 0, -28; 
+0, 0, 1, 0, 0, 0, 0, 56; 0, 0, 0, 1, 0, 0, 0, -70; 0, 0, 0, 0, 1, 0, 0, 56; 
+0, 0, 0, 0, 0, 1, 0, -28; 0, 0, 0, 0, 0, 0, 1, 8]
+[0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, -9; 0, 1, 0, 0, 0, 0, 0,
+ 0, 36; 0, 0, 1, 0, 0, 0, 0, 0, -84; 0, 0, 0, 1, 0, 0, 0, 0, 126; 0, 0, 0, 0
+, 1, 0, 0, 0, -126; 0, 0, 0, 0, 0, 1, 0, 0, 84; 0, 0, 0, 0, 0, 0, 1, 0, -36;
+ 0, 0, 0, 0, 0, 0, 0, 1, 9]
+[0, 0, 0, 0, 0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 10; 0, 1, 0, 0, 0
+, 0, 0, 0, 0, -45; 0, 0, 1, 0, 0, 0, 0, 0, 0, 120; 0, 0, 0, 1, 0, 0, 0, 0, 0
+, -210; 0, 0, 0, 0, 1, 0, 0, 0, 0, 252; 0, 0, 0, 0, 0, 1, 0, 0, 0, -210; 0, 
+0, 0, 0, 0, 0, 1, 0, 0, 120; 0, 0, 0, 0, 0, 0, 0, 1, 0, -45; 0, 0, 0, 0, 0, 
+0, 0, 0, 1, 10]
+[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -11; 0, 1, 0
+, 0, 0, 0, 0, 0, 0, 0, 55; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -165; 0, 0, 0, 1, 0
+, 0, 0, 0, 0, 0, 330; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -462; 0, 0, 0, 0, 0, 1, 
+0, 0, 0, 0, 462; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -330; 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 165; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -55; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 11]
+[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12; 0
+, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -66; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 220; 0
+, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -495; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 792; 
+0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -924; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 792;
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -495; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 220
+; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -66; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 12]
+[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+-13; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0
+, 0, -286; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 715; 0, 0, 0, 0, 1, 0, 0, 0, 
+0, 0, 0, 0, -1287; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1716; 0, 0, 0, 0, 0, 
+0, 1, 0, 0, 0, 0, 0, -1716; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1287; 0, 0, 
+0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -715; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 286;
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -78; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+, 13]
+[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 14; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -91; 0, 0, 1, 0, 0, 0, 0, 
+0, 0, 0, 0, 0, 0, 364; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1001; 0, 0, 0
+, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2002; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ -3003; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3432; 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, -3003; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2002; 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1001; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 364; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -91; 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 14]
+[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+0, 0, 0, 0, -15; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105; 0, 0, 1, 0, 
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -455; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+, 1365; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3003; 0, 0, 0, 0, 0, 1, 0
+, 0, 0, 0, 0, 0, 0, 0, 5005; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -6435
+; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 6435; 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, -5005; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3003; 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1365; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 455; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -105; 0, 0, 0, 0, 0
+, 0, 0, 0, 0, 0, 0, 0, 0, 1, 15]
+[0, -1; 1, 2]
+[0, 0, 1; 1, 0, -3; 0, 1, 3]
+[0, 0, 0, -1; 1, 0, 0, 4; 0, 1, 0, -6; 0, 0, 1, 4]
+[0, 0, 0, 0, 1; 1, 0, 0, 0, -5; 0, 1, 0, 0, 10; 0, 0, 1, 0, -10; 0, 0, 0, 1,
+ 5]
+[0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 6; 0, 1, 0, 0, 0, -15; 0, 0, 1, 0, 0, 20;
+ 0, 0, 0, 1, 0, -15; 0, 0, 0, 0, 1, 6]
+[0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, -7; 0, 1, 0, 0, 0, 0, 21; 0, 0, 1, 0
+, 0, 0, -35; 0, 0, 0, 1, 0, 0, 35; 0, 0, 0, 0, 1, 0, -21; 0, 0, 0, 0, 0, 1, 
+7]
+[0, 0, 0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 0, 0, 8; 0, 1, 0, 0, 0, 0, 0, -28; 
+0, 0, 1, 0, 0, 0, 0, 56; 0, 0, 0, 1, 0, 0, 0, -70; 0, 0, 0, 0, 1, 0, 0, 56; 
+0, 0, 0, 0, 0, 1, 0, -28; 0, 0, 0, 0, 0, 0, 1, 8]
+[0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, -9; 0, 1, 0, 0, 0, 0, 0,
+ 0, 36; 0, 0, 1, 0, 0, 0, 0, 0, -84; 0, 0, 0, 1, 0, 0, 0, 0, 126; 0, 0, 0, 0
+, 1, 0, 0, 0, -126; 0, 0, 0, 0, 0, 1, 0, 0, 84; 0, 0, 0, 0, 0, 0, 1, 0, -36;
+ 0, 0, 0, 0, 0, 0, 0, 1, 9]
+[0, 0, 0, 0, 0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 10; 0, 1, 0, 0, 0
+, 0, 0, 0, 0, -45; 0, 0, 1, 0, 0, 0, 0, 0, 0, 120; 0, 0, 0, 1, 0, 0, 0, 0, 0
+, -210; 0, 0, 0, 0, 1, 0, 0, 0, 0, 252; 0, 0, 0, 0, 0, 1, 0, 0, 0, -210; 0, 
+0, 0, 0, 0, 0, 1, 0, 0, 120; 0, 0, 0, 0, 0, 0, 0, 1, 0, -45; 0, 0, 0, 0, 0, 
+0, 0, 0, 1, 10]
+[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -11; 0, 1, 0
+, 0, 0, 0, 0, 0, 0, 0, 55; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -165; 0, 0, 0, 1, 0
+, 0, 0, 0, 0, 0, 330; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -462; 0, 0, 0, 0, 0, 1, 
+0, 0, 0, 0, 462; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -330; 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 165; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -55; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 11]
+Mat(1)
+[0, -1/12; 1, 4/3]
+[0, 0, 1/2160; 1, 0, -127/720; 0, 1, 23/15]
+[0, 0, 0, -1/6048000; 1, 0, 0, 41/23625; 0, 1, 0, -3341/12600; 0, 0, 1, 176/
+105]
+[0, 0, 0, 0, 1/266716800000; 1, 0, 0, 0, -61501/53343360000; 0, 1, 0, 0, 852
+401/222264000; 0, 0, 1, 0, -735781/2116800; 0, 0, 0, 1, 563/315]
+[0, 0, 0, 0, 0, -1/186313420339200000; 1, 0, 0, 0, 0, 3529/70573265280000; 0
+, 1, 0, 0, 0, -10828423/2688505344000; 0, 0, 1, 0, 0, 18344719/2750517000; 0
+, 0, 0, 1, 0, -14806217/34927200; 0, 0, 0, 0, 1, 6508/3465]
+[0, 0, 0, 0, 0, 0, 1/2067909047925770649600000; 1, 0, 0, 0, 0, 0, -8237351/5
+9083115655022018560000; 0, 1, 0, 0, 0, 0, 509709971/1758426061161369600; 0, 
+0, 1, 0, 0, 0, -126867217979/12687056718336000; 0, 0, 0, 1, 0, 0, 2804123885
+/276900047424; 0, 0, 0, 0, 1, 0, -197708437/399567168; 0, 0, 0, 0, 0, 1, 880
+69/45045]
+[0, 0, 0, 0, 0, 0, 0, -1/365356847125734485878112256000000; 1, 0, 0, 0, 0, 0
+, 0, 442037/17839689801061254193267200000; 0, 1, 0, 0, 0, 0, 0, -12581527408
+69/906142974022158943150080000; 0, 0, 1, 0, 0, 0, 0, 725120398661/6688626213
+66980040000; 0, 0, 0, 1, 0, 0, 0, -3571285252517/176488178798131200; 0, 0, 0
+, 0, 1, 0, 0, 85934726089/6093243231075; 0, 0, 0, 0, 0, 1, 0, -6070382321/10
+821610800; 0, 0, 0, 0, 0, 0, 1, 91072/45045]
 [0, x, x]
 [0, x^2 + x, 1]
 [0, 0]
@@ -328,4 +124,4 @@ x^2 - 2*a*x + (a^2 - d^2)
 []
 [matrix(0,1), [1, 0; 0, -2; 0, 1], matrix(0,2)]
 [Mod(1, 3)*x^4 + Mod(2, 3)*x + Mod(2, 3), 1, 1]
-Total time spent: 292
+Total time spent: 255
diff --git a/src/test/32/member b/src/test/32/member
index 6e839ae..b1de263 100644
--- a/src/test/32/member
+++ b/src/test/32/member
@@ -31,44 +31,41 @@ NF chvar
 .diff: [4, 0; 0, 2]
 .disc: -8
 .index: 1
-.nf: [y^2 + 2, [0, 1], -8, 1, [Mat([1, 0.E-38 + 1.41421356237309504880168872
+.nf: [y^2 + 2, [0, 1], -8, 1, [Mat([1, 0.E-57 + 1.41421356237309504880168872
 42096980786*I]), [1, 1.4142135623730950488016887242096980786; 1, -1.41421356
 23730950488016887242096980786], [1, 1; 1, -1], [2, 0; 0, -4], [4, 0; 0, 2], 
-[2, 0; 0, -1], [2, [0, -2; 1, 0]], [2]], [0.E-38 + 1.41421356237309504880168
+[2, 0; 0, -1], [2, [0, -2; 1, 0]], [2]], [0.E-57 + 1.41421356237309504880168
 87242096980786*I], [1, y], [1, 0; 0, 1], [1, 0, 0, -2; 0, 1, 1, 0]]
 .pol: y^2 + 2
 .r1: 0
 .r2: 1
-.roots: [0.E-38 + 1.4142135623730950488016887242096980786*I]
+.roots: [0.E-57 + 1.4142135623730950488016887242096980786*I]
 .sign: [0, 1]
-.t2: [2, 0.E-38; 0.E-38, 4.0000000000000000000000000000000000000]
+.t2: [2, 0.E-57; 0.E-57, 4.0000000000000000000000000000000000000]
 .zk: [1, y]
 BNF
 .bnf: [[2, 0; 0, 2], [1, 1, 0; 1, 0, 1], [10.9503854058256053302677508250179
 37393 + 3.1415926535897932384626433832795028842*I; -10.950385405825605330267
 750825017937393 + 6.2831853071795864769252867665590057684*I], [-2.8070134016
-636593080928506577483570863 + 6.2831853071795864769252867665590057684*I, -6.
-4656286076812397829259659980344686073 + 6.2831853071795864769252867665590057
-684*I, 6.3140644011531557847583424971265245465 + 4.70197740 E-38*I, 0, 0; 2.
-8070134016636593080928506577483570863 + 3.1415926535897932384626433832795028
-842*I, 6.4656286076812397829259659980344686073 + 3.1415926535897932384626433
-832795028842*I, -6.3140644011531557847583424971265245465 + 7.05296610 E-38*I
-, 0, 0], [[2, [-1, 1]~, 1, 1, [0, 276; 1, -1]], [3, [0, 2]~, 1, 1, [-1, -276
-; -1, 0]], [5, [1, 2]~, 2, 1, [1, 552; 2, -1]], [2, [2, 1]~, 1, 1, [1, 276; 
-1, 0]], [3, [2, 2]~, 1, 1, [0, -276; -1, 1]]], 0, [y^2 - 1105, [2, 0], 1105,
- 2, [[1, -17.120770138594661402315290771052609448; 1, 16.1207701385946614023
-15290771052609448], [1, -17.120770138594661402315290771052609448; 1, 16.1207
-70138594661402315290771052609448], [1, -17; 1, 16], [2, -1; -1, 553], [1105,
- 553; 0, 1], [553, 1; 1, 2], [1105, [553, 276; 1, 552]], [5, 13, 17]], [-33.
-241540277189322804630581542105218897, 33.24154027718932280463058154210521889
-7], [1, 1/2*y - 1/2], [1, 1; 0, 2], [1, 0, 0, 276; 0, 1, 1, -1]], [[4, [2, 2
-], [[2, 0; 0, 1], [3, 1; 0, 1]]], 10.950385405825605330267750825017937393, 1
-, [2, -1], [857*y - 28488]], [[-1, 0; 0, -1], [[0, 0], [0, 0]], [[2.80701340
-16636593080928506577483570863 - 6.2831853071795864769252867665590057684*I, -
-2.8070134016636593080928506577483570863 - 3.14159265358979323846264338327950
-28842*I], [6.4656286076812397829259659980344686073 - 6.283185307179586476925
-2867665590057684*I, -6.4656286076812397829259659980344686073 - 3.14159265358
-97932384626433832795028842*I]]], [0, 0]]
+636593080928506577483570863, -6.4656286076812397829259659980344686072, 6.314
+0644011531557847583424971265245465, 0, 0; 2.80701340166365930809285065774835
+70863 + 3.1415926535897932384626433832795028842*I, 6.46562860768123978292596
+59980344686072 + 3.1415926535897932384626433832795028842*I, -6.3140644011531
+557847583424971265245465, 0, 0], [[2, [-1, 1]~, 1, 1, [0, 276; 1, -1]], [3, 
+[0, 2]~, 1, 1, [-1, -276; -1, 0]], [5, [1, 2]~, 2, 1, [1, 552; 2, -1]], [2, 
+[2, 1]~, 1, 1, [1, 276; 1, 0]], [3, [2, 2]~, 1, 1, [0, -276; -1, 1]]], 0, [y
+^2 - 1105, [2, 0], 1105, 2, [[1, -17.120770138594661402315290771052609448; 1
+, 16.120770138594661402315290771052609448], [1, -17.120770138594661402315290
+771052609448; 1, 16.120770138594661402315290771052609448], [1, -17; 1, 16], 
+[2, -1; -1, 553], [1105, 553; 0, 1], [553, 1; 1, 2], [1105, [553, 276; 1, 55
+2]], [5, 13, 17]], [-33.241540277189322804630581542105218897, 33.24154027718
+9322804630581542105218897], [1, 1/2*y - 1/2], [1, 1; 0, 2], [1, 0, 0, 276; 0
+, 1, 1, -1]], [[4, [2, 2], [[2, 0; 0, 1], [3, 1; 0, 1]]], 10.950385405825605
+330267750825017937393, 1, [2, -1], [857*y - 28488]], [[-1, 0; 0, -1], [[0, 0
+], [0, 0]], [[2.8070134016636593080928506577483570863, -2.807013401663659308
+0928506577483570863 - 3.1415926535897932384626433832795028842*I], [6.4656286
+076812397829259659980344686072, -6.4656286076812397829259659980344686072 - 3
+.1415926535897932384626433832795028842*I]]], [0, 0]]
 .clgp: [4, [2, 2], [[2, 0; 0, 1], [3, 1; 0, 1]]]
 .codiff: [1, 553/1105; 0, 1/1105]
 .cyc: [2, 2]
@@ -106,29 +103,26 @@ BNR
 .bnf: [[2, 0; 0, 2], [1, 1, 0; 1, 0, 1], [10.9503854058256053302677508250179
 37393 + 3.1415926535897932384626433832795028842*I; -10.950385405825605330267
 750825017937393 + 6.2831853071795864769252867665590057684*I], [-2.8070134016
-636593080928506577483570863 + 6.2831853071795864769252867665590057684*I, -6.
-4656286076812397829259659980344686073 + 6.2831853071795864769252867665590057
-684*I, 6.3140644011531557847583424971265245465 + 4.70197740 E-38*I, 0, 0; 2.
-8070134016636593080928506577483570863 + 3.1415926535897932384626433832795028
-842*I, 6.4656286076812397829259659980344686073 + 3.1415926535897932384626433
-832795028842*I, -6.3140644011531557847583424971265245465 + 7.05296610 E-38*I
-, 0, 0], [[2, [-1, 1]~, 1, 1, [0, 276; 1, -1]], [3, [0, 2]~, 1, 1, [-1, -276
-; -1, 0]], [5, [1, 2]~, 2, 1, [1, 552; 2, -1]], [2, [2, 1]~, 1, 1, [1, 276; 
-1, 0]], [3, [2, 2]~, 1, 1, [0, -276; -1, 1]]], 0, [y^2 - 1105, [2, 0], 1105,
- 2, [[1, -17.120770138594661402315290771052609448; 1, 16.1207701385946614023
-15290771052609448], [1, -17.120770138594661402315290771052609448; 1, 16.1207
-70138594661402315290771052609448], [1, -17; 1, 16], [2, -1; -1, 553], [1105,
- 553; 0, 1], [553, 1; 1, 2], [1105, [553, 276; 1, 552]], [5, 13, 17]], [-33.
-241540277189322804630581542105218897, 33.24154027718932280463058154210521889
-7], [1, 1/2*y - 1/2], [1, 1; 0, 2], [1, 0, 0, 276; 0, 1, 1, -1]], [[4, [2, 2
-], [[2, 0; 0, 1], [3, 1; 0, 1]]], 10.950385405825605330267750825017937393, 1
-, [2, -1], [857*y - 28488]], [[-1, 0; 0, -1], [[0, 0], [0, 0]], [[2.80701340
-16636593080928506577483570863 - 6.2831853071795864769252867665590057684*I, -
-2.8070134016636593080928506577483570863 - 3.14159265358979323846264338327950
-28842*I], [6.4656286076812397829259659980344686073 - 6.283185307179586476925
-2867665590057684*I, -6.4656286076812397829259659980344686073 - 3.14159265358
-97932384626433832795028842*I]]], [0, [Mat([[16, -1]~, 1]), Mat([[-137, -8]~,
- 1])]]]
+636593080928506577483570863, -6.4656286076812397829259659980344686072, 6.314
+0644011531557847583424971265245465, 0, 0; 2.80701340166365930809285065774835
+70863 + 3.1415926535897932384626433832795028842*I, 6.46562860768123978292596
+59980344686072 + 3.1415926535897932384626433832795028842*I, -6.3140644011531
+557847583424971265245465, 0, 0], [[2, [-1, 1]~, 1, 1, [0, 276; 1, -1]], [3, 
+[0, 2]~, 1, 1, [-1, -276; -1, 0]], [5, [1, 2]~, 2, 1, [1, 552; 2, -1]], [2, 
+[2, 1]~, 1, 1, [1, 276; 1, 0]], [3, [2, 2]~, 1, 1, [0, -276; -1, 1]]], 0, [y
+^2 - 1105, [2, 0], 1105, 2, [[1, -17.120770138594661402315290771052609448; 1
+, 16.120770138594661402315290771052609448], [1, -17.120770138594661402315290
+771052609448; 1, 16.120770138594661402315290771052609448], [1, -17; 1, 16], 
+[2, -1; -1, 553], [1105, 553; 0, 1], [553, 1; 1, 2], [1105, [553, 276; 1, 55
+2]], [5, 13, 17]], [-33.241540277189322804630581542105218897, 33.24154027718
+9322804630581542105218897], [1, 1/2*y - 1/2], [1, 1; 0, 2], [1, 0, 0, 276; 0
+, 1, 1, -1]], [[4, [2, 2], [[2, 0; 0, 1], [3, 1; 0, 1]]], 10.950385405825605
+330267750825017937393, 1, [2, -1], [857*y - 28488]], [[-1, 0; 0, -1], [[0, 0
+], [0, 0]], [[2.8070134016636593080928506577483570863, -2.807013401663659308
+0928506577483570863 - 3.1415926535897932384626433832795028842*I], [6.4656286
+076812397829259659980344686072, -6.4656286076812397829259659980344686072 - 3
+.1415926535897932384626433832795028842*I]]], [0, [Mat([[16, -1]~, 1]), Mat([
+[-137, -8]~, 1])]]]
 .clgp: [4, [2, 2]]
 .codiff: [1, 553/1105; 0, 1/1105]
 .cyc: [2, 2]
@@ -168,19 +162,20 @@ RNF
 .polabs: x^4 - 1105
 .zk: [[1, x - 1], [1, [1, 1/2; 0, 1/2]]]
 QUADCLASSUNIT
-.clgp: [4, [2, 2], [Qfb(2, 31, -18, 0.E-48), Qfb(3, 29, -22, 0.E-48)]]
+.clgp: [4, [2, 2], [Qfb(2, 31, -18, 0.E-38), Qfb(3, 29, -22, 0.E-38)]]
 .cyc: [2, 2]
-.gen: [Qfb(2, 31, -18, 0.E-48), Qfb(3, 29, -22, 0.E-48)]
+.gen: [Qfb(2, 31, -18, 0.E-38), Qfb(3, 29, -22, 0.E-38)]
 .no: 4
 .reg: 10.950385405825605330267750825017937393
 GAL
 .gen: [Vecsmall([2, 1])]
 .group: [Vecsmall([1, 2]), Vecsmall([2, 1])]
-.mod: 96889010407
+.mod: 1004525211269079039999221534496697502180541686174722466474743
 .orders: Vecsmall([2])
 .p: 7
-.pol: x^2 - 2
-.roots: [19757775943, 77131234464]~
+.pol: x^2 - 680564733841876926926749214863536422912
+.roots: [799887496508668970963744346332673997234258373480806990099832, 20463
+7714760410069035477188164023504946283312693915476374911]~
 ELL
 .a1: 1
 .a2: 2
@@ -203,7 +198,10 @@ ELL
 8135906792497 - 1.0687497763561930661592635474375038788*I]
 .roots: [-1.6189099322673713423780009396072169751, -0.3155450338663143288109
 9953019639151248 + 2.0925470969119586079816894466366945829*I, -0.31554503386
-631432881099953019639151248 - 2.0925470969119586079816894466366945829*I]~
+631432881099953019639151248 - 2.0925470969119586079816894466366945829*I, 0.E
+-38 + 4.1850941938239172159633788932733891659*I, -1.303364898401057013567001
+4094108254626 + 2.0925470969119586079816894466366945829*I, -1.30336489840105
+70135670014094108254626 - 2.0925470969119586079816894466366945829*I]~
 ELLFp
 .a1: Mod(1, 13)
 .a2: Mod(2, 13)
@@ -218,8 +216,8 @@ ELLFp
 .c6: Mod(3, 13)
 .cyc: [13]
 .disc: Mod(10, 13)
-.gen: [[Mod(12, 13), Mod(3, 13)]]
-.group: [13, [13], [[Mod(12, 13), Mod(3, 13)]]]
+.gen: [[Mod(6, 13), Mod(12, 13)]]
+.group: [13, [13], [[Mod(6, 13), Mod(12, 13)]]]
 .j: Mod(9, 13)
 .no: 13
 .p: 13
@@ -237,8 +235,8 @@ ELLFq
 .c6: 3
 .cyc: [195]
 .disc: 10
-.gen: [[9*x + 8, 4*x + 2]]
-.group: [195, [195], [[9*x + 8, 4*x + 2]]]
+.gen: [[6*x + 1, x + 6]]
+.group: [195, [195], [[6*x + 1, x + 6]]]
 .j: 9
 .no: 195
 .p: 13
@@ -258,7 +256,7 @@ ELLQp
 .j: 6128487/10351
 .p: 11
 .roots: [9 + O(11^2)]~
-.tate: [6 + 8*11 + 5*11^2 + O(11^4), Mod(u, u^2 + (5 + 2*11 + 5*11^2 + 10*11
+.tate: [6 + 8*11 + 5*11^2 + O(11^4), Mod(x, x^2 + (5 + 2*11 + 5*11^2 + 10*11
 ^3 + O(11^4))), 3*11 + 7*11^2 + O(11^4), [6 + 3*11 + O(11^4), 6 + 11 + 9*11^
 2 + 11^3 + O(11^4)]]
 FFELT
@@ -316,4 +314,4 @@ ll([])], Mat([1/2, -1/2])]], [[], [], []]], Mat([0, 1])]
 .mod: [[4, 1; 0, 1], [0, 0]]
 .no: 2
 .zkst: [2, [2]]
-Total time spent: 48
+Total time spent: 44
diff --git a/src/test/32/modfun b/src/test/32/modfun
index 704b6bf..7efc97b 100644
--- a/src/test/32/modfun
+++ b/src/test/32/modfun
@@ -6,4 +6,6 @@
 x^-1 + 743 + 196884*x + 21690644*x^2 + O(x^3)
 0.E-38 - 0.50432357748832834893222560519660217759*I
 1.0905077326652576592070106557607079790
-Total time spent: 0
+1.0811782878393746833655992417658285836 - 0.14233982193131805512395869109512
+286588*I
+Total time spent: 4
diff --git a/src/test/32/agm b/src/test/32/modpoly
similarity index 100%
copy from src/test/32/agm
copy to src/test/32/modpoly
diff --git a/src/test/32/modsym b/src/test/32/modsym
new file mode 100644
index 0000000..801b063
--- /dev/null
+++ b/src/test/32/modsym
@@ -0,0 +1,187 @@
+  ***   Warning: new stack size = 20000000 (19.073 Mbytes).
+
+[-2]
+
+
+[3 -1]
+
+[0 -2]
+
+
+[3  1  1]
+
+[0 -2  0]
+
+[0  0 -2]
+
+
+[1 0]
+
+[0 1]
+
+0
+1/2
+[1/4, -1/2, -1/2]
+-1/2
+[[[0, 0; -1, 1; 0, 0; -1, 0; -1, 1; -1, 0; -1, 1; -2, 1; 0, 0; -1, 0; 0, 0; 
+0, 0; 0, -1; 0, 0; -1, 1; -1, 1; -1, 1; 0, 1; 0, 1; 0, 1; 1, 0; 0, 1; 0, 1; 
+-1, 1; 1, 0; 0, 1; 1, 0; 1, -1; 0, 0; 0, 1; 1, 0; 0, 1; 0, 0; -1, 1; -2, 1; 
+-1, 0; -1, 0; -1, 0; 0, -1], [0, -1; 1, -1], 1, Vecsmall([2, 4])], [[0, 0; 1
+, 8; 2, 4; -1, 4; 1, -4; -1, 4; 1, -4; 1, 2; 0, 0; 1, 2; 2, 4; 3, 3; 0, 0; 1
+, 2; 3, 0; 2, -2; 3, 0; 0, -3; 0, -6; 2, -8; 0, -3; 0, -6; 2, -8; 1, -4; 0, 
+-6; 0, -6; 0, -6; 0, 0; 0, 0; 0, -3; 0, -3; 3, 3; 0, 0; 1, 8; 1, 2; 1, 2; 1,
+ 2; -1, 4; 0, 0], [4, -8; -2, 1], -12, Vecsmall([2, 3])], [[0, 0; -1, 5; -2,
+ 10; -1, -5; -1, 1; 1, 1; 1, 7; 0, 6; 0, -4; -1, 7; -2, 10; 0, 8; 0, -2; 2, 
+2; 1, 3; -1, 1; 1, 3; 0, 2; 0, 2; 0, 6; -1, 7; 0, 2; 0, 6; -1, 1; -3, -3; -2
+, 0; -3, -3; -1, -3; 0, -8; 0, 2; -1, 7; 0, 2; 0, -8; -1, 5; 0, 6; -1, 11; -
+1, 7; 1, 1; 0, -2], [-5, -5; 1, -1], 10, Vecsmall([2, 4])], [[0, 0, 0; 0, 0,
+ 0; -1, 0, 1; -1, -1, 1; -1, 0, 1; -1, -1, 1; -1, 0, 1; -1, 0, 0; 0, 0, 0; -
+1, 0, 0; -1, 0, 1; 0, 0, 0; 0, 0, 0; -1, 0, 0; 0, 1, 0; 1, 1, 0; 0, 1, 0; 0,
+ 1, 0; 0, 2, 0; 0, 1, 0; 0, 1, 0; 0, 2, 0; 0, 1, 0; -1, 0, 1; 0, 0, 1; 0, 0,
+ 1; 0, 0, 1; 0, 0, 0; 0, 0, 0; 0, 1, 0; 0, 1, 0; 0, 0, 0; 0, 0, 0; 0, 0, 0; 
+-1, 0, 0; -1, 0, 0; -1, 0, 0; -1, -1, 1; 0, 0, 0], [0, 0, 1; -1, 1, 0; -1, 0
+, 1], -1, Vecsmall([3, 4, 8])], [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 3, -1, 1, 1,
+ -1, -7, 5, -1, -1, 2; 5, -1, -2, 7, 5, -19, 11, -1, -3, 8; 1, 1, -2, 1, 5, 
+-7, 5, -1, -3, 2; 2, 0, -1, 2, 4, -14, 7, 10, -4, 4; 5, -3, 2, -7, 7, -11, 1
+0, 1, -1, 7; 6, -4, 1, -2, 8, -4, 11, -10, 0, 8; 6, -4, 1, -2, 2, -4, 8, -10
+, 2, 5; 4, -4, 4, -8, 8, -4, 8, -4, 0, 5; -2, 0, 5, -10, 4, 10, -5, 4, 0, -2
+; 5, -1, -2, 7, 5, -19, 11, -1, -3, 8; 2, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 2, 0
+, 0, 0, 0, 0, 0, 0, 0; 0, 0, 3, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 6, 0, 0, 0, 0,
+ 0, 0; 0, 0, -3, 6, 0, 0, 0, 0, 0, 0; 0, 0, 0, 6, 0, 0, 0, 0, 0, 0; 0, 0, 0,
+ 0, 6, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 6, 0, 0, 0, 0; 1, -1, -1, 5, 1, 7, 1, -
+11, 1, 1; 0, 0, 0, 0, 0, 0, 3, 0, 0, 0; 0, 0, 0, 0, 0, 6, 0, 0, 0, 0; 1, -1,
+ 1, 1, -1, -7, 2, 11, -1, 2; 2, 0, -1, 2, 4, -14, 7, 10, -4, 4; 0, 0, 0, 0, 
+0, 0, 0, 6, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 2, 0; 0, 0, 0, 0, 0, 0, 0, 6, 0, 0
+; 0, 0, 0, 0, 0, 0, 0, 6, -2, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 3; 0, 0, 0, 0, 6
+, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 3, 0, 0, 0; 2, -2, 0, 0, 0, 0, 0, 0, 0, 3
+; 0, 0, 0, 0, 0, 0, 0, 0, 0, 3; 3, -1, 1, 1, -1, -7, 5, -1, -1, 2; 6, -4, 1,
+ -2, 2, -4, 8, -10, 2, 5; -6, 4, 1, -2, -4, 14, -13, 8, 0, -7; -2, 0, 5, -10
+, 4, 10, -5, 4, 0, -2; 5, -3, 2, -7, 7, -11, 10, 1, -1, 7; 0, 2, 0, 0, 0, 0,
+ 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, -6; -21, 9, 21, 42, -33, -27, 102,
+ -39, 54, -54; -10, 2, 10, 16, -10, -10, 40, -18, 20, -20; -3, 1, 5, 6, -3, 
+-5, 18, -9, 10, -10; -1, 1, 4, 7, -4, -4, 19, -11, 11, -12; -2, 2, 2, 2, -2,
+ -4, 8, -2, 4, -4; -12, 8, 12, 20, -16, -16, 56, -24, 32, -28; -2, 2, 4, 4, 
+-4, -4, 14, -6, 8, -8; -15, 9, 24, 39, -30, -24, 99, -45, 57, -54; 4, -4, -4
+, -8, 4, 4, -24, 16, -16, 16], -12, Vecsmall([2, 3, 4, 5, 6, 7, 8, 9, 10, 12
+])]]
+[301, 24]
+x^2 - 9*x + 8
+x^4 - 54*x^3 + 333*x^2 + 10692*x + 39204
+x^3 - 84*x^2 + 2352*x - 21952
+x^6 - 22*x^5 + 153*x^4 - 316*x^3 - 140*x^2 + 576*x + 324
+x^4 - 113*x^3 - 1872*x^2 - 6208*x + 8192
+[[[+oo, 0], [0, 1]], [[[[1, 1; [1, 1; 0, 1], -1], 1], [1, 2]], [[[1, 1; [1, 
+-1; 2, -1], 1], 2]]]]
+[Mat([[1, 0; 0, 1], 1]), 0]
+[0, Mat([[1, 0; 0, 1], 1])]
+[Mat([[1, 1; 2, 3], -1]), 0]
+[0, 0]
+[-32/5*x^5 + 8*x^3 - 8/5*x, -32*x^4 - 64*x^3 - 40*x^2 - 8*x]
+0
+-32/5*x^5 + 8*x^3 - 8/5*x
+-32*x^4 - 64*x^3 - 40*x^2 - 8*x
+[[[0, 0; -1, 0; 0, -1], [-1, 0; 0, -1], 1, Vecsmall([2, 3])], [[-5; -1; -1],
+ Mat(1), -5, Vecsmall([1])]]
+1
+1
+[Mod(1, x^2 + x - 1), Mod(x, x^2 + x - 1), Mod(-2*x - 1, x^2 + x - 1), Mod(-
+x - 1, x^2 + x - 1), Mod(2*x, x^2 + x - 1), Mod(x - 2, x^2 + x - 1), Mod(2*x
+ + 2, x^2 + x - 1), Mod(-2*x - 1, x^2 + x - 1), Mod(2, x^2 + x - 1), Mod(-2*
+x + 2, x^2 + x - 1), Mod(-2*x - 4, x^2 + x - 1), Mod(x + 3, x^2 + x - 1), Mo
+d(3, x^2 + x - 1), Mod(2, x^2 + x - 1), Mod(2*x - 4, x^2 + x - 1), Mod(3*x, 
+x^2 + x - 1), Mod(-2*x + 2, x^2 + x - 1), Mod(2*x, x^2 + x - 1), Mod(-2, x^2
+ + x - 1), Mod(-2, x^2 + x - 1), Mod(-2*x - 6, x^2 + x - 1), Mod(-2*x - 2, x
+^2 + x - 1), Mod(1, x^2 + x - 1), Mod(5, x^2 + x - 1), Mod(-4*x - 1, x^2 + x
+ - 1), Mod(3*x, x^2 + x - 1), Mod(2*x + 1, x^2 + x - 1), Mod(-2*x - 4, x^2 +
+ x - 1), Mod(-3, x^2 + x - 1), Mod(-6*x + 2, x^2 + x - 1)]
+[Mod(1, x^2 + x - 1), Mod(x, x^2 + x - 1), Mod(-2*x - 1, x^2 + x - 1), Mod(-
+x - 1, x^2 + x - 1), Mod(2*x, x^2 + x - 1), Mod(x - 2, x^2 + x - 1), Mod(2*x
+ + 2, x^2 + x - 1), Mod(-2*x - 1, x^2 + x - 1), Mod(2, x^2 + x - 1), Mod(-2*
+x + 2, x^2 + x - 1), Mod(-2*x - 4, x^2 + x - 1), Mod(x + 3, x^2 + x - 1), Mo
+d(3, x^2 + x - 1), Mod(2, x^2 + x - 1), Mod(2*x - 4, x^2 + x - 1), Mod(3*x, 
+x^2 + x - 1)]
+[[1, -2, 0, 2, -2, 0, -2, 0, 0, 4, 4, 0, 2, 4, 0, -4], [1, -1, 0, -1, 2, 0, 
+4, 3, 0, -2, -4, 0, 2, -4, 0, -1], [1, -1, 0, -1, 3, 0, -3, 3, 0, -3, 0, 0, 
+4, 3, 0, -1], [1, 1, 0, -1, -2, 0, 4, -3, 0, -2, 4, 0, 2, 4, 0, -1], [1, 1, 
+0, -1, 1, 0, -5, -3, 0, 1, 4, 0, -4, -5, 0, -1], [1, 2, 0, 2, 0, 0, 0, 0, 0,
+ 0, 6, 0, 4, 0, 0, -4]]
+
+[1 0 0 0 0 0]
+
+[0 1 0 0 0 0]
+
+[0 0 1 0 0 0]
+
+[0 0 0 1 0 0]
+
+[0 0 0 0 1 0]
+
+[0 0 0 0 0 1]
+
+1
+
+[ 1 -1/3    0  4  -2   1]
+
+[ 0    0    0 12  -6   3]
+
+[ 6   -3    0 78 -36  16]
+
+[ 3  1/3 -1/2 18  -7 5/2]
+
+[12    2   -2 60 -23   8]
+
+[12    3   -2 48 -18   6]
+
+1
+
+[  3    0 -1/3   24  -10   4]
+
+[  0    0    0  -18    6  -2]
+
+[ 24    0   -3  288 -120  48]
+
+[ -2 -1/2  1/3  -32   13  -5]
+
+[-12   -2    2 -180   73 -28]
+
+[-18   -2    3 -252  102 -39]
+
+1
+
+[ 1 0 0   10  -4   5/3]
+
+[-6 0 1  -60  24    -9]
+
+[ 6 1 0  150 -60    24]
+
+[ 0 0 0  -24  10 -25/6]
+
+[ 0 0 0 -120  49   -20]
+
+[ 0 0 0 -150  60   -24]
+
+1
+  ***   at top-level: msatkinlehner(W,4)
+  ***                 ^------------------
+  *** msatkinlehner: domain error in msatkinlehner: N % Q != 0
+
+[1 0 0    0   0   0]
+
+[0 1 0    0   0   0]
+
+[0 0 1 -144  60 -24]
+
+[0 0 0   25 -10   4]
+
+[0 0 0  120 -49  20]
+
+[0 0 0  144 -60  25]
+
+1
+1
+0
+1
+[[Mat([[1, 0; 0, 1], 1]), 0, 0, 0, 0], [0, Mat([[1, 0; 0, 1], 1]), 0, 0, 0],
+ [0, 0, Mat([[1, 0; 0, 1], 1]), 0, 0], [0, 0, 0, Mat([[1, 0; 0, 1], 1]), 0],
+ [0, 0, 0, 0, Mat([[1, 0; 0, 1], 1])]]
+Total time spent: 1184
diff --git a/src/test/32/modular b/src/test/32/modular
index 7c06e27..f7b7e30 100644
--- a/src/test/32/modular
+++ b/src/test/32/modular
@@ -65,4 +65,30 @@ Mod(0, 2)
 Mod(2, 7)
   *** _^_: Warning: Mod(a,b)^n with n >> b : wasteful.
 Mod(4, 7)
-Total time spent: 4
+   debug = 1
+  *** _+_: Warning: coercing quotient rings; moduli 2 and 3 -> 1.
+Mod(0, 1)
+  *** _-_: Warning: coercing quotient rings; moduli 2 and 3 -> 1.
+Mod(0, 1)
+  *** _*_: Warning: coercing quotient rings; moduli 2 and 3 -> 1.
+Mod(0, 1)
+  *** _/_: Warning: coercing quotient rings; moduli 2 and 3 -> 1.
+Mod(0, 1)
+Mod(0, 2)
+Mod(0, 2)
+Mod(1, 2)
+Mod(1, 2)
+  *** _+_: Warning: coercing quotient rings; moduli x and x + 1 -> 1.
+Mod(0, 1)
+  *** _-_: Warning: coercing quotient rings; moduli x and x + 1 -> 1.
+Mod(0, 1)
+  *** _*_: Warning: coercing quotient rings; moduli x and x + 1 -> 1.
+Mod(0, 1)
+  *** _/_: Warning: coercing quotient rings; moduli x and x + 1 -> 1.
+Mod(0, 1)
+Mod(2, x)
+Mod(0, x)
+Mod(1, x)
+Mod(1, x)
+1
+Total time spent: 0
diff --git a/src/test/32/nf b/src/test/32/nf
index c9036cc..aae316a 100644
--- a/src/test/32/nf
+++ b/src/test/32/nf
@@ -1,11 +1,10 @@
-   realprecision = 38 significant digits
 [85997496, [42998748, 2], [[408188227, 99620635; 0, 1], [2, 1; 0, 1]]]
-12.340047278667903334059769086970462220
-4.1894250945222025884896456921310573068
+12.340047278667903334059769086970462209
+4.1894250945222025884896456921310573069
 20915648110955829231381594293324156411897455346679838307589120000
 571459344155975480004612560667633185714077696
-[54898, [54898], [[1195, 78; 0, 1]]]
-[26, [26], [[19, 14, 5, 14; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1]]]
+[54898, [54898], [[7, 0; 0, 1]]]
+[26, [26], [[19, 15, 5, 13; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1]]]
 [1, [], []]
   *** zetakinit: Warning: non-monic polynomial. Result of the form [nf,c].
   *** zetakinit: Warning: non-monic polynomial. Change of variables discarded.
@@ -315,10 +314,10 @@ csmall([1])], [6, [6]], Mat([[2, [1, 2, 1, 0, 0]~, 1, 2, [0, -80, -20, 0, 0;
  0]~], [[1, 0, 0, -1, 0]~], [Vecsmall([])], Mat([0, 0, 0, 1, 0])]], [[2], [-
 1], [Vecsmall([1])]]], [1, 0; 0, 1]], [0, 0, 0; 1, 1, 1]], [[[[2, 0, 1, 0, 0
 ; 0, 2, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], Vecsmall([1])
-], [6, [6], [[-1, -1, 0, 0, 0]~]], Mat([[2, [1, 2, 1, 0, 0]~, 1, 2, [0, -80,
- -20, 0, 0; 0, -1, -100, -10, -120; 1, 0, -1, -20, -100; 0, 2, 0, 0, 0; 1, 1
-, -1, -10, 0]], 1]), [[[[3], [[1, 1, 0, 0, 0]~], [[1, 1, 0, 0, 0]~], [Vecsma
-ll([])], 1]], [[2], [-1], [Vecsmall([1])]]], Mat([-2, -3])], Mat([-3, 1, -3]
+], [6, [6], [[0, -1, 0, 0, 0]~]], Mat([[2, [1, 2, 1, 0, 0]~, 1, 2, [0, -80, 
+-20, 0, 0; 0, -1, -100, -10, -120; 1, 0, -1, -20, -100; 0, 2, 0, 0, 0; 1, 1,
+ -1, -10, 0]], 1]), [[[[3], [[0, 1, 0, 0, 0]~], [[0, 1, 0, 0, 0]~], [Vecsmal
+l([])], 1]], [[2], [-1], [Vecsmall([1])]]], Mat([-2, -3])], Mat([-3, -1, -3]
 )]]]
 [[[5, 1, [2, 2; 5, 2; 39821, 1; 161141, 1]]], [[]], [], [[10, 2, [2, 6; 5, 4
 ; 39821, 2; 161141, 2]], []]]
@@ -359,4 +358,79 @@ ll([])], 1]], [[2], [-1], [Vecsmall([1])]]], Mat([-2, -3])], Mat([-3, 1, -3]
   ***   at top-level: nfnewprec(vector(16)
   ***                 ^--------------------
   *** nfnewprec: incorrect type in nfnewprec (t_VEC).
-Total time spent: 1952
+[x^7 - x^6 + x^5 - x^4 - x^3 - x^2, x^9 + x^8 + x^7 + x^6 + 2*x^4 + 2*x^3 + 
+x^2 + x + 1, x^10 + x^9 - x^8 - x^3 - x^2 - x, x^10 + x^9 + 2*x^7 + x^6 + x^
+5 + x^4 + 2*x^2 + x + 1, -x^11 - 2*x^10 - x^8 - 2*x^7 - x^6 - x^5 - 2*x^4 - 
+x^3 - 2*x^2 - x - 1, -x^11 - x^10 - 2*x^9 - x^8 - 2*x^7 - x^6 - 2*x^5 - x^4 
+- x^2 - 2*x - 1, -x^11 - x^10 - x^9 + x^8 - x^7 + x^6, -x^11 - x^9 - x^6 + x
+^4 - x^3 + x, x^11 - x^10 + x^6 - x^5 - x^2 - x, x^11 - x^8 - x^7 + x^5 - x^
+4 - x, x^11 + x^10 + 2*x^8 + x^7 + x^4 + x^3 + 2*x^2 + x + 1, x^11 + 2*x^10 
++ x^9 + x^7 + x^5 + x^3 + x^2 + 2*x + 1]
+1
+[x^10 + Mod(-5/2*y + 5/2, y^2 - 5)*x^9 + Mod(-5*y + 20, y^2 - 5)*x^8 + Mod(-
+20*y + 30, y^2 - 5)*x^7 + Mod(-45/2*y + 145/2, y^2 - 5)*x^6 + Mod(-71/2*y + 
+121/2, y^2 - 5)*x^5 + Mod(-20*y + 60, y^2 - 5)*x^4 + Mod(-25*y + 5, y^2 - 5)
+*x^3 + 45*x^2 + Mod(-5*y + 15, y^2 - 5)*x + Mod(-2*y + 6, y^2 - 5), x^10 + M
+od(5/2*y + 5/2, y^2 - 5)*x^9 + Mod(5*y + 20, y^2 - 5)*x^8 + Mod(20*y + 30, y
+^2 - 5)*x^7 + Mod(45/2*y + 145/2, y^2 - 5)*x^6 + Mod(79/2*y + 121/2, y^2 - 5
+)*x^5 + Mod(25*y + 85, y^2 - 5)*x^4 + Mod(15*y + 55, y^2 - 5)*x^3 + Mod(10*y
+ - 5, y^2 - 5)*x^2 - 10*x + Mod(-2*y + 6, y^2 - 5)]
+[x^10 + Mod(-5/2*y + 5/2, y^2 - 5)*x^9 + Mod(-5*y + 20, y^2 - 5)*x^8 + Mod(-
+20*y + 30, y^2 - 5)*x^7 + Mod(-45/2*y + 145/2, y^2 - 5)*x^6 + Mod(-71/2*y + 
+121/2, y^2 - 5)*x^5 + Mod(-20*y + 60, y^2 - 5)*x^4 + Mod(-25*y + 5, y^2 - 5)
+*x^3 + 45*x^2 + Mod(-5*y + 15, y^2 - 5)*x + Mod(-2*y + 6, y^2 - 5), Mod(Mod(
+26/2945*y - 653/5890, y^2 - 5)*x^9 + Mod(1633/5890*y - 869/2945, y^2 - 5)*x^
+8 + Mod(2951/5890*y - 5939/2945, y^2 - 5)*x^7 + Mod(21757/11780*y - 29451/11
+780, y^2 - 5)*x^6 + Mod(18733/11780*y - 69587/11780, y^2 - 5)*x^5 + Mod(1445
+/589*y - 9436/2945, y^2 - 5)*x^4 + Mod(7893/11780*y - 34679/11780, y^2 - 5)*
+x^3 + Mod(9461/5890*y + 3919/2945, y^2 - 5)*x^2 + Mod(-8383/11780*y - 54699/
+11780, y^2 - 5)*x + Mod(261/589*y - 2467/2945, y^2 - 5), x^10 + Mod(-5/2*y +
+ 5/2, y^2 - 5)*x^9 + Mod(-5*y + 20, y^2 - 5)*x^8 + Mod(-20*y + 30, y^2 - 5)*
+x^7 + Mod(-45/2*y + 145/2, y^2 - 5)*x^6 + Mod(-71/2*y + 121/2, y^2 - 5)*x^5 
++ Mod(-20*y + 60, y^2 - 5)*x^4 + Mod(-25*y + 5, y^2 - 5)*x^3 + 45*x^2 + Mod(
+-5*y + 15, y^2 - 5)*x + Mod(-2*y + 6, y^2 - 5)), Mod(Mod(26/2945*y - 653/589
+0, y^2 - 5)*x^9 + Mod(1633/5890*y - 869/2945, y^2 - 5)*x^8 + Mod(2951/5890*y
+ - 5939/2945, y^2 - 5)*x^7 + Mod(21757/11780*y - 29451/11780, y^2 - 5)*x^6 +
+ Mod(18733/11780*y - 69587/11780, y^2 - 5)*x^5 + Mod(1445/589*y - 9436/2945,
+ y^2 - 5)*x^4 + Mod(7893/11780*y - 34679/11780, y^2 - 5)*x^3 + Mod(9461/5890
+*y + 3919/2945, y^2 - 5)*x^2 + Mod(-8383/11780*y - 42919/11780, y^2 - 5)*x +
+ Mod(261/589*y - 2467/2945, y^2 - 5), x^10 + Mod(-5/2*y + 5/2, y^2 - 5)*x^9 
++ Mod(-5*y + 20, y^2 - 5)*x^8 + Mod(-20*y + 30, y^2 - 5)*x^7 + Mod(-45/2*y +
+ 145/2, y^2 - 5)*x^6 + Mod(-71/2*y + 121/2, y^2 - 5)*x^5 + Mod(-20*y + 60, y
+^2 - 5)*x^4 + Mod(-25*y + 5, y^2 - 5)*x^3 + 45*x^2 + Mod(-5*y + 15, y^2 - 5)
+*x + Mod(-2*y + 6, y^2 - 5)), -1]
+Mod(0, x^10 + Mod(-5/2*y + 5/2, y^2 - 5)*x^9 + Mod(-5*y + 20, y^2 - 5)*x^8 +
+ Mod(-20*y + 30, y^2 - 5)*x^7 + Mod(-45/2*y + 145/2, y^2 - 5)*x^6 + Mod(-71/
+2*y + 121/2, y^2 - 5)*x^5 + Mod(-20*y + 60, y^2 - 5)*x^4 + Mod(-25*y + 5, y^
+2 - 5)*x^3 + 45*x^2 + Mod(-5*y + 15, y^2 - 5)*x + Mod(-2*y + 6, y^2 - 5))
+1
+[Mod(1, y^2 - 5)*x^5 + Mod(y, y^2 - 5), x^10 + Mod(77*y - 275, y^2 - 5)*x^5 
++ Mod(-41525*y + 96630, y^2 - 5), x^10 + Mod(77*y + 275, y^2 - 5)*x^5 + Mod(
+41525*y + 96630, y^2 - 5)]
+x^10 + 5*x^9 + 15*x^8 + 30*x^7 + 45*x^6 + Mod(2*y + 51, y^2 - 5)*x^5 + Mod(5
+*y + 45, y^2 - 5)*x^4 + Mod(-10*y + 30, y^2 - 5)*x^3 + Mod(-20*y + 15, y^2 -
+ 5)*x^2 + Mod(-5*y + 5, y^2 - 5)*x + Mod(y + 6, y^2 - 5)
+[x^10 + 5*x^9 + 15*x^8 + 30*x^7 + 45*x^6 + Mod(2*y + 51, y^2 - 5)*x^5 + Mod(
+5*y + 45, y^2 - 5)*x^4 + Mod(-10*y + 30, y^2 - 5)*x^3 + Mod(-20*y + 15, y^2 
+- 5)*x^2 + Mod(-5*y + 5, y^2 - 5)*x + Mod(y + 6, y^2 - 5), Mod(Mod(-32280/62
+2201, y^2 - 5)*x^9 + Mod(22275/622201*y - 145260/622201, y^2 - 5)*x^8 + Mod(
+89100/622201*y - 397350/622201, y^2 - 5)*x^7 + Mod(244100/622201*y - 22995/2
+0071, y^2 - 5)*x^6 + Mod(420450/622201*y - 918351/622201, y^2 - 5)*x^5 + Mod
+(510720/622201*y - 852705/622201, y^2 - 5)*x^4 + Mod(424640/622201*y - 23827
+5/622201, y^2 - 5)*x^3 + Mod(871950/622201*y + 235710/622201, y^2 - 5)*x^2 +
+ Mod(714855/622201*y - 1610346/622201, y^2 - 5)*x + Mod(-62626/622201*y - 86
+0751/622201, y^2 - 5), x^10 + 5*x^9 + 15*x^8 + 30*x^7 + 45*x^6 + Mod(2*y + 5
+1, y^2 - 5)*x^5 + Mod(5*y + 45, y^2 - 5)*x^4 + Mod(-10*y + 30, y^2 - 5)*x^3 
++ Mod(-20*y + 15, y^2 - 5)*x^2 + Mod(-5*y + 5, y^2 - 5)*x + Mod(y + 6, y^2 -
+ 5)), Mod(Mod(-32280/622201, y^2 - 5)*x^9 + Mod(22275/622201*y - 145260/6222
+01, y^2 - 5)*x^8 + Mod(89100/622201*y - 397350/622201, y^2 - 5)*x^7 + Mod(24
+4100/622201*y - 22995/20071, y^2 - 5)*x^6 + Mod(420450/622201*y - 918351/622
+201, y^2 - 5)*x^5 + Mod(510720/622201*y - 852705/622201, y^2 - 5)*x^4 + Mod(
+424640/622201*y - 238275/622201, y^2 - 5)*x^3 + Mod(871950/622201*y + 235710
+/622201, y^2 - 5)*x^2 + Mod(714855/622201*y - 988145/622201, y^2 - 5)*x + Mo
+d(-62626/622201*y - 860751/622201, y^2 - 5), x^10 + 5*x^9 + 15*x^8 + 30*x^7 
++ 45*x^6 + Mod(2*y + 51, y^2 - 5)*x^5 + Mod(5*y + 45, y^2 - 5)*x^4 + Mod(-10
+*y + 30, y^2 - 5)*x^3 + Mod(-20*y + 15, y^2 - 5)*x^2 + Mod(-5*y + 5, y^2 - 5
+)*x + Mod(y + 6, y^2 - 5)), -1]
+[x^2 + x + 1, Mod(0, x^2 + x + 1), Mod(x, x^2 + x + 1), -1]
+Total time spent: 1740
diff --git a/src/test/32/nfields b/src/test/32/nfields
index 42861e7..80d7e5f 100644
--- a/src/test/32/nfields
+++ b/src/test/32/nfields
@@ -5,21 +5,21 @@
 ? nfpol=x^5-5*x^3+5*x+25;nf=nfinit(nfpol)
 [x^5 - 5*x^3 + 5*x + 25, [1, 2], 595125, 45, [[1, -1.08911514572050482502495
 27946671612684, -2.4285174907194186068992069565359418365, 0.7194669112891317
-8943997506477288225737, -2.5558200350691694950646071159426779972; 1, -0.1383
+8943997506477288225734, -2.5558200350691694950646071159426779972; 1, -0.1383
 8372073406036365047976417441696637 - 0.4918163765776864349975328551474152510
 7*I, 1.9647119211288133163138753392090569931 + 0.809714924188978951282940822
-19556466857*I, -0.072312766896812300380582649294307897074 + 2.19808037538462
-76641195195160383234878*I, -0.98796319352507039803950539735452837193 + 1.570
+19556466857*I, -0.072312766896812300380582649294307897122 + 2.19808037538462
+76641195195160383234878*I, -0.98796319352507039803950539735452837195 + 1.570
 1452385894131769052374806001981109*I; 1, 1.682941293594312776162956161507997
 6006 + 2.0500351226010726172974286983598602164*I, -0.75045317576910401286427
 186094108607489 + 1.3101462685358123283560773619310445916*I, -0.787420688747
-75359433940488309213323154 + 2.1336633893126618034168454610457936018*I, 1.26
+75359433940488309213323155 + 2.1336633893126618034168454610457936018*I, 1.26
 58732110596551455718089553258673705 - 2.716479010374315056657802803578983483
 5*I], [1, -1.0891151457205048250249527946671612684, -2.428517490719418606899
-2069565359418365, 0.71946691128913178943997506477288225737, -2.5558200350691
-694950646071159426779972; 1, -0.63020009731174679864801261932183221743, 2.77
-44268453177922675968161614046216617, 2.1257676084878153637389368667440155907
-, 0.58218204506434277886573208324566973897; 1, 0.353432655843626071347053090
+2069565359418365, 0.71946691128913178943997506477288225734, -2.5558200350691
+694950646071159426779972; 1, -0.63020009731174679864801261932183221744, 2.77
+44268453177922675968161614046216617, 2.1257676084878153637389368667440155906
+, 0.58218204506434277886573208324566973893; 1, 0.353432655843626071347053090
 97299828470, 1.1549969969398343650309345170134923246, -2.2703931422814399645
 001021653326313849, -2.5581084321144835749447428779547264828; 1, 3.732976416
 1953853934603848598678578170, 0.55969309276670831549180550098995851667, 1.34
@@ -47,28 +47,28 @@
 ? nfinit(nfpol,2)
 [x^5 - 2*x^4 + 3*x^3 + 8*x^2 + 3*x + 2, [1, 2], 595125, 4, [[1, -1.089115145
 7205048250249527946671612684, -2.4285174907194186068992069565359418365, 0.71
-946691128913178943997506477288225735, -2.55582003506916949506460711594267799
-71; 1, -0.13838372073406036365047976417441696637 + 0.49181637657768643499753
+946691128913178943997506477288225734, -2.55582003506916949506460711594267799
+72; 1, -0.13838372073406036365047976417441696637 + 0.49181637657768643499753
 285514741525107*I, 1.9647119211288133163138753392090569931 - 0.8097149241889
-7895128294082219556466857*I, -0.072312766896812300380582649294307897123 - 2.
+7895128294082219556466857*I, -0.072312766896812300380582649294307897122 - 2.
 1980803753846276641195195160383234878*I, -0.98796319352507039803950539735452
 837195 - 1.5701452385894131769052374806001981109*I; 1, 1.6829412935943127761
 629561615079976006 + 2.0500351226010726172974286983598602164*I, -0.750453175
-76910401286427186094108607490 + 1.3101462685358123283560773619310445915*I, -
-0.78742068874775359433940488309213323160 + 2.1336633893126618034168454610457
-936016*I, 1.2658732110596551455718089553258673704 - 2.7164790103743150566578
-028035789834836*I], [1, -1.0891151457205048250249527946671612684, -2.4285174
-907194186068992069565359418365, 0.71946691128913178943997506477288225735, -2
-.5558200350691694950646071159426779971; 1, 0.3534326558436260713470530909729
+76910401286427186094108607489 + 1.3101462685358123283560773619310445916*I, -
+0.78742068874775359433940488309213323155 + 2.1336633893126618034168454610457
+936018*I, 1.2658732110596551455718089553258673705 - 2.7164790103743150566578
+028035789834835*I], [1, -1.0891151457205048250249527946671612684, -2.4285174
+907194186068992069565359418365, 0.71946691128913178943997506477288225734, -2
+.5558200350691694950646071159426779972; 1, 0.3534326558436260713470530909729
 9828470, 1.1549969969398343650309345170134923246, -2.27039314228143996450010
 21653326313849, -2.5581084321144835749447428779547264828; 1, -0.630200097311
 74679864801261932183221744, 2.7744268453177922675968161614046216617, 2.12576
 76084878153637389368667440155906, 0.58218204506434277886573208324566973893; 
 1, 3.7329764161953853934603848598678578170, 0.559693092766708315491805500989
-95851657, 1.3462427005649082090774405779536603700, -1.4506057993146599110859
-938482531161132; 1, -0.36709382900675984113447253685186261580, -2.0605994443
-049163412203492228721306664, -2.9210840780604153977562503441379268332, 3.982
-3522214339702022296117589048508541], [1, -1, -2, 1, -3; 1, 0, 1, -2, -3; 1, 
+95851667, 1.3462427005649082090774405779536603703, -1.4506057993146599110859
+938482531161129; 1, -0.36709382900675984113447253685186261580, -2.0605994443
+049163412203492228721306665, -2.9210840780604153977562503441379268334, 3.982
+3522214339702022296117589048508540], [1, -1, -2, 1, -3; 1, 0, 1, -2, -3; 1, 
 -1, 3, 2, 1; 1, 4, 1, 1, -1; 1, 0, -2, -3, 4], [5, 2, 0, -1, -2; 2, -2, -5, 
 -10, 20; 0, -5, 10, -10, 5; -1, -10, -10, -17, 1; -2, 20, 5, 1, -8], [345, 0
 , 200, 110, 177; 0, 345, 95, 1, 145; 0, 0, 5, 4, 3; 0, 0, 0, 1, 0; 0, 0, 0, 
@@ -96,17 +96,17 @@ x + 2)
 [Mat(3), Mat([1, 1, 2]), [-2.7124653051843439746808795106061300699 + 3.14159
 26535897932384626433832795028842*I; 2.7124653051843439746808795106061300699]
 , [1.7903417566977293763292119206302198761, 1.289761953065273502503008607239
-5031018 + 3.1415926535897932384626433832795028842*I, 0.E-37, 0.5005798036324
+5031017 + 3.1415926535897932384626433832795028842*I, 0.E-57, 0.5005798036324
 5587382620331339071677436; -1.7903417566977293763292119206302198761, -1.2897
-619530652735025030086072395031018, 0.E-38, -0.500579803632455873826203313390
+619530652735025030086072395031017, 0.E-57, -0.500579803632455873826203313390
 71677436 + 3.1415926535897932384626433832795028842*I], [[3, [-1, 1]~, 1, 1, 
 [0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 57; 1, 2]], [3, [0, 1]~, 1, 1, [-1, 
 57; 1, 0]], [5, [1, 1]~, 1, 1, [-2, 57; 1, -1]]], 0, [x^2 - x - 57, [2, 0], 
 229, 1, [[1, -7.0663729752107779635959310246705326059; 1, 8.0663729752107779
-635959310246705326058], [1, -7.0663729752107779635959310246705326059; 1, 8.0
-663729752107779635959310246705326058], [1, -7; 1, 8], [2, 1; 1, 115], [229, 
+635959310246705326059], [1, -7.0663729752107779635959310246705326059; 1, 8.0
+663729752107779635959310246705326059], [1, -7; 1, 8], [2, 1; 1, 115], [229, 
 114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]], [229]], [-7.06637297
-52107779635959310246705326059, 8.0663729752107779635959310246705326058], [1,
+52107779635959310246705326059, 8.0663729752107779635959310246705326059], [1,
  x], [1, 0; 0, 1], [1, 0, 0, 57; 0, 1, 1, 1]], [[3, [3], [[3, 2; 0, 1]]], 2.
 7124653051843439746808795106061300699, 1, [2, -1], [x + 7]], [Mat(1), [[0, 0
 ]], [[1.7903417566977293763292119206302198761, -1.79034175669772937632921192
@@ -178,31 +178,31 @@ x + 2)
 4 - 8374015687535120430*x^3 + 8907744727915040221*x^2 + 4155976664123434381*
 x + 318920215718580450], 1/83718587879473471], [[49744, 0, 0; 0, 49744, 0; 0
 , 0, 49744], 3109], 1, [], [], [[1, x, x^2, x^3, x^4], [1, 1, 1, 1, 1]], [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], []
-, [y^3 - y - 1, [1, 1], -23, 1, [[1, 0.7548776662466927600495088963585286919
-0, 1.3247179572447460259609088544780973407; 1, -0.87743883312334638002475444
-817926434595 - 0.74486176661974423659317042860439236724*I, -0.66235897862237
-301298045442723904867037 + 0.56227951206230124389918214490937306150*I], [1, 
-0.75487766624669276004950889635852869190, 1.32471795724474602596090885447809
-73407; 1, -1.6223005997430906166179248767836567132, -0.100079466560071769081
-27228232967560887; 1, -0.13257706650360214343158401957487197871, -1.22463849
-06846742568796365721484217319], [1, 1, 1; 1, -2, 0; 1, 0, -1], [3, -1, 0; -1
-, 1, 3; 0, 3, 2], [23, 16, 13; 0, 1, 0; 0, 0, 1], [7, -2, 3; -2, -6, 9; 3, 9
-, -2], [23, [10, 1, 8; 7, 3, 1; 1, 7, 10]], [23]], [1.3247179572447460259609
-088544780973407, -0.66235897862237301298045442723904867037 + 0.5622795120623
-0124389918214490937306150*I], [1, y^2 - 1, y], [1, 0, 1; 0, 0, 1; 0, 1, 0], 
-[1, 0, 0, 0, 0, 1, 0, 1, 1; 0, 1, 0, 1, -1, 0, 0, 0, 1; 0, 0, 1, 0, 1, 0, 1,
- 0, 0]], [x^15 - 5*x^13 + 5*x^12 + 7*x^11 - 26*x^10 - 5*x^9 + 45*x^8 + 158*x
-^7 - 98*x^6 + 110*x^5 - 190*x^4 + 189*x^3 + 144*x^2 + 25*x + 1, 395165361655
-38345/83718587879473471*x^14 - 6500512476832995/83718587879473471*x^13 - 196
-215472046117185/83718587879473471*x^12 + 229902227480108910/8371858787947347
-1*x^11 + 237380704030959181/83718587879473471*x^10 - 1064931988160773805/837
-18587879473471*x^9 - 20657086671714300/83718587879473471*x^8 + 1772885205999
-206010/83718587879473471*x^7 + 5952033217241102348/83718587879473471*x^6 - 4
-838840187320655696/83718587879473471*x^5 + 5180390720553188700/8371858787947
-3471*x^4 - 8374015687535120430/83718587879473471*x^3 + 8907744727915040221/8
-3718587879473471*x^2 + 4155976664123434381/83718587879473471*x + 31892021571
-8580450/83718587879473471, -1, y^3 - y - 1, x^5 - x - 2], [0, 0]]
+ 0, 0, 0, 0; 0, 1, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], 1,
+ [y^3 - y - 1, [1, 1], -23, 1, [[1, 0.75487766624669276004950889635852869189
+, 1.3247179572447460259609088544780973407; 1, -0.877438833123346380024754448
+17926434595 - 0.74486176661974423659317042860439236724*I, -0.662358978622373
+01298045442723904867037 + 0.56227951206230124389918214490937306150*I], [1, 0
+.75487766624669276004950889635852869189, 1.324717957244746025960908854478097
+3407; 1, -1.6223005997430906166179248767836567132, -0.1000794665600717690812
+7228232967560887; 1, -0.13257706650360214343158401957487197871, -1.224638490
+6846742568796365721484217319], [1, 1, 1; 1, -2, 0; 1, 0, -1], [3, -1, 0; -1,
+ 1, 3; 0, 3, 2], [23, 16, 13; 0, 1, 0; 0, 0, 1], [7, -2, 3; -2, -6, 9; 3, 9,
+ -2], [23, [10, 1, 8; 7, 3, 1; 1, 7, 10]], [23]], [1.32471795724474602596090
+88544780973407, -0.66235897862237301298045442723904867037 + 0.56227951206230
+124389918214490937306150*I], [1, y^2 - 1, y], [1, 0, 1; 0, 0, 1; 0, 1, 0], [
+1, 0, 0, 0, 0, 1, 0, 1, 1; 0, 1, 0, 1, -1, 0, 0, 0, 1; 0, 0, 1, 0, 1, 0, 1, 
+0, 0]], [x^15 - 5*x^13 + 5*x^12 + 7*x^11 - 26*x^10 - 5*x^9 + 45*x^8 + 158*x^
+7 - 98*x^6 + 110*x^5 - 190*x^4 + 189*x^3 + 144*x^2 + 25*x + 1, 3951653616553
+8345/83718587879473471*x^14 - 6500512476832995/83718587879473471*x^13 - 1962
+15472046117185/83718587879473471*x^12 + 229902227480108910/83718587879473471
+*x^11 + 237380704030959181/83718587879473471*x^10 - 1064931988160773805/8371
+8587879473471*x^9 - 20657086671714300/83718587879473471*x^8 + 17728852059992
+06010/83718587879473471*x^7 + 5952033217241102348/83718587879473471*x^6 - 48
+38840187320655696/83718587879473471*x^5 + 5180390720553188700/83718587879473
+471*x^4 - 8374015687535120430/83718587879473471*x^3 + 8907744727915040221/83
+718587879473471*x^2 + 4155976664123434381/83718587879473471*x + 318920215718
+580450/83718587879473471, -1, y^3 - y - 1, x^5 - x - 2], [0]]
 ? bnfcertify(bnf)
 1
 ? dobnf(x^4+24*x^2+585*x+1791,,[0.1,0.1])
@@ -445,16 +445,16 @@ x + 318920215718580450], 1/83718587879473471], [[49744, 0, 0; 0, 49744, 0; 0
 , 6; 0, 2], [10, 2; 0, 2]]]
 ? bid=idealstar(nf2,54)
 [[[54, 0, 0; 0, 54, 0; 0, 0, 54], [0]], [132678, [1638, 9, 9]], [[2, [2, 0, 
-0]~, 1, 3, 1], 1; [3, [3, 0, 0]~, 1, 3, 1], 3], [[[[7], [[2, 1, 0]~], [[-26,
- -27, 0]~], [Vecsmall([])], 1]], [[[26], [[2, 2, 0]~], [[-25, 2, 0]~], [Vecs
-mall([])], 1], [[3, 3, 3], [4, [1, 3, 0]~, [1, 0, 3]~], [-77, [1, -24, 0]~, 
-[1, 0, -24]~], [Vecsmall([]), Vecsmall([]), Vecsmall([])], [1/3, 0, 0; 0, 1/
-3, 0; 0, 0, 1/3]], [[3, 3, 3], [10, [1, 9, 0]~, [1, 0, 9]~], [-233, [1, -18,
- 0]~, [1, 0, -18]~], [Vecsmall([]), Vecsmall([]), Vecsmall([])], [1/9, 0, 0;
- 0, 1/9, 0; 0, 0, 1/9]]], [[], [], []]], [468, 469, 0, 0, -910, 0, 0, -1092;
- 0, 0, 1, 0, -3, -6, 0, 0; 0, 0, 0, 1, -3, 0, -6, 0]]
+0]~, 1, 3, 1], 1; [3, [3, 0, 0]~, 1, 3, 1], 3], [[[[7], [[2, 1, 1]~], [[-26,
+ -27, -27]~], [Vecsmall([])], 1]], [[[26], [[4, 2, 1]~], [[-23, 2, -26]~], [
+Vecsmall([])], 1], [[3, 3, 3], [4, [1, 3, 0]~, [1, 0, 3]~], [-77, [1, -24, 0
+]~, [1, 0, -24]~], [Vecsmall([]), Vecsmall([]), Vecsmall([])], [1/3, 0, 0; 0
+, 1/3, 0; 0, 0, 1/3]], [[3, 3, 3], [10, [1, 9, 0]~, [1, 0, 9]~], [-233, [1, 
+-18, 0]~, [1, 0, -18]~], [Vecsmall([]), Vecsmall([]), Vecsmall([])], [1/9, 0
+, 0; 0, 1/9, 0; 0, 0, 1/9]]], [[], [], []]], [468, -77, 0, 728, -1456, 0, 54
+6, -1092; 0, 0, 1, 0, -1, -6, 0, -3; 0, 1, 0, -1, 1, 0, -3, 3]]
 ? ideallog(nf2,y,bid)
-[176, 2, 0]~
+[284, 1, 1]~
 ? idealmin(nf,idx,[1,2,3])
 [1, 0, 1, 0, 0]~
 ? idealnorm(nf,idt)
@@ -501,14 +501,14 @@ mall([])], 1], [[3, 3, 3], [4, [1, 3, 0]~, [1, 0, 3]~], [-77, [1, -24, 0]~,
 [-1, 4, 2, 4, 2]~
 ? idealstar(nf2,54)
 [[[54, 0, 0; 0, 54, 0; 0, 0, 54], [0]], [132678, [1638, 9, 9]], [[2, [2, 0, 
-0]~, 1, 3, 1], 1; [3, [3, 0, 0]~, 1, 3, 1], 3], [[[[7], [[2, 1, 1]~], [[-26,
- -27, -27]~], [Vecsmall([])], 1]], [[[26], [[4, 2, 2]~], [[-23, 2, 2]~], [Ve
-csmall([])], 1], [[3, 3, 3], [4, [1, 3, 0]~, [1, 0, 3]~], [-77, [1, -24, 0]~
-, [1, 0, -24]~], [Vecsmall([]), Vecsmall([]), Vecsmall([])], [1/3, 0, 0; 0, 
-1/3, 0; 0, 0, 1/3]], [[3, 3, 3], [10, [1, 9, 0]~, [1, 0, 9]~], [-233, [1, -1
-8, 0]~, [1, 0, -18]~], [Vecsmall([]), Vecsmall([]), Vecsmall([])], [1/9, 0, 
-0; 0, 1/9, 0; 0, 0, 1/9]]], [[], [], []]], [468, 469, 0, 0, -364, 0, 0, -109
-2; 0, 0, 1, 0, -6, -6, 0, 0; 0, 0, 0, 1, -3, 0, -6, 0]]
+0]~, 1, 3, 1], 1; [3, [3, 0, 0]~, 1, 3, 1], 3], [[[[7], [[0, 0, 1]~], [[-26,
+ 0, -27]~], [Vecsmall([])], 1]], [[[26], [[0, 0, 2]~], [[-27, 0, 2]~], [Vecs
+mall([])], 1], [[3, 3, 3], [4, [1, 3, 0]~, [1, 0, 3]~], [-77, [1, -24, 0]~, 
+[1, 0, -24]~], [Vecsmall([]), Vecsmall([]), Vecsmall([])], [1/3, 0, 0; 0, 1/
+3, 0; 0, 0, 1/3]], [[3, 3, 3], [10, [1, 9, 0]~, [1, 0, 9]~], [-233, [1, -18,
+ 0]~, [1, 0, -18]~], [Vecsmall([]), Vecsmall([]), Vecsmall([])], [1/9, 0, 0;
+ 0, 1/9, 0; 0, 0, 1/9]]], [[], [], []]], [468, 469, 0, 0, -182, 0, 0, -546; 
+0, 0, 1, 0, -7, -6, 0, -3; 0, 0, 0, 1, -3, 0, -6, 0]]
 ? idealval(nf,idp,vp)
 7
 ? ba=nfalgtobasis(nf,x^3+5)
@@ -529,23 +529,10 @@ csmall([])], 1], [[3, 3, 3], [4, [1, 3, 0]~, [1, 0, 3]~], [-77, [1, -24, 0]~
 
 ? nfbasis(x^3+4*x+5)
 [1, x, 1/7*x^2 - 1/7*x - 2/7]
-? nfbasis(x^3+4*x+5,2)
-[1, x, 1/7*x^2 - 1/7*x - 2/7]
-? nfbasis(x^3+4*x+12,1)
-[1, x, 1/2*x^2]
 ? nfbasistoalg(nf,ba)
 Mod(x^3 + 5, x^5 - 5*x^3 + 5*x + 25)
-? nfbasis(p2,0,fa)
-[1, x, x^2, 1/11699*x^3 + 1847/11699*x^2 - 132/11699*x - 2641/11699, 1/13962
-3738889203638909659*x^4 - 1552451622081122020/139623738889203638909659*x^3 +
- 418509858130821123141/139623738889203638909659*x^2 - 6810913798507599407313
-4/139623738889203638909659*x - 13185339461968406/58346808996920447]
 ? nfdisc(x^3+4*x+12)
 -1036
-? nfdisc(x^3+4*x+12,1)
--1036
-? nfdisc(p2,0,fa)
-136866601
 ? nfeltdiv(nf,ba,bb)
 [584/373, 66/373, -32/373, -105/373, 120/373]~
 ? nfeltdiveuc(nf,ba,bb)
@@ -578,8 +565,8 @@ Mod(-1/2*x^5 + 9*x^2, x^6 + 108)
 ? nfhilbert(nf,3,5,vp)
 -1
 ? nfhnf(nf,[a,aid])
-[[1, -1, -1; 0, 1, 0; 0, 0, 1], [[3, 2, 1, 0, 1; 0, 1, 0, 0, 0; 0, 0, 1, 0, 
-0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], 1, 1]]
+[[1, 1, 4; 0, 1, 0; 0, 0, 1], [[15, 2, 10, 12, 4; 0, 1, 0, 0, 0; 0, 0, 1, 0,
+ 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], 1, 1]]
 ? da=nfdetint(nf,[a,aid])
 
 [15 10 5 0 12]
@@ -593,8 +580,8 @@ Mod(-1/2*x^5 + 9*x^2, x^6 + 108)
 [ 0  0 0 0  1]
 
 ? nfhnfmod(nf,[a,aid],da)
-[[1, -1, -1; 0, 1, 0; 0, 0, 1], [[3, 2, 1, 0, 1; 0, 1, 0, 0, 0; 0, 0, 1, 0, 
-0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], 1, 1]]
+[[1, 1, 4; 0, 1, 0; 0, 0, 1], [[15, 2, 10, 12, 4; 0, 1, 0, 0, 0; 0, 0, 1, 0,
+ 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], 1, 1]]
 ? nfisideal(bnf[7],[5,1;0,1])
 1
 ? nfisincl(x^2+1,x^4+1)
@@ -610,11 +597,11 @@ Mod(-1/2*x^5 + 9*x^2, x^6 + 108)
 ? nfrootsof1(nf)
 [2, -1]
 ? nfsnf(nf,[a[,1..3],[1,1,1],[idealinv(nf,idx),idealinv(nf,idy),1]])
-[[5113790367401366394295125, 4367721766083689974291960, 47291190972301090559
-2775, 4905437241737335488566685, 4697851874666647634403882; 0, 5, 0, 0, 2; 0
-, 0, 5, 0, 1; 0, 0, 0, 5, 2; 0, 0, 0, 0, 1], [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], [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]]
+[[15706993357777254170417850, 1636878763571210697462070, 1307908830618593502
+9427775, 1815705333955314515809980, 7581330311082212790621785; 0, 5, 0, 0, 0
+; 0, 0, 5, 0, 0; 0, 0, 0, 5, 0; 0, 0, 0, 0, 5], [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], [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]]
 ? nfsubfields(nf)
 [[x, 0], [x^5 - 5*x^3 + 5*x + 25, x]]
 ? polcompositum(x^4-4*x+2,x^3-x-1)
@@ -686,7 +673,7 @@ x^5 - x^4 + 2*x^3 - 4*x^2 + x - 1
 ? polsubcyclo(31,5)
 x^5 + x^4 - 12*x^3 - 21*x^2 + x + 5
 ? setrand(1);poltschirnhaus(x^5-x-1)
-x^5 - 15*x^4 + 88*x^3 - 273*x^2 + 532*x - 304
+x^5 + 10*x^4 + 32*x^3 - 100*x^2 - 879*x - 1457
 ? p=x^5-5*x+y;aa=rnfpseudobasis(nf2,p)
 [[1, 0, 0, -2, [3, 1, 0]~; 0, 1, 0, 2, [0, -1, 0]~; 0, 0, 1, 1, [-5, -2, 0]~
 ; 0, 0, 0, 1, -2; 0, 0, 0, 0, 1], [1, 1, 1, [1, 0, 2/5; 0, 1, 3/5; 0, 0, 1/5
@@ -736,16 +723,13 @@ x^15 - 15*x^11 + 75*x^7 - x^5 - 125*x^3 + 5*x + 1
 ? zetak(nfz,-3)
 0.091666666666666666666666666666666666667
 ? zetak(nfz,1.5+3*I)
-0.88324345992059326405525724366416928892 - 0.2067536250233895222724230899142
-7938848*I
+0.88324345992059326405525724366416928890 - 0.2067536250233895222724230899142
+7938845*I
 ? setrand(1);quadclassunit(1-10^7,,[1,1])
 [2416, [1208, 2], [Qfb(277, 55, 9028), Qfb(1700, 1249, 1700)], 1]
 ? setrand(1);quadclassunit(10^9-3,,[0.5,0.5])
-[4, [4], [Qfb(199, 31533, -7123, 0.E-57)], 2800.6252519070160764863706217370
-745514]
-? sizebyte(%)
-156
-? getheap
-[217, 100743]
+[4, [4], [Qfb(211, 31405, -16263, 0.E-38)], 2800.625251907016076486370621737
+0745514]
+? if(getheap()!=HEAP,getheap())
 ? print("Total time spent: ",gettime);
-Total time spent: 116
+Total time spent: 88
diff --git a/src/test/32/nfsplitting b/src/test/32/nfsplitting
new file mode 100644
index 0000000..3040b0a
--- /dev/null
+++ b/src/test/32/nfsplitting
@@ -0,0 +1,48 @@
+  ***   at top-level: nfsplitting(1)
+  ***                 ^--------------
+  *** nfsplitting: incorrect type in checknf [please apply nfinit()] (t_INT).
+x
+x
+x
+x^120 + 900*x^116 + 508450*x^112 + 3093750*x^110 + 233445700*x^108 + 6244625
+000*x^106 + 86356219375*x^104 + 6147962343750*x^102 - 9942720082555*x^100 + 
+3349338126562500*x^98 - 1654757011326100*x^96 + 1309871930885937500*x^94 + 1
+2436255994792015950*x^92 + 627622053389650906250*x^90 + 10990443401191124447
+575*x^88 + 376988045414723757750000*x^86 + 5753330797521192519076250*x^84 + 
+177095246957480012540937500*x^82 + 2532236050928665494862464460*x^80 + 66602
+887475268525125564843750*x^78 + 900151039266122540911840715400*x^76 + 176011
+62771342375630639534375000*x^74 + 297430062665456220256577151477075*x^72 + 2
+930309217240262538594060043562500*x^70 + 72799466070683508609604970583641825
+*x^68 + 544024340743931708706461811877750000*x^66 + 815192787279703050465510
+9860308253125*x^64 + 109815744628769444357250042241632031250*x^62 + 14587139
+1991398970515017378630342573815*x^60 + 8649858988205592244458199943754150781
+250*x^58 - 28260531870665143418958164521279483618600*x^56 - 4028396539193675
+80525292500109637748437500*x^54 + 106953851435466039913768978932670329879545
+0*x^52 - 117799258418763740543911272144086881778781250*x^50 + 21225667468078
+1774826232152789145244306484575*x^48 - 1157371878847856250227888707333507692
+960375000*x^46 - 60605754850991956455326492294916133973935406250*x^44 - 2931
+8354970878696157506850322206226355212812500*x^42 + 2969007992022620344286139
+006599749400952695117330*x^40 + 18940874618289173736585545257929220177884468
+75000*x^38 - 462258652890221831497176176774279926624850728121600*x^36 - 7387
+86176377220399331352006274159764367952001562500*x^34 - 271554668935406462553
+6181765731364171583296080250050*x^32 + 9040698598507624900324513465462196895
+3701672354656250*x^30 + 6671002781929457078914865848663080213892617538608397
+00*x^28 + 8674210771396452568056517384098059387025568935299000000*x^26 + 398
+10727829888294052738784121978440350534098819581529375*x^24 + 165091395418543
+016833097401882144226762030772580167343750*x^22 + 27455383835034865960434299
+3914027364500470431599325551949*x^20 + 5727389048071940962286881233887371037
+10592833161132812500*x^18 + 680363944593316626764117242129370969026933149388
+6975000*x^16 + 1207367254754819680587174702262138380906821896553743750000*x^
+14 + 1324631954910684324357431850891744535485699735726160156250*x^12 - 24458
+13956434295007552447734476548803933624572506738281250*x^10 + 309719742207326
+9812049512199025218992726116649855468750000*x^8 + 34385172087788316066248428
+61577883803163997230102539062500*x^6 - 3386560639084519090735630415918618954
+238015795898437500000*x^4 + 105395630279973820390312384403539563373280780029
+2968750000*x^2 + 1865600384408017914532215685346909435223786258697509765625
+x^32 - 10356*x^24 + 127847862*x^16 - 11069073684*x^8 + 565036352721
+x^32 - 10356*x^24 + 127847862*x^16 - 11069073684*x^8 + 565036352721
+x^32 - 10356*x^24 + 127847862*x^16 - 11069073684*x^8 + 565036352721
+x^10 - 30*x^8 + 325*x^6 - 1500*x^4 + 2500*x^2 + 2000
+x^22 + x^21 + x^20 + x^19 + x^18 + x^17 + x^16 + x^15 + x^14 + x^13 + x^12 +
+ x^11 + x^10 + x^9 + x^8 + x^7 + x^6 + x^5 + x^4 + x^3 + x^2 + x + 1
+Total time spent: 372
diff --git a/src/test/32/objets b/src/test/32/objets
index c2e564c..a212eee 100644
--- a/src/test/32/objets
+++ b/src/test/32/objets
@@ -120,6 +120,7 @@ O(x^12)
   ***   at top-level: Mod(10873,49649)^-1
   ***                                 ^---
   *** _^_: impossible inverse in Fp_inv: Mod(131, 49649).
-? if(getheap()!=HEAP,getheap())
+? (1+I)*(1+1/2*I)
+1/2 + 3/2*I
 ? print("Total time spent: ",gettime);
 Total time spent: 4
diff --git a/src/test/32/op b/src/test/32/op
index f2779cb..6a346b6 100644
--- a/src/test/32/op
+++ b/src/test/32/op
@@ -4,4 +4,10 @@
 10
 2
 [2, 3, 1, 10, 2]
+3
+1
+2
+2
+[2, 2, 2, 10, 2]
+[3, 3, 1, 10, 1]
 Total time spent: 0
diff --git a/src/test/32/padic b/src/test/32/padic
index 7627574..dec846c 100644
--- a/src/test/32/padic
+++ b/src/test/32/padic
@@ -6,17 +6,29 @@
   ***                 ^--------------------
   *** padicappr: inconsistent moduli in Zp_to_Z: 5 != 3
 
-[(1 + O(7^8))*y + O(7^8) 1]
-
-[(1 + O(7^8))*y + (3 + 2*7 + 6*7^2 + 2*7^3 + 7^4 + 7^5 + 5*7^6 + 2*7^7 + O(7
-^8)) 1]
-
-[(1 + O(7^8))*y + (4 + 4*7 + 4*7^3 + 5*7^4 + 5*7^5 + 7^6 + 4*7^7 + O(7^8)) 1
-]
-
-
 [(1 + O(3^5))*y^2 + O(3^5)*y + O(3^5) 1]
 
+[303091841983800080655794283008425100039742205409907463050265866099342335310
+9435450473759394409290772958513969209043309887654107823563961950120902162328
+9769326760830012577046380799009644065843091379678844848336197237093057023804
+6689848912926486505130709901883062497124814860382257802988956439425088932461
+0372025296688642620365911220110991569990328464459735660494309717728461213007
+1801499708339544755377536878289360381720619549093067863866419820272280136477
+2830800728859838435544923858759881340490985695391715382902245978494662272462
+6052864155393228763598731308273292630444845297138100310999495119765776446322
+3860052732483765519446500500094346234790611688099389032815052584811119320550
+3704669618458110652816974131143493927907230211763195122366400692171033393720
+271195569191, 13020836829112671085985220226774471665002775641446996088876884
+3691338423847199876670450857336997350275120427670497827105902457829900805568
+9719472368109783134615365374621272645318492298469870785155840876721739513480
+5863213246980524738313176449660582809667252629484206997514702295002515061510
+0684360909834392213592414944152124335972138550682495171014579333479279921333
+5904066365587070683781105745761987654966795582331907184529593280396827369610
+2019154579782144905432984081972843049020762285632803482844786928852456176727
+9344982547780680381242398549057381848394717649769513041214735182126715458420
+8350305350756518594813992253867533694908369935455537375264348437017294628673
+7633210413290943225901496946252789071904264368534914051665187493778714162848
+7537382321251210717887612]~
 [2, 2, 2]
 [3, 2, 2]
 [6, 2, 2]
diff --git a/src/test/32/ploth b/src/test/32/ploth
index 1a02c3f..9e5d674 100644
--- a/src/test/32/ploth
+++ b/src/test/32/ploth
@@ -12,6 +12,81 @@
 ? plotlines(0,vector(5,k,50*k),vector(5,k,10*k*k))
 ? plotmove(0,243,583);plotcursor(0)
 [243, 583]
+? plot(x=-1,1,floor(x))
+
+        0 --------------------------------""""""""""""""""""""""""""""""""
+          |                               :                              |
+          |                               :                              |
+          |                               :                              |
+          |                               :                              |
+          |                               :                              |
+          |                               :                              |
+          |                               :                              |
+          |                               :                              |
+          |                               :                              |
+          |                               :                              |
+          |                              :                               |
+          |                              :                               |
+          |                              :                               |
+          |                              :                               |
+          |                              :                               |
+          |                              :                               |
+          |                              :                               |
+          |                              :                               |
+          |                              :                               |
+          |                              :                               |
+       -1 ________________________________...............................|
+          -1                                                             1
+? plot(x=-1,1,-floor(x))
+
+        1 """"""""""""""""""""""""""""""""'''''''''''''''''''''''''''''''|
+          |                              :                               |
+          |                              :                               |
+          |                              :                               |
+          |                              :                               |
+          |                              :                               |
+          |                              :                               |
+          |                              :                               |
+          |                              :                               |
+          |                              :                               |
+          |                              :                               |
+          |                               :                              |
+          |                               :                              |
+          |                               :                              |
+          |                               :                              |
+          |                               :                              |
+          |                               :                              |
+          |                               :                              |
+          |                               :                              |
+          |                               :                              |
+          |                               :                              |
+        0 ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,________________________________
+          -1                                                             1
+? plot(x=0,1,-0.29)
+
+     0.71 |''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''|
+          |                                                              |
+          |                                                              |
+          |                                                              |
+          |                                                              |
+          |                                                              |
+          |                                                              |
+          |                                                              |
+          |                                                              |
+          |                                                              |
+          |                                                              |
+          |                                                              |
+          |                                                              |
+          |                                                              |
+          |                                                              |
+          ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+          |                                                              |
+          |                                                              |
+          |                                                              |
+          |                                                              |
+          |                                                              |
+    -0.29 ________________________________________________________________
+          0                                                              1
 ? plot(x=-5,5,sin(x))
 
 0.9995545 x""x_''''''''''''''''''''''''''''''''''_x""x'''''''''''''''''''|
@@ -43,14 +118,10 @@
 ? ploth(t=0,2*Pi,[sin(5*t),sin(7*t)])
 [0.E-307, 6.283185307179586232, -0.9999987638285974256, 0.999998763828597425
 6]
-? ploth(t=0,2*Pi,[sin(5*t),sin(7*t)],1,100)
+? ploth(t=0,2*Pi,[sin(5*t),sin(7*t)],"Parametric",100)
 [-0.9998741276738750683, 0.9998741276738750683, -0.9998741276738750683, 0.99
 98741276738750683]
-? ploth(t=0,2*Pi,[sin(5*t),sin(7*t)],2,100)
-  ***   at top-level: ploth(t=0,2*Pi,[sin(5*t),sin(7*t)],
-  ***                                ^--------------------
-  ***   incorrect type in ploth [multi-curves cannot be plot recursively] (t_VEC).
-? ploth(t=0,2*Pi,[sin(5*t),sin(7*t)],3,100)
+? ploth(t=0,2*Pi,[sin(5*t),sin(7*t)],"Parametric|Recursive",100)
 [-1.000000000000000000, 1.000000000000000000, -1.000000000000000000, 1.00000
 0000000000000]
 ? plothraw(vector(501,k,k-1),vector(501,k,(k-1)*(k-1)/500));
@@ -71,13 +142,81 @@
 ? plotmove(0,200,200);plotstring(0,"(0,0)")
 ? plotdraw([0,10,10])
 ? psdraw([0,10,10])
-? ploth(x=0,2*Pi,if(x<1,[cos(x),sin(x)],1),1)
+? ploth(x=0,1,x^3,"Splines")
+[0.E-307, 1.000000000000000000, 0.E-307, 1.000000000000000000]
+? ploth(x=0,1,[x^2,x^3],"Parametric|Splines")
+[0.E-307, 0.9999999999999998890, 0.E-307, 0.9999999999999998890]
+? plotinit(1);
+? plotcopy(0,1,300,0);
+? plotclip(1);
+? plotdraw([1,10,10]);
+? plotkill(1);
+? plotinit(1);
+? plotcopy(0,1,1/2,0,1);
+? plotclip(1);
+? plotdraw([1,10,10]);
+? plotkill(1);
+? plotinit(1);
+? plotcopy(0,1,1/2,1/3,3);
+? plotclip(1);
+? plotdraw([1,10,10]);
+? plotkill(1);
+? plotinit(1);
+? plotcopy(0,1,1/3,1/3,5);
+? plotclip(1);
+? plotdraw([1,10,10]);
+? plotkill(1);
+? plotinit(1);
+? plotcopy(0,1,1/3,1/3,7);
+? plotclip(1);
+? plotdraw([1,10,10]);
+? plotinit(-1)
+  ***   at top-level: plotinit(-1)
+  ***                 ^------------
+  *** plotinit: domain error in graphic function: rectwindow < 0
+? plotinit(100)
+  ***   at top-level: plotinit(100)
+  ***                 ^-------------
+  *** plotinit: domain error in graphic function: rectwindow > 15
+? plotmove(-1,0,0)
+  ***   at top-level: plotmove(-1,0,0)
+  ***                 ^----------------
+  *** plotmove: domain error in graphic function: rectwindow < 0
+? plotmove(100,0,0)
+  ***   at top-level: plotmove(100,0,0)
+  ***                 ^-----------------
+  *** plotmove: domain error in graphic function: rectwindow > 17
+? plotcopy(0,1,2,1,1)
+  ***   at top-level: plotcopy(0,1,2,1,1)
+  ***                 ^-------------------
+  *** plotcopy: domain error in plotcopy: dx > 1
+? plotcopy(0,1,-1,1,1)
+  ***   at top-level: plotcopy(0,1,-1,1,1)
+  ***                 ^--------------------
+  *** plotcopy: domain error in plotcopy: dx < 0
+? plotcopy(0,1,1,2,1)
+  ***   at top-level: plotcopy(0,1,1,2,1)
+  ***                 ^-------------------
+  *** plotcopy: domain error in plotcopy: dy > 1
+? plotcopy(0,1,1,-1,1)
+  ***   at top-level: plotcopy(0,1,1,-1,1)
+  ***                 ^--------------------
+  *** plotcopy: domain error in plotcopy: dy < 0
+? ploth(x=0,2*Pi,if(x<1,[cos(x),sin(x)],1),"Parametric")
   ***   at top-level: ploth(x=0,2*Pi,if(x<1,[cos(x),sin(x)],
   ***                                   ^--------------------
   ***   inconsistent dimensions in rectploth.
+? ploth(t=0,2*Pi,[sin(5*t),sin(7*t)],"Recursive",100)
+  ***   at top-level: ploth(t=0,2*Pi,[sin(5*t),sin(7*t)],
+  ***                                ^--------------------
+  ***   incorrect type in ploth [multi-curves cannot be plot recursively] (t_VEC).
+? ploth(x=0,2*Pi,1,"Parametric")
+  ***   at top-level: ploth(x=0,2*Pi,1,"Parametric")
+  ***                                ^---------------
+  ***   incorrect type in ploth [not a t_VEC with PLOT_PARAMETRIC] (t_INT).
 ? ploth(x=0,1,x,,1)
   ***   at top-level: ploth(x=0,1,x,,1)
   ***                 ^-----------------
   *** ploth: domain error in ploth: #points < 2
 ? print("Total time spent: ",gettime);
-Total time spent: 36
+Total time spent: 96
diff --git a/src/test/32/pol b/src/test/32/pol
index a88dd4f..f9a2bdf 100644
--- a/src/test/32/pol
+++ b/src/test/32/pol
@@ -1,5 +1,5 @@
 Mod(0, 3) Mod(0, 3) Mod(0, 3)
-Mod(0, 3) + O(y^16) Mod(0, 3) + O(x^16) Mod(0, 3) + O(x^5)
+Mod(0, 3)*y^15 + O(y^16) Mod(0, 3)*x^15 + O(x^16) Mod(0, 3)*x^4 + O(x^5)
 y x x
 y + O(y^17) y + O(x^16) y + O(x^5)
 0 0 0
@@ -18,8 +18,10 @@ y^2 + 2*y - 4 x^2 + 2*x - 4 -4*x^2 + 2*x + 1
 y + 2*y^2 + O(y^4) (y + 2*y^2 + O(y^4)) + O(x^16) (y + 2*y^2 + O(y^4)) + O(x
 ^5)
 2 2 3
-y + 2 y + 2 (y + 2) + x + O(x^2)
+y + 2 y + 2 x + 2
 1 1 x + 2
+z
+y
 x^2 + x + 1
 -x^3 - 2*x^2 - x + 1
 [4, 0, 0, 0, -2]~
@@ -33,4 +35,7 @@ x^2 + 1
   ***   at top-level: Pol("")
   ***                 ^-------
   *** Pol: incorrect type in gtopoly (t_STR).
+2*x^2 + x + 1
+6*x^3 + 2*x^2
+"t_INT"
 Total time spent: 0
diff --git a/src/test/32/agm b/src/test/32/polclass
similarity index 100%
copy from src/test/32/agm
copy to src/test/32/polclass
diff --git a/src/test/32/polmod b/src/test/32/polmod
index 1994600..b3ea98b 100644
--- a/src/test/32/polmod
+++ b/src/test/32/polmod
@@ -44,7 +44,7 @@ Mod(Mod(4611686018427387936, 18446744073709551629)*x^2 + Mod(461168601842738
 Mod(Mod(1, 18446744073709551629), Mod(2, 18446744073709551629)*x^3 + Mod(1, 
 18446744073709551629)*x + Mod(1, 18446744073709551629))
 Mod(1/4, t)*x^2 + Mod(1, t)*x + Mod(1, t)
-0
+Mod(0, 1)
 Mod(y, x)
 Mod(1/y, x)
 Mod(O(y), x)
@@ -54,7 +54,7 @@ Mod(1, y)
   ***   at top-level: Mod(1+O(y),y+1)
   ***                 ^---------------
   *** Mod: forbidden division t_SER % t_POL.
-0
+Mod(0, 1)
 Mod(-1, x - 1)
 36893488147419103232
 a
diff --git a/src/test/32/agm b/src/test/32/polmodular
similarity index 100%
copy from src/test/32/agm
copy to src/test/32/polmodular
diff --git a/src/test/32/polred b/src/test/32/polred
index 83877e0..14f6af7 100644
--- a/src/test/32/polred
+++ b/src/test/32/polred
@@ -30,9 +30,10 @@ d(-385*y - 251, y^2 - y - 7)*x^5 + Mod(695*y + 2955, y^2 - y - 7)*x^4 + Mod(
 x^3 + Mod(y^2 - 2, y^3 - y - 1)*x^2 + Mod(-y + 1, y^3 - y - 1)*x + Mod(y - 1
 , y^3 - y - 1)
 x^9 - 4*x^8 + 8*x^7 - 9*x^6 + 7*x^5 - 3*x^4 - x^3 + 4*x^2 - 3*x + 1
-0
-0
-0
+Mod(0, x^3 + Mod(y^2 - y - 2, y^3 - y - 1)*x^2 + Mod(-y^2 + y + 1, y^3 - y -
+ 1)*x + Mod(y^2, y^3 - y - 1))
+Mod(0, x^9 - 4*x^8 + 8*x^7 - 9*x^6 + 7*x^5 - 3*x^4 - x^3 + 4*x^2 - 3*x + 1)
+Mod(0, x^9 - 4*x^8 + 8*x^7 - 9*x^6 + 7*x^5 - 3*x^4 - x^3 + 4*x^2 - 3*x + 1)
   *** nfinit: Warning: non-monic polynomial. Result of the form [nf,c].
 x^2 - 3646554366
 304
@@ -67,4 +68,5 @@ x^3 + 160*x^2 - 89*x + 26)]
 x^16 - 4*x^15 - 334*x^14 + 264*x^13 + 32231*x^12 + 57392*x^11 - 1031422*x^10
  - 3628868*x^9 + 7185297*x^8 + 42417784*x^7 + 11283472*x^6 - 137773504*x^5 -
  127243504*x^4 + 69059728*x^3 + 56307944*x^2 - 6264432*x + 6436
-Total time spent: 2596
+  ***   Warning: new stack size = 25165824 (24.000 Mbytes).
+Total time spent: 5340
diff --git a/src/test/32/polylog b/src/test/32/polylog
index ab865ea..cba4bfc 100644
--- a/src/test/32/polylog
+++ b/src/test/32/polylog
@@ -3,9 +3,9 @@
 63565*I
 4.3226178452644705784020044544722613393 - 2.90951877177225946407469488966471
 03179*I
-[-0.20561675835602830455905189583075314865 - 0.91596559417721901505460351493
-238411077*I, -0.20561675835602830455905189583075314865 + 0.91596559417721901
-505460351493238411077*I]~
+[-0.20561675835602830455905189583075314866 - 0.91596559417721901505460351493
+238411074*I, -0.20561675835602830455905189583075314866 + 0.91596559417721901
+505460351493238411074*I]~
 [0.58224052646501250590265632015968010874, 0.7275863077163333895135362968404
 8110789]
 x + 1/4*x^2 + 1/9*x^3 + 1/16*x^4 + O(x^5)
diff --git a/src/test/32/polyser b/src/test/32/polyser
index 93fef60..d25e58a 100644
--- a/src/test/32/polyser
+++ b/src/test/32/polyser
@@ -24,13 +24,6 @@ xx
 [(1 + O(7^8))*y^2 + (1 + 6*7 + 4*7^2 + 4*7^3 + 3*7^4 + 4*7^5 + 6*7^7 + O(7^8
 ))*y + (6 + 5*7 + 3*7^2 + 6*7^3 + 7^4 + 3*7^5 + 2*7^6 + 5*7^7 + O(7^8)) 1]
 
-? factorpadic(apol,7,8,1)
-
-[(1 + O(7^8))*y + (6 + 2*7^2 + 2*7^3 + 3*7^4 + 2*7^5 + 6*7^6 + O(7^8)) 1]
-
-[(1 + O(7^8))*y^2 + (1 + 6*7 + 4*7^2 + 4*7^3 + 3*7^4 + 4*7^5 + 6*7^7 + O(7^8
-))*y + (6 + 5*7 + 3*7^2 + 6*7^3 + 7^4 + 3*7^5 + 2*7^6 + 5*7^7 + O(7^8)) 1]
-
 ? intformal(sin(x))
 1/2*x^2 - 1/24*x^4 + 1/720*x^6 - 1/40320*x^8 + 1/3628800*x^10 - 1/479001600*
 x^12 + 1/87178291200*x^14 - 1/20922789888000*x^16 + O(x^18)
@@ -157,4 +150,4 @@ x + x^2 - 1/6*x^3 - 1/2*x^4 - 59/120*x^5 - 1/8*x^6 + 419/5040*x^7 + 59/720*x
 name
 ? if(getheap()!=HEAP,getheap())
 ? print("Total time spent: ",gettime);
-Total time spent: 4
+Total time spent: 0
diff --git a/src/test/32/pow b/src/test/32/pow
index 58e84bd..740b135 100644
--- a/src/test/32/pow
+++ b/src/test/32/pow
@@ -52,4 +52,10 @@ Mod(2, 3)
   ***   at top-level: sqrt(Mod(2,4))
   ***                 ^--------------
   *** sqrt: not a prime number in Fl_sqrt [modulus]: 4.
-Total time spent: 0
+[Mod(1, 11), Mod(2, 11), Mod(4, 11), Mod(8, 11), Mod(5, 11), Mod(10, 11), Mo
+d(9, 11), Mod(7, 11), Mod(3, 11), Mod(6, 11), Mod(1, 11)]
+[1, 3.1415926535897932384626433832795028842, 9.86960440108935861883449099987
+61511353, 31.006276680299820175476315067101395202, 97.4090910340024372364403
+32688705111250, 306.01968478528145326274131004343560648, 961.389193575304437
+03021944365241989886, 3020.2932277767920675142064930720418319]
+Total time spent: 4
diff --git a/src/test/32/prec b/src/test/32/prec
index d56316a..7e81d60 100644
--- a/src/test/32/prec
+++ b/src/test/32/prec
@@ -7,6 +7,7 @@ x + (1 + O(3^3))
 Mod(1 + O(3^3), (1 + O(3^3))*x)
 [1 + O(3^3), 2]
 77
+57
 38
 1
 1
@@ -19,4 +20,4 @@ Mod(1 + O(3^3), (1 + O(3^3))*x)
 3
 3
 4
-Total time spent: 8
+Total time spent: 0
diff --git a/src/test/32/primes b/src/test/32/primes
index aae7da2..5e296f3 100644
--- a/src/test/32/primes
+++ b/src/test/32/primes
@@ -1,12 +1,17 @@
 [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
  73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 
 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229]
+[2, 3, 5]
 [11, 13, 17, 19]
 [4294967197, 4294967231, 4294967279, 4294967291, 4294967311, 4294967357, 429
 4967371, 4294967377, 4294967387, 4294967389]
 [18446744073709551521, 18446744073709551533, 18446744073709551557, 184467440
 73709551629, 18446744073709551653, 18446744073709551667, 1844674407370955169
 7, 18446744073709551709]
+5758
 61938
 2
-Total time spent: 476
+  ***   at top-level: primes([1,Pol(2)])
+  ***                 ^------------------
+  *** primes: incorrect type in primes_interval (t_POL).
+Total time spent: 488
diff --git a/src/test/32/printf b/src/test/32/printf
index 185d080..c045293 100644
--- a/src/test/32/printf
+++ b/src/test/32/printf
@@ -184,4 +184,7 @@ a
 [1.00]
 
 [2.00]
-Total time spent: 4
+  ***   at top-level: printf("%c",'x)
+  ***                 ^---------------
+  *** printf: incorrect type in gtolong (t_POL).
+Total time spent: 0
diff --git a/src/test/32/program b/src/test/32/program
index 2ffd900..aa946af 100644
--- a/src/test/32/program
+++ b/src/test/32/program
@@ -76,10 +76,10 @@ x + y equals x + y
 ? print1("give a value for s? ");s=input();print(1/(s^2+1))
 give a value for s? printtex((x+y)^3/(x-y)^2)
 \frac{x^3
- + 3 y x^2
- + 3 y^2 x
+ + 3\*y\*x^2
+ + 3\*y^2\*x
  + y^3}{x^2
- - 2 y x
+ - 2\*y\*x
  + y^2}
 1
 ? for(i=1,100,for(j=1,25,if(i+j==32,break(2)));print(i))
@@ -104,4 +104,4 @@ give a value for s? printtex((x+y)^3/(x-y)^2)
 ? kill(addii)
 ? if(getheap()!=HEAP,getheap())
 ? print("Total time spent: ",gettime);
-Total time spent: 20
+Total time spent: 8
diff --git a/src/test/32/qfb b/src/test/32/qfb
index f16b1c9..0d8775d 100644
--- a/src/test/32/qfb
+++ b/src/test/32/qfb
@@ -11,6 +11,15 @@ Qfb(1, 1, 6)
 Qfb(1009, 60, 99108027750247771)
 Qfb(1, 0, 100000000000000000039)
 Qfb(1, 1, 6)
+[Qfb(1, 1, 6), [22479, 76177; -39508, -133885]]
+[Qfb(4, 3, -3, 0.E-38), [127327, -416128; -148995, 486943]]
+[Qfb(4, 3, -3, 0.E-38), [127327, -416128; -148995, 486943]]
+  ***   at top-level: qfbredsl2(q,[D])
+  ***                 ^----------------
+  *** qfbredsl2: incorrect type in qfbredsl2 (t_VEC).
+  ***   at top-level: qfbredsl2(q,[D,1.])
+  ***                 ^-------------------
+  *** qfbredsl2: incorrect type in qfbredsl2 (t_VEC).
 Qfb(18446744073709551629, 4741036151112220792, 304625896260305173)
 Qfb(18446744073709551629, 7562574061564804959, 775103267656920011, 0.E-38)
-Total time spent: 0
+Total time spent: 4
diff --git a/src/test/32/qfbclassno b/src/test/32/qfbclassno
new file mode 100644
index 0000000..a0effb2
--- /dev/null
+++ b/src/test/32/qfbclassno
@@ -0,0 +1,16 @@
+10125
+11045
+4802
+1660
+2136
+2144
+1508
+2728
+15376
+7688
+15376
+76800
+7688
+8112
+32448
+Total time spent: 8
diff --git a/src/test/32/qfsolve b/src/test/32/qfsolve
new file mode 100644
index 0000000..f4faab2
--- /dev/null
+++ b/src/test/32/qfsolve
@@ -0,0 +1,142 @@
+dim=3
+[2, 42762409]
+[3, 3617]
+[4, 5]
+[5, 43]
+[6, 31]
+[9, 5]
+[11, 7]
+[12, 3]
+[13, 17]
+[14, 19]
+[15, 73]
+[16, 79]
+[17, 38287]
+[18, 3774601]
+[19, 7]
+[20, 3]
+[21, 61]
+[22, 3]
+[23, 229]
+[24, 7]
+[25, 3]
+[27, 68196433]
+[28, 2393]
+[29, 13]
+[30, 145963897]
+[31, 71]
+[33, 433]
+[34, 3]
+[35, 409]
+[36, 3]
+[37, -1]
+[38, 11483]
+[41, 11]
+[44, -1]
+[45, 281]
+[46, 4363]
+[47, -1]
+[48, 7]
+[49, 41]
+[52, 5965507]
+[53, 13]
+[56, 135319]
+[57, 2473301]
+[58, 141613]
+[59, -1]
+[60, 109]
+[61, 3]
+[62, -1]
+[65, 5]
+[66, 13]
+[67, 11]
+[68, 271]
+[69, 7]
+[70, 642419]
+[73, 29]
+[74, 1951]
+[76, 3]
+[77, -1]
+[78, 107]
+[79, -1]
+[80, 48199741]
+[81, 89]
+[82, 11]
+[83, 157]
+[84, 197]
+[85, 5]
+[86, -1]
+[87, -1]
+[88, 11]
+[89, 29]
+[90, 7]
+[91, -1]
+[92, 3]
+[93, 17]
+[94, 7]
+[95, 3]
+[98, 31]
+[99, 19]
+dim=4
+[20, 2]
+[71, 2]
+[81, 2]
+[96, 2]
+[100, 2]
+dim=5
+dim=6
+dim=7
+dim=8
+
+[-3 -10  3]
+
+[ 5  -6 -5]
+
+[-1   0 -1]
+
+
+[-3   2 11]
+
+[ 5 -26 27]
+
+[-1   4 -5]
+
+
+[-3 -16 -10]
+
+[ 5   4  -6]
+
+[-1  -2  -2]
+
+[1]~
+-1
+-2
+[1, 0]~
+[-42, 35]~
+
+[-1 0 1]
+
+[ 0 2 0]
+
+[ 1 0 1]
+
+[0, 5, -1]~
+3
+
+[-12  0 -1]
+
+[  0 24  0]
+
+[  0  0 24]
+
+
+[310 -62  3]
+
+[-62  16 -1]
+
+[-18   2  0]
+
+  ***   at top-level: qfsolve([1,0,0;0,1,1
+  ***                 ^--------------------
+  *** qfsolve: incorrect type in qfsolve [not symmetric] (t_MAT).
+Total time spent: 2220
diff --git a/src/test/32/quadray b/src/test/32/quadray
index 5865708..2c48533 100644
--- a/src/test/32/quadray
+++ b/src/test/32/quadray
@@ -1123,4 +1123,20 @@ x^11 + (-25462020*y + 12961894)*x^10 + (-5864817*y - 6566480)*x^9 + (1438139
  - 430)*x^2 + (-15*y + 36)*x - 1
 x^6 + (-2*y - 2)*x^5 + (2*y - 4)*x^4 + 14*x^3 + (-2*y - 2)*x^2 + (2*y - 4)*x
  + 1
+x^8 + 9*x^6 - 16*x^4 + 9*x^2 + 1
+x^20 + 6*x^19 + 24*x^18 + 46*x^17 + 57*x^16 + 51*x^15 + 37*x^14 + 21*x^13 + 
+12*x^12 + 3*x^11 - 11*x^10 - 3*x^9 + 15*x^8 + 14*x^7 + 9*x^6 + 15*x^5 + 15*x
+^4 + 6*x^3 + 3*x^2 + 3*x + 1
+x^20 + 12*x^18 + 6*x^16 - 5*x^14 - 9*x^12 + 17*x^10 - 9*x^8 + 6*x^4 - 3*x^2 
++ 1
+x^24 + 4*x^22 + 8*x^20 + 20*x^18 + 32*x^16 - 12*x^14 - 42*x^12 - 12*x^10 + 3
+2*x^8 + 20*x^6 + 8*x^4 + 4*x^2 + 1
+x^21 - 7*x^20 + (3*y + 16)*x^19 + (-22*y - 3)*x^18 + (64*y - 46)*x^17 + (-80
+*y + 89)*x^16 + (14*y - 133)*x^15 + (57*y + 244)*x^14 + (-56*y - 259)*x^13 +
+ (132*y - 3)*x^12 + (-317*y + 204)*x^11 + (317*y - 113)*x^10 + (-132*y + 129
+)*x^9 + (56*y - 315)*x^8 + (-57*y + 301)*x^7 + (-14*y - 119)*x^6 + (80*y + 9
+)*x^5 + (-64*y + 18)*x^4 + (22*y - 25)*x^3 + (-3*y + 19)*x^2 - 7*x + 1
+x^4 - y*x^3 - 3*x^2 + y*x + 1
+x^4 + (-1/4*y + 1/2)*x^3 - 2*x^2 + (1/4*y + 1/2)*x + 1
+x^2 - x + 1
 Total time spent: 436
diff --git a/src/test/32/random b/src/test/32/random
index 165c528..27b24b0 100644
--- a/src/test/32/random
+++ b/src/test/32/random
@@ -1,17 +1,17 @@
-Mod(0, 3)
-0
-[[a^2 + 1, a + 1], 1]
-1387580271*a^2 + 3706911745*a + 1312695376
-[[573349991*a^2 + 2420031944*a + 1343519483, 2386085604*a^2 + 2392264859*a +
- 1794760354], 1]
-15580190479849132290*a^2 + 18389358899415525065*a + 4921253721701162537
-[[13347186698121344203*a^2 + 15544125443573997803*a + 6210385477505767251, 3
-879726255188522250*a^2 + 4837042904171823814*a + 4650867119660314244], 1]
-0.2189535881123797030145835478
-Mod(4, 7)*x^4 + Mod(4, 7)*x^3 + Mod(2, 7)*x^2 + Mod(6, 7)*x
+Mod(2, 3)
+a^2
+[[a, a + 1], 1]
+3223690774*a^2 + 2495927739*a + 1543932468
+[[222673296*a^2 + 832141822*a + 1993872865, 3473855231*a^2 + 2165401445*a + 
+1363496513], 1]
+4063307077606482163*a^2 + 2169871353760194456*a + 10598342506117936052
+[[2557945391375694509*a^2 + 5182580949942002905*a + 4115304207846177355, 808
+4599253441901006*a^2 + 17319169765369271807*a + 5394713598728073384], 1]
+0.56071855301363810851584520787407920871
+Mod(5, 7)*x^3 + Mod(2, 7)*x^2 + Mod(1, 7)*x + Mod(6, 7)
   ***   at top-level: randomprime(2)
   ***                 ^--------------
-  *** randomprime: domain error in randomprime: N < 2
+  *** randomprime: domain error in randomprime: N <= 2
   ***   at top-level: randomprime([0,1])
   ***                 ^------------------
   *** randomprime: domain error in randomprime: floor(b) - max(ceil(a),2) < 0
@@ -21,9 +21,9 @@ Mod(4, 7)*x^4 + Mod(4, 7)*x^3 + Mod(2, 7)*x^2 + Mod(6, 7)*x
   ***   at top-level: randomprime([2.4,2.5
   ***                 ^--------------------
   *** randomprime: domain error in randomprime: floor(b) - max(ceil(a),2) < 0
-2124902699
+1051006573
 5
-1267650600228229401496704197543
+1267650600228229401496703924683
   ***   at top-level: random("")
   ***                 ^----------
   *** random: incorrect type in genrand (t_STR).
diff --git a/src/test/32/real b/src/test/32/real
index cc962db..ff50baf 100644
--- a/src/test/32/real
+++ b/src/test/32/real
@@ -1,7 +1,30 @@
-  ***   at top-level: 1.<<2^60
+5.9 E347063955532709820
+1.7 E-347063955532709821
+  ***   at top-level: 1.<<2^64
   ***                     ^----
   ***   overflow in t_INT-->long assignment.
-  ***   at top-level: 1.>>2^60
+  ***   at top-level: 1.>>2^64
   ***                     ^----
   ***   overflow in t_INT-->long assignment.
+0.E1
+1
+1
+0
+0
+1
+1
+0
+0
+1
+1
+0
+0
+1
+1
+1
+1
+0
+0
+0
+0
 Total time spent: 0
diff --git a/src/test/32/resultant b/src/test/32/resultant
index 0b08883..fe5efb6 100644
--- a/src/test/32/resultant
+++ b/src/test/32/resultant
@@ -410,4 +410,7 @@ Mod(0, 3)
 Mod(1, 3)
 Mod(0, 2)
 [-x + 1, 1, 1]
-Total time spent: 6844
+x^4 + 2*y*x^2 + y^2
+x^20 - 10*x^16 + 20*x^15 + 40*x^12 + 2600*x^11 + 150*x^10 - 80*x^8 + 12400*x
+^7 - 17000*x^6 + 500*x^5 + 80*x^4 + 5600*x^3 + 11000*x^2 + 5000*x + 593
+Total time spent: 6972
diff --git a/src/test/32/rnf b/src/test/32/rnf
index e6f59b2..85a89a6 100644
--- a/src/test/32/rnf
+++ b/src/test/32/rnf
@@ -55,6 +55,53 @@
 [1, 2]
 Mod(x^5 + x^2 + 2, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1)
 Mod(z^2, z^3 + z^2 - 2*z - 1)
+[[1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 1, 1]]
+
+[[-9843, 391, -3472]~ [5826, -17043, -23934]~ [-183013449, -53300400, -56068
+6734]~ [-4831228968, -2610454140, -9159229488]~]
+
+[[3393, 2719, 1883]~ [3799, -2741, -7311]~ [44971153, -74830626, -108534066]
+~ [2330522034, 204707177, -1049209305]~]
+
+[[3690, -3485, 1185]~ [-7214, 11969, 18952]~ [135688819, 52627092, 452330447
+]~ [1633778037, 574919842, 6646910401]~]
+
+[[4169, 4338, 229]~ [722, 8865, 13444]~ [-106537503, 134281548, 137000286]~ 
+[1060748979, 4131422295, 3026338070]~]
+
+
+[0 1 0 0]
+
+[0 0 1 0]
+
+[0 0 0 1]
+
+[[6017899359, 5241880500, 2055449334; 0, 87, 12; 0, 0, 3], [1, 0, 0; 0, 1, 0
+; 0, 0, 1], [1, 0, 0; 0, 1, 0; 0, 0, 1]]
+
+[1 [-8073, 4800, -5591]~ [-315011, 112392, -182676]~]
+
+[0                     1          [-87, -173, -155]~]
+
+[0                     0                           1]
+
+
+[[165073371/2005966453, -120336277/2005966453, -220005359/2005966453]~ [436,
+ -266, 285]~ 0]
+
+[[-36888191/2005966453, 61195737/2005966453, 56154718/2005966453]~ [-321, 17
+8, -216]~ [-4, -4, -5]~]
+
+[[-137636147/2005966453, 99618172/2005966453, 248701141/2005966453]~ [-20, 3
+7, 3]~ [7, 1, -3]~]
+
+
+[1 0 0]
+
+[0 1 0]
+
+[0 0 1]
+
 [[1, -1/2; 0, 1], [1, 1]]
 [Mod(1/6*y + 2/3, y^2 - 40), -3]
 [Mod(1/2*y + 4, y^2 - 40), 1]
diff --git a/src/test/32/rnfkummer b/src/test/32/rnfkummer
index 06ce962..afd6bb0 100644
--- a/src/test/32/rnfkummer
+++ b/src/test/32/rnfkummer
@@ -1,174 +1,135 @@
   ***   Warning: new stack size = 20000000 (19.073 Mbytes).
 1
-x^3 + (774806212396682040403800911285727580902360710356054423617*y^3 + 97150
-6686017039131003298525517527246921922994336799568156*y^2 + 11821565693684429
-03321920531164159182095127947357116914844*y - 108151434729309365356471406894
-6874997341102881639770950564)*x + (-1101081691006188641718571980971003086516
-33373991261854661897473896921309979584250845786*y^3 - 1380613897447424014891
-54687510692802021389570171865180798324014776069968837855846155006*y^2 - 1679
-9696925608361694809806777136478453179953197918860855068694876240580160263314
-5257038*y + 1536946435524002857971775575314758204502648805624233135296867674
-44129838100365080190135)
+x^3 + (-309809053782*y^3 - 3888997223751*y^2 - 6797301518349*y - 84052574654
+07)*x + (2110598365387467792592554352717526002539781865920923249*y^3 + 21641
+216011110540424109369276995877123124719593450117617*y^2 - 112415300673959930
+84134917692441162658808857634880256897*y - 756749747169262373129861936919845
+290814942520335331064)
 2
-x^3 + (19710886507130683637499481853346220*y^3 - 276380637484283870500207144
-441368652*y^2 + 321806883259334223558938029085301164*y - 2893764851921508720
-91555008989630209)*x + (6234404200069914092635781978921534907087800821965005
-*y^3 - 87417103564909472118499724747251035776212296637996160*y^2 + 101785081
-248253577808797714025930280347744436431138133*y - 91527591822456102976671051
-455070193926146359966708289)
+x^3 + (-1547417164685*y^3 + 31806432693392*y^2 - 139471604300434*y - 1773556
+14250444)*x + (17339620993155536027731830465024620*y^3 - 2221469729970792828
+36844633756882355*y^2 - 23768491929510661288125574428753608*y + 226113886010
+159043440455818352510576)
 3
-x^5 + (-9882428445923387818821706968670335401786927402638328900/229919*y^3 +
- 252296777028239459931789167380697746461097731168075549950/229919*y^2 + 1764
-4021855250586329539712931017927391863593427164909150900/229919*y - 461692355
-191971518777222710539906813016286270054704580073485/229919)*x^3 + (520648303
-4334319898424292755071689636089386050580211646308033020493437324042023205648
-285918215543231297402900/229919*y^3 - 13510172122026074216086588070702609589
-3274800593243490875856383565886434411548352697079275501817626818578211700/22
-9919*y^2 - 91473485080232913616389746227405125029881179747504594125555560364
-17693246367183353048197363570304603875632855400/229919*y + 24083884821528790
-5870876643297480712506722062627721245971248179841780526788214041708631271723
-314318325272663341055/229919)*x + (78137203667601283191063741412847022062641
-2553304434052564901727553710334163982444928868366386245031074040191710705188
-597170075308725360/229919*y^3 - 20291832477897260584400088627142955032228712
-6427904642210421816300635730915867663743323382945939621991147280148116769004
-38451037873749030/229919*y^2 - 137170262514990797441175521438442862270311264
-3393460621755229264686711842372711647632765203362009673941201960909433758980
-882672771455560640/229919*y + 3612647630201497335124541722355310659164687014
-5370282645038587200821787637136651857253746125088350772872898101762266295117
-812934962971329040/229919)
+x^5 + (31053694430691806959028153535526508575394491595530880075/229919*y^3 -
+ 1337172444910675702714834520768516136648811147052111368700/229919*y^2 - 184
+35607679719630233800003735429609306259420537202849365675/229919*y + 85168752
+1879977644810463044558307395052118113383799019741260/229919)*x^3 + (-8226341
+6915869106989395958531761781594352114542089475985382056823633565937770898673
+231009566363506250615631175/229919*y^3 + 35385478381530645798170469394211236
+5168282550917362433457634864372667449652003732800972194102687257779244625180
+0/229919*y^2 + 4908982791938024433088442608773791198363680014945006762419677
+7607385389691428594721475982079142722308089422533825/229919*y - 226026940013
+1374832457412095356272722509330921975907891179036715440913257809856987870817
+500825759225344497438991545/229919)*x + (22551998352901963131641993046601513
+3946638262176063989037254138908992270637128842426264382844972281470462066091
+03759437051565982306045980/229919*y^3 - 970069103291587887819679165888035909
+1513452525059353022827758974127410768456473896085059479072681870140524313325
+16795716517046923205689040/229919*y^2 - 134577716464015013979539429011927274
+5559600788924748443465167004437508786600266658176529346878744443590275167546
+0471237318952656599936814270/229919*y + 619640324884053589505905068854009288
+3970336868820186315305602482095747219334932025573793524177539052848269546757
+02205305460016853411791162970/229919)
 4
-x^5 + 110*x^3 + 385*x^2 + (-6875*y + 13310)*x + (-20625*y - 32197)
+x^5 + 110*x^3 - 385*x^2 + (-6875*y + 13310)*x + (20625*y + 32197)
 5
-x^5 + (-59095446785579003366541009942375474915703002626492806189050492652833
-6777227549063361763754954860856971852727711644600186470988132579883875090572
-9803079525882763972042802336339760904754466580963063546728664273633835569948
-0*y - 1255629109524792530051324640019771107268873725738371437452373149898780
-8664516003920392766770766925545374769735534821188976309229469036602133358973
-7353191296177407075389420915446219197172794981974368679535268516967068453014
-30)*x^3 + (11644277774384555651776761259407289108977097641980228242435012611
-5006754047681181999487760953138546648235722021492042022118650990530538252856
-6414026821914198835648283336487147011301797121610470649794178541651897633010
-2619047628371992250175584734031123181309438679458163454790544342192453573731
-030635180622494122125396065225820240750*y + 24741151693056889254242449430265
-2468571687763455720080168193011803383803554198165726270992078221951492505067
-2523425192260651173461424746524891653990998558483368796194367290039509450211
-7223320966363646799929781716117510559483376953872459496427621808761687440880
-10277314407796992274304485160518076623273185053816747431170532802842069845)*
-x^2 + (320866938295880246233167260001000107563618762621372357179787452301597
-9350243325972757280812393253232955595814724357682764593258584468527774061354
-2242378888385866623543414807804481384620950782988555853437885938726285585062
-2324974444011130041770207214081732874802346406968000065586950875225394719188
-4623518822273224739400356095176344365863179853117653552348695220926538716085
-52583923034075591677276229656463785917547906153809856186338690340273770*y + 
-6817612691384532081704360643291649127584439227042117746627599451584982487957
-6572901637848129335693848481338746129646962173434343962797786879758126909137
-7381569437746730995649270075916763692439787747952720962070291143876149949483
-9614210516670824112990967457708754073489807333741020159222761044037864938737
-9246261520429224755935851613098789923520029380140527313267008357869036620577
-084037264149183512006735786452064658360584468340747599718504718410)*x + (479
-1488386897535189299378836180236085423634678222324224479062728075805982822437
-0614332128649486567242879024330122834178040516179680619153613540616585806037
-7183008624149304402927672945839064441661929200188706502079385514833093457024
-5806768755451682906974568908692395923842934118138666558754879374484134729144
-9868938565283781573780271601168423137627916189740121447280291767296950672317
-2653182572204989153504589598280507795775397905066604615953915755995460867052
-8060987075566530764495079483852000046629727066859504551785397092661954246711
-193183042460393012*y + 10180703630802729839362382111928571606603034484770558
-5306817525550772935039363481339905081141074846357682616458160033371105154149
-6119838532365651143544327472969299425232951428413020731520165630201894232969
-6028437849118197154430955186252049741741678410724900967414872905752188199744
-8965131243275080049232949513675900438219816309709252600957185206156348098304
-0110963425335258732186906609451092433156633139140137874710419209044386833785
-3831519981280988311756942110207862081145784700793692327274548446746868893274
-79033237457477153740386126551265094681046611167)
-6
-x^5 + 1497313810*x^3 - 153069990594216277067332440*x^2 - 9993317827227414657
-08504771613701347765415*x + 421302153697978557238622899127897637801303537233
+x^5 + 1497313810*x^3 + 153069990594216277067332440*x^2 - 9993317827227414657
+08504771613701347765415*x - 421302153697978557238622899127897637801303537233
 83633556328
+6
+x^3 + (72*y^5 - 180*y^4 + 306*y^3 - 156*y^2 + 156*y + 132)*x + (144*y^5 - 36
+0*y^4 + 610*y^3 - 312*y^2 + 318*y + 250)
 7
-x^3 + (6*y^3 - 12*y^2 + 12*y - 12)*x + (12*y^5 - 32*y^4 + 54*y^3 - 32*y^2 + 
-28*y + 20)
-8
 x^5 + (677308732982301944730030845266716201702837696162187325328/5*y^3 + 481
 271319660811460139352501916644558975058261230836596652/5*y^2 - 3487807973304
 8511269299413306183851642254427026365686673888/5*y - 24783137893632185532697
-291886880720222932490781434136563942/5)*x^3 + (31218254245856135648287296707
-04559492032765858876683224121119983801219547643890505070*y^3 + 2218259473949
-490736667831079912338956828105689590705243343986337391928943383709808005*y^2
- - 1607587048361124753491934721194326369713341397761485813643339582894344828
-06877560648970*y - 114229487928172801039731551289054638597376141715926648946
-031483976252167029243247022480)*x^2 + (-166692999053535356002572927874917139
-2118748717302099608304683989705975477021372381764147057643564706588636619348
-44/5*y^3 - 11844618891597190508741280303272659573039434424283175367673479155
-0346393669679117451359918013807557809143042588696/5*y^2 + 858387225015985285
-7479162156889677342550132950704205078118190632176525884150800135006242479797
-595396229858998666474/5*y + 609939805478110246004601234032243326487160080269
-1098946100231203424708988718659688581036467351459717869466864403491/5)*x + (
--376194285951669846001777157888755029972864354842521262364492544230511805129
-9870709569967640457662697840860989973276516003636843449764721490044/5*y^3 - 
+291886880720222932490781434136563942/5)*x^3 + (-3121825424585613564828729670
+704559492032765858876683224121119983801219547643890505070*y^3 - 221825947394
+9490736667831079912338956828105689590705243343986337391928943383709808005*y^
+2 + 160758704836112475349193472119432636971334139776148581364333958289434482
+806877560648970*y + 11422948792817280103973155128905463859737614171592664894
+6031483976252167029243247022480)*x^2 + (-16669299905353535600257292787491713
+9211874871730209960830468398970597547702137238176414705764356470658863661934
+844/5*y^3 - 1184461889159719050874128030327265957303943442428317536767347915
+50346393669679117451359918013807557809143042588696/5*y^2 + 85838722501598528
+5747916215688967734255013295070420507811819063217652588415080013500624247979
+7595396229858998666474/5*y + 60993980547811024600460123403224332648716008026
+91098946100231203424708988718659688581036467351459717869466864403491/5)*x + 
+(376194285951669846001777157888755029972864354842521262364492544230511805129
+9870709569967640457662697840860989973276516003636843449764721490044/5*y^3 + 
 2673104432455463952284352656647109245231103663592899118247897745294025980581
-570350460813923435311458682114748384710825808171997155877533243621/5*y^2 + 1
+570350460813923435311458682114748384710825808171997155877533243621/5*y^2 - 1
 9372161459591757660716692723884954611407620247350322071070721355639658608496
-4322202670927424345172110316287310450443586757567876756951302594424/5*y + 13
+4322202670927424345172110316287310450443586757567876756951302594424/5*y - 13
 7651773558650909762864388498297831958827163349141150095186154867116600261791
 580542516653158613689676015829782898702530873665348851222173825666/5)
+8
+x^3 + (-2138833799099964*y - 77766538091057475)*x + (-2899681696823107245657
+26*y - 10543044869724218021876124)
 9
-x^3 + (-2138833799099964*y - 77766538091057475)*x + (28996816968231072456572
-6*y + 10543044869724218021876124)
+[x^3 + (-2138833799099964*y - 77766538091057475)*x + (-271454449233503516412
+931*y - 9869898621944137446807843), x^3 + (-2138833799099964*y - 77766538091
+057475)*x + (18513720448807208152795*y + 673146247780080575068281), x^3 + (-
+2138833799099964*y - 77766538091057475)*x + (-289968169682310724565726*y - 1
+0543044869724218021876124), x^3 - 3*x - 1]
 10
-[x^3 + (-2138833799099964*y - 77766538091057475)*x + (1851372044880720815279
-5*y + 673146247780080575068281), x^3 + (-2138833799099964*y - 77766538091057
-475)*x + (289968169682310724565726*y + 10543044869724218021876124), x^3 + (-
-2138833799099964*y - 77766538091057475)*x + (-271454449233503516412931*y - 9
-869898621944137446807843), x^3 - 3*x - 1]
-11
 x^5 - 10*x^3 + 20*x + 10
-12
+11
 x^5 + (14433507922528796322450466885842559554649240/81*y^3 - 206924153900250
 190478940045819169994648120380/81*y^2 + 387221873734866129008668004845146809
-3411480/27*y + 9952907878012919545305461812329973812202320)*x^3 + (151213742
-1515820547988557267937916762553254164737251785897692300/27*y^3 + 18337121232
-6689306422734140437601099700562333545199409203074500/27*y^2 - 11743163565184
-2472537762690188912056014010181849092684109181910170/9*y + 27790231583332542
-847266778828385473838935385907433291290641467310)*x^2 + (-226693826937254370
-3014068118233450711618653187091810917531287989910268281950806313112830/81*y^
-3 + 239315207598088678889180580299531524598499432218877226931937677230073476
-51161135616414460/81*y^2 + 4557474129212450957128695360991332089101354211319
-1870218073887288396098516272850951573480/27*y - 4785071374094015662869316915
-362187463934517274549880463316992141982057530013804207289130)*x + (119270482
-8439928261324666320105890752409692593927875083779153072015384025578913692346
-3989511892271143598294/3*y^3 - 152961475704026365347150203105055935481447020
-419907822345352843160917118838486063790065390094212607259586902/3*y^2 - 9397
-8480302010002477264842168576217064771866107133401243553275407905590291763780
-391464292290112011298779372*y + 40510745442141622784634137179518469588738855
-3485545336064626090438935556037611475681610251702629961491235364)
+3411480/27*y + 9952907878012919545305461812329973812202320)*x^3 + (-15121374
+21515820547988557267937916762553254164737251785897692300/27*y^3 - 1833712123
+26689306422734140437601099700562333545199409203074500/27*y^2 + 1174316356518
+42472537762690188912056014010181849092684109181910170/9*y - 2779023158333254
+2847266778828385473838935385907433291290641467310)*x^2 + (-22669382693725437
+03014068118233450711618653187091810917531287989910268281950806313112830/81*y
+^3 + 23931520759808867888918058029953152459849943221887722693193767723007347
+651161135616414460/81*y^2 + 455747412921245095712869536099133208910135421131
+91870218073887288396098516272850951573480/27*y - 478507137409401566286931691
+5362187463934517274549880463316992141982057530013804207289130)*x + (-1192704
+8284399282613246663201058907524096925939278750837791530720153840255789136923
+463989511892271143598294/3*y^3 + 1529614757040263653471502031050559354814470
+20419907822345352843160917118838486063790065390094212607259586902/3*y^2 + 93
+9784803020100024772648421685762170647718661071334012435532754079055902917637
+80391464292290112011298779372*y - 405107454421416227846341371795184695887388
+553485545336064626090438935556037611475681610251702629961491235364)
+12
+x^5 + (-851144406868559279232996971324725873829107720800*y - 789318851387399
+1842317094186099932000353485209310)*x^3 + (-43598930311479787918633936768341
+9232691384674801616263923073114708639930*y - 4043198465203672254220234791146
+129167056215073195769930655328439910350350)*x^2 + (2194240445634978589987163
+697794653683158447798607957128524354188268092895134005397224513339544600*y +
+ 203485487802052726938585350262826646331621060750721288241946679402110145465
+99006386469739888533585)*x + (4487271766922150403279065006331295700947106495
+64789965265088646961341003482440973587627263428493400548308062454501128034*y
+ + 4161324645204494065844472460463583238903889997974154247351350815735235081
+291291583568531697548194392575994990027027850050)
 13
-x^5 + (332998327585787806210715462400*y - 3088099449668699468241894745310)*x
-^3 + (494543408306584524066234839600325678760597930*y - 45862068980974258959
-41238867752143070004508050)*x^2 + (26417254338273940545860942707750465903049
-7550267984532302200*y - 2449835384316313335292893982961063446219951623920034
-753322415)*x + (476291033688128034677862637907914049204992323838153758931557
-45202346081966*y - 441694133924899145700575613631246753719401915993262186949
-236663342183626850)
+x^2 + (579005994260871660725675138161827610313714425601379330908*y^5 - 10665
+838767241026781798972314566336490960682839047298886121*y^4 - 125451512411576
+00984519055919161910715239885311867631785451*y^3 - 1073834268336903398192739
+1139740391065234975927048788721099*y^2 - 14903158824521475429243429293262572
+511122641600774314257887*y - 14998783880299450494129067945527908842599620490
+145975145023)
 14
-x^2 + (-246740429132141146463522518444668570440348378975804*y^5 + 4703956945
-787111585543964420667028301009723801572487*y^4 + 266190357187628389772307989
-7863774384599266481260032*y^3 - 39177999595004651251370478833094268643601230
-78018159*y^2 + 10590083476362079496920522735326808810513545604444961*y - 584
-8192501453958323706561054990087672915722280908328)
+x^2 + (-1/4*y^5 - 9/4*y^4 - 1/2*y^3 - 3/4*y^2 - 3/4*y + 3/2)
 15
-x^2 + (-1/2*y^5 - 9/2*y^4 - y^3 - 3/2*y^2 - 3/2*y + 3)
+x^2 + (-53140587696485690121168112086566519*y^5 - 98157358121814711167092564
+297381805*y^4 - 1913471778408690519143587422326674*y^3 - 2075566936738425347
+3741951752946058*y^2 - 12577008858253013499052611584073889*y - 8328381136606
+8509872924242423547922)
 16
-x^2 + (7064114974621884209263957684*y^5 - 78597289737331354515763478580*y^4 
-+ 13905399960467092094726011945*y^3 - 27789415584376787513088098359*y^2 + 26
-854231387417039826858692319*y - 60884996981015832433185005956)
+x^2 + (8*y - 109)
 17
-x^2 + (-8*y - 101)
-18
 x^2 - 5
+18
+x^3 + (-29*y^3 + 156*y^2 + 403*y - 4767)*x + (430655/6*y^3 - 1953316/3*y^2 +
+ 10148915/6*y + 7987262/3)
 19
-x^3 + (-3*y^3 - 141/2*y^2 + 921*y - 6963/2)*x + (49621/3*y^3 - 547595/6*y^2 
-- 619772/3*y + 15840415/6)
-20
 [x^3 - 3*x - 1]
-Total time spent: 15853
+20
+x^3 - 3*x - 1
+[]
+21
+x^5 - 10*x^3 + 5*x^2 + 10*x + 1
+Total time spent: 8644
diff --git a/src/test/32/rootsreal b/src/test/32/rootsreal
new file mode 100644
index 0000000..558d2bd
--- /dev/null
+++ b/src/test/32/rootsreal
@@ -0,0 +1,64 @@
+[1.0000000000000000000000000000000000000, 2.00000000000000000000000000000000
+00000, 3.0000000000000000000000000000000000000]~
+[1.0000000000000000000000000000000000000]~
+[2.0000000000000000000000000000000000000, 3.00000000000000000000000000000000
+00000]~
+[1.0000000000000000000000000000000000000, 2.00000000000000000000000000000000
+00000, 3.0000000000000000000000000000000000000]~
+[2.0000000000000000000000000000000000000, 3.00000000000000000000000000000000
+00000]~
+[1.0000000000000000000000000000000000000, 2.00000000000000000000000000000000
+00000]~
+1
+2
+3
+2
+2
+3
+2
+2
+2
+[-22.176420046821213834911725420609849287, -1.220401103882337235735459354425
+6902868]~
+[-0.98480775301220805936674302458952301367, -0.86602540378443864676372317075
+293618347, -0.64278760968653932632264340990726343291, -0.3420201433256687330
+4409961468225958076, 0.E-38, 0.34202014332566873304409961468225958076, 0.642
+78760968653932632264340990726343291, 0.8660254037844386467637231707529361834
+7, 0.98480775301220805936674302458952301367]~
+[-0.98768834059513772619004024769343726076, -0.89100652418836786235970957141
+362631277, -0.70710678118654752440084436210484903928, -0.4539904997395467915
+6040836635787119898, -0.15643446504023086901010531946716689231, 0.1564344650
+4023086901010531946716689231, 0.45399049973954679156040836635787119898, 0.70
+710678118654752440084436210484903928, 0.891006524188367862359709571413626312
+77, 0.98768834059513772619004024769343726076]~
+[]~
+[]~
+  ***   at top-level: polrootsreal(0)
+  ***                 ^---------------
+  *** polrootsreal: zero polynomial in realroots.
+  ***   at top-level: polrootsreal(Pol(0))
+  ***                 ^--------------------
+  *** polrootsreal: zero polynomial in realroots.
+  ***   at top-level: polrootsreal(Mod(1,2
+  ***                 ^--------------------
+  *** polrootsreal: incorrect type in realroots (t_INTMOD).
+[0.E-38 + 0.E-38*I, 1.0000000000000000000000000000000000000 + 0.E-38*I, 2.00
+00000000000000000000000000000000000 + 0.E-38*I, 3.00000000000000000000000000
+00000000000 + 0.E-38*I]~
+[]~
+[1.0000000000000000000000000000000000000]~
+[]~
+1
+0
+3
+2
+3
+[1.2599210498948731647672106072782283506]~
+[-1.2599210498948731647672106072782283506]~
+2
+[0.E-38]~
+1
+  ***   at top-level: polsturm((x^4-2)^2)
+  ***                 ^-------------------
+  *** polsturm: domain error in polsturm: issquarefree(pol) = 0
+Total time spent: 0
diff --git a/src/test/32/round4 b/src/test/32/round4
index f9a8c11..4c53871 100644
--- a/src/test/32/round4
+++ b/src/test/32/round4
@@ -458,5 +458,4 @@
 [1, 1/23737807549715*x + 1/23737807549715], -84
 [1, 1/23737807549715*x + 1/23737807549715], -84
 [1, x], -47332614610453741984512822900
-[1, 1/23737807549715*x + 1/23737807549715], -84
-Total time spent: 5576
+Total time spent: 2560
diff --git a/src/test/32/select b/src/test/32/select
index 14c76a6..a4cacc4 100644
--- a/src/test/32/select
+++ b/src/test/32/select
@@ -12,4 +12,6 @@ List([2, 3, 5])
 
 [0]
 
-Total time spent: 8
+[]
+[1, 3]
+Total time spent: 0
diff --git a/src/test/32/self b/src/test/32/self
new file mode 100644
index 0000000..c6c5205
--- /dev/null
+++ b/src/test/32/self
@@ -0,0 +1,2 @@
+120
+Total time spent: 0
diff --git a/src/test/32/ser b/src/test/32/ser
index 187e157..e650956 100644
--- a/src/test/32/ser
+++ b/src/test/32/ser
@@ -1,26 +1,39 @@
 x + x^2 + O(x^5)
 x + x^2 - 1/3*x^3 - x^4 + O(x^5)
 O(x^5)
+[0.78539816339744830961566084581987572105 + O(x^16)]
 x + x^2 + 1/6*x^3 + 1/2*x^4 + O(x^5)
 O(x^5)
+[1.5707963267948966192313216916397514421 + O(x^8)]
 1.5707963267948966192313216916397514421 - x - x^2 - 1/6*x^3 - 1/2*x^4 + O(x^
 5)
 1.5707963267948966192313216916397514421 + O(x^5)
+[O(x^8)]
 1 + 1/2*x^2 + x^3 + 13/24*x^4 + O(x^5)
 1 + O(x^5)
+[1.5430806348152437784779056207570616826 + O(x^16)]
 x + x^2 + 1/6*x^3 + 1/2*x^4 + O(x^5)
 O(x^5)
+[1.1752011936438014568823818505956008152 + O(x^16)]
 x + x^2 - 1/3*x^3 - x^4 + O(x^5)
 O(x^5)
+[0.76159415595576488811945828260479359041 + O(x^16)]
 1.5707963267948966192313216916397514421*I - 1.000000000000000000000000000000
 0000000*I*x - 1.0000000000000000000000000000000000000*I*x^2 - 0.166666666666
 66666666666666666666666667*I*x^3 - 0.50000000000000000000000000000000000000*
 I*x^4 + O(x^5)
 1.5707963267948966192313216916397514421*I + O(x^5)
+[O(x^8)]
 x + x^2 - 1/6*x^3 - 1/2*x^4 + O(x^5)
 O(x^5)
+[0.88137358701954302523260932497979230903 + O(x^16)]
 x + x^2 + 1/3*x^3 + x^4 + O(x^5)
 O(x^5)
+  ***   at top-level: ...rint(f[i](O(x^5)));print(f[i]([Pol(1)]));)
+  ***                                             ^-----------------
+  ***   in function f: atanh
+  ***                  ^-----
+  *** atanh: impossible inverse in div_ser: O(x^16).
 O(x^-2)
 O(x^-2)
 2 + O(x^2)
@@ -35,4 +48,35 @@ y + x + O(x^2)
   ***   at top-level: Ser("")
   ***                 ^-------
   *** Ser: incorrect type in gtoser (t_STR).
+Mod(0, 7)*x^15 + O(x^16)
+Mod(1, 7)*x^2 + Mod(1, 7)*x^4 + O(x^5)
+Mod(0, 7)*x^15 + O(x^16)
+Mod(1, 7) + O(x^16)
+Mod(1, 7)*x + O(x^16)
+Mod(0, 7)*x^14 + O(x^15)
+Mod(0, 7)*x^14 + O(x^15)
+Mod(0, 7)*x^15 + O(x^16)
+Mod(0, 7)*x^15 + O(x^16)
+Mod(0, 7)*x^15 + O(x^16)
+Mod(0, 7)*x^15 + O(x^16)
+O(x^16)
+Mod(0, 7)*x^15 + O(x^16)
+O(x^16)
+  ***   at top-level: Ser(x,,-5)
+  ***                 ^----------
+  *** Ser: domain error in gtoser: precision < 0
+0
+Mod(0, 4)*x + O(x^2)
+(1 + O(y^2))*x^3
+(Mod(1, 3) + O(y^2))*x^3
+O(x)
+O(3) + O(x)
+O(3^2) + O(x)
+O(3^3) + O(x)
+1 + O(x)
+  *** _+_: Warning: normalizing a series with 0 leading term.
+x^-1 + O(x)
+[0, 1, 1]
+[0, 1, 1]
+[0, 1, 1]
 Total time spent: 0
diff --git a/src/test/32/size b/src/test/32/size
index a8b8368..7c2f107 100644
--- a/src/test/32/size
+++ b/src/test/32/size
@@ -1,3 +1,4 @@
+0
 1
 1
 1
@@ -10,4 +11,4 @@
   ***   at top-level: matsize(1)
   ***                 ^----------
   *** matsize: incorrect type in matsize (t_INT).
-Total time spent: 4
+Total time spent: 0
diff --git a/src/test/32/str b/src/test/32/str
index 487f2ca..05a63dd 100644
--- a/src/test/32/str
+++ b/src/test/32/str
@@ -1,8 +1,9 @@
 Vecsmall([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33])
 "hello world!"
 "\\pmatrix{\n \\frac{1}{2}\\cr\n }"
-"\\frac{x^3\n + 3 y x^2\n + 3 y^2 x\n + y^3}{x^2\n - 2 y x\n + y^2}"
+"\\frac{x^3\n + 3\\*y\\*x^2\n + 3\\*y^2\\*x\n + y^3}{x^2\n - 2\\*y\\*x\n + y
+^2}"
 "x"
 "1/2"
 "ab1"
-Total time spent: 4
+Total time spent: 0
diff --git a/src/test/32/subgroup b/src/test/32/subgroup
index ec02864..63e8db9 100644
--- a/src/test/32/subgroup
+++ b/src/test/32/subgroup
@@ -8,4 +8,31 @@
   ***                                       ^---------
   ***   incorrect type in forsubgroup [not a group] (t_VEC).
 []
-Total time spent: 4
+
+group: 1  1  1  1 
+  alpha_lambda(mu,p) = 1
+  countsub = 1
+  alpha_lambda(mu,p) = 15
+  subgroup: 1 
+  countsub = 15
+  alpha_lambda(mu,p) = 35
+  subgroup: 1  1 
+  countsub = 35
+  alpha_lambda(mu,p) = 15
+  subgroup: 1  1  1 
+  countsub = 15
+  alpha_lambda(mu,p) = 1
+  subgroup: 1  1  1  1 
+  countsub = 1
+nb subgroup = 67
+67
+  ***   at top-level: subgrouplist(1)
+  ***                 ^---------------
+  *** subgrouplist: incorrect type in subgrouplist (t_INT).
+  ***   at top-level: subgrouplist([2,2],[
+  ***                 ^--------------------
+  *** subgrouplist: sorry, exact type in subgrouplist is not yet implemented.
+  ***   at top-level: subgrouplist([2,2],-
+  ***                 ^--------------------
+  *** subgrouplist: domain error in subgroup: index bound <= 0
+Total time spent: 0
diff --git a/src/test/32/sumdiv b/src/test/32/sumdiv
index fda6d59..7326fa4 100644
--- a/src/test/32/sumdiv
+++ b/src/test/32/sumdiv
@@ -89,4 +89,7 @@ x^10 + 16*x^9 + 115*x^8 + 491*x^7 + 1387*x^6 + 2729*x^5 + 3822*x^4 + 3805*x^
 3 + 2616*x^2 + 1146*x + 252
 x^10 + 16*x^9 + 115*x^8 + 491*x^7 + 1387*x^6 + 2729*x^5 + 3822*x^4 + 3805*x^
 3 + 2616*x^2 + 1146*x + 252
+  ***   at top-level: divisors([1,2])
+  ***                 ^---------------
+  *** divisors: incorrect type in divisors (t_VEC).
 Total time spent: 0
diff --git a/src/test/32/sumiter b/src/test/32/sumiter
index 61c7b12..cd9b8ce 100644
--- a/src/test/32/sumiter
+++ b/src/test/32/sumiter
@@ -37,7 +37,7 @@
 ? suminf(n=1,2.^-n)
 0.99999999999999999999999999999999999999
 ? 6/Pi^2*sumpos(n=1,n^-2)
-1.0000000000000000000000000000000000000
+0.99999999999999999999999999999999999999
 ? if(getheap()!=HEAP,getheap())
 ? print("Total time spent: ",gettime);
-Total time spent: 8
+Total time spent: 16
diff --git a/src/test/32/thue b/src/test/32/thue
index df2737c..1430769 100644
--- a/src/test/32/thue
+++ b/src/test/32/thue
@@ -1,26 +1,52 @@
   ***   Warning: new stack size = 20000000 (19.073 Mbytes).
 []
 [[0, -1]]
-[[-4, 3], [4, 3], [-4, -3], [4, -3]]
+[[-4, -3], [-4, 3], [4, -3], [4, 3]]
 [[1, 1]]
-[[1, 0], [-1, 0], [0, 1], [1, 1], [-1, -1], [0, -1]]
-[[1868, 514], [-4, -2]]
+[[-1, -1], [-1, 0], [0, -1], [0, 1], [1, 0], [1, 1]]
+[[-4, -2], [1868, 514]]
 []
 [[5, 1]]
-[[1, 1]]
-[[1, 1]]
+[[-1, -1], [1, 1]]
+[[-1, -1], [1, 1]]
   ***   at top-level: thueinit(x^0)
   ***                 ^-------------
   *** thueinit: constant polynomial in thueinit.
-[[2, 2], [-2, -2], [4, 1], [-4, -1]]
+[[-4, -1], [-2, -2], [2, 2], [4, 1]]
 [[0, 3], [3, -276], [3, 0]]
 [[0, 3], [3, 0], [19, 2], [27, 3]]
-[[-1, 1], [1, 1], [-1, -1], [1, -1]]
-[]
+[[-1, -1], [-1, 1], [1, -1], [1, 1]]
 [[0, 0]]
 [[0, 0]]
-[[-1, -1], [1, -1], [-1, 1], [1, 1]]
+[[0, 0]]
+[[-1, -1], [-1, 1], [1, -1], [1, 1]]
 []
-[[0, 1], [1, -537825], [1, 1], [537824, 1], [1, 0]]
+[[0, 1], [1, -537825], [1, 0], [1, 1], [537824, 1]]
 [[44, -131]]
-Total time spent: 2188
+[[-17711, -28657], [2584, 4181], [4181, 6765], [10946, 17711]]
+[]
+[[0, -1], [0, 1]]
+[[0, 1]]
+[[-8, 6], [-2, -2], [-2, 0], [0, -2], [2, -2]]
+[[-2, -1], [-1, -2], [1, 2], [2, 1]]
+[]
+[]
+[[-12100, 5500], [-12100, 6600], [-11000, 1100], [-11000, 9900], [-9900, -11
+00], [-9900, 11000], [-6600, -5500], [-6600, 12100], [-5500, -6600], [-5500,
+ 12100], [-1100, -9900], [-1100, 11000], [1100, -11000], [1100, 9900], [5500
+, -12100], [5500, 6600], [6600, -12100], [6600, 5500], [9900, -11000], [9900
+, 1100], [11000, -9900], [11000, -1100], [12100, -6600], [12100, -5500]]
+44
+44
+2
+2
+24
+6
+[]
+[]
+[[0, 1]]
+[]
+[]
+[[739, -219]]
+[[739, -219]]
+Total time spent: 4010
diff --git a/src/test/32/trans2 b/src/test/32/trans2
index fdeab87..78f4f2d 100644
--- a/src/test/32/trans2
+++ b/src/test/32/trans2
@@ -36,7 +36,7 @@ error("incorrect type in exp (t_INTMOD).")
 error("incorrect type in log (t_INTMOD).")
 error("domain error in Qp_log: argument = 0")
 O(3^4)
-0.E-38 + 1.5707963267948966192313216916397514421*I
+1.5707963267948966192313216916397514421*I
 error("incorrect type in cos (t_INTMOD).")
 1 + O(3^5)
 1 + 3^2 + 2*3^4 + O(3^6)
@@ -87,4 +87,4 @@ O(x)
 2.2048475583142180027021126820970067173 - 1.02440088160844588172486045441088
 66770*I
 0.E-2003
-Total time spent: 12
+Total time spent: 4
diff --git a/src/test/32/valuation b/src/test/32/valuation
index 6cd177b..037324f 100644
--- a/src/test/32/valuation
+++ b/src/test/32/valuation
@@ -1,4 +1,4 @@
-oo oo oo oo 
++oo +oo +oo +oo 
 0 0 0 0 
 0 -1 0 0 
 ERROR ERROR 0 0 
@@ -19,9 +19,17 @@ ERROR 1 0 0
   ***   at top-level: valuation(0,0)
   ***                 ^--------------
   *** valuation: domain error in gvaluation: p = 0
+  ***   at top-level: valuation(0,I)
+  ***                 ^--------------
+  *** valuation: domain error in gvaluation: p = I
+2
+0
 2
 1.0000000000000000000000000000000000000 - 1.00000000000000000000000000000000
 00000*x + O(x^2)
 1
 O(x)
-Total time spent: 8
+-oo
+-oo
+-oo
+Total time spent: 0
diff --git a/src/test/32/vararg b/src/test/32/vararg
new file mode 100644
index 0000000..aa2bffb
--- /dev/null
+++ b/src/test/32/vararg
@@ -0,0 +1,27 @@
+(s,v[..])->if(#v>0,print1(v[1]);for(i=2,#v,print1(s,v[i])));print()
+myprintsep =
+  (s,v[..])->if(#v>0,print1(v[1]);for(i=2,#v,print1(s,v[i])));print()
+
+:
+:
+a, b, c, d
+a, 0, c, 0
+a0b0c0d
+x=5
+x=5 y=7
+x=5 y=7 z=9
+:
+  ***   at top-level: print1(":");myprintsep()
+  ***                             ^------------
+  ***   in function myprintsep: s,v[..]
+  ***                           ^-------
+  ***   missing mandatory argument 's' in user function.
+:
+a, b, c, d
+  ***   at top-level: myprintsep(,a,b,c,d)
+  ***                 ^--------------------
+  ***   in function myprintsep: s,v[..]
+  ***                           ^-------
+  ***   missing mandatory argument 's' in user function.
+a, 0, c, 0
+Total time spent: 0
diff --git a/src/test/32/variable b/src/test/32/variable
index e35a088..eb45edc 100644
--- a/src/test/32/variable
+++ b/src/test/32/variable
@@ -8,5 +8,17 @@ y
 z
 0
 y
-[x, y, z, v]
-Total time spent: 4
+[x, y, z]
+[y, x, y, z, y]
+[y, x, y, z, y]
+[y, y, x, y, z, y]
+[y, y, x, y, z, y]
+[y, y, x, y, z, y, y]
+[y, y, x, y, z, y, y, tt]
+  ***   at top-level: varhigher("zzz",y);1/0
+  ***                                     ^--
+  *** _/_: impossible inverse in gdiv: 0.
+[y, y, x, y, z, y, y, tt]
+[y, x, y, z, y]
+[y, y, x, y, z, y, y, tt]
+Total time spent: 0
diff --git a/src/test/32/whatnow b/src/test/32/whatnow
index 26928e0..cb3735e 100644
--- a/src/test/32/whatnow
+++ b/src/test/32/whatnow
@@ -1,4 +1,4 @@
-This function was suppressed
+This function no longer exists
 
 New syntax: char(x,y) ===> charpoly(x,y)
 
@@ -19,4 +19,6 @@ As far as I can recall, this function never existed
 
 New syntax: compimag(x,y) ===> x*y
 
+x*y: product of x and y.
+
 Total time spent: 0
diff --git a/src/test/32/zetak b/src/test/32/zetak
index 3ef1e32..984f4c2 100644
--- a/src/test/32/zetak
+++ b/src/test/32/zetak
@@ -15,20 +15,20 @@
 1.1534151088973390171523689045164417703
 1.4238865750458932917520934583801572803
 0
-0.75988495679933103986934747406595883227 - 0.2667106768393931037951306887756
+0.75988495679933103986934747406595883226 - 0.2667106768393931037951306887756
 2967178*I
 0
 1.1979816549838251284996760656144424126
 1.6026632619004405990075072278650989584
 0
 0.56325049211603379810700612339514262331 - 0.7431218796586144471407060306283
-8684011*I
+8684012*I
 0
 1.1897132625253515180121146266710359469
 1.5629865407014105763649713127143672948
 0
-0.080540708067958142852744201044408963832 - 0.799351155467781709752299811229
-26087752*I
+0.080540708067958142852744201044408963836 - 0.799351155467781709752299811229
+26087755*I
 2*5^-1 + 2*5 + 3*5^2 + 3*5^4 + 3*5^5 + 2*5^6 + 5^7 + 4*5^8 + O(5^9)
 0.57721614942066140874800424251188396262 - 99.999271841202858157138397118797
 159155*I
@@ -49,4 +49,4 @@ error("overflow in zeta [large negative argument].")
 1.6449340668482264364724151666460251892 - 9.37548254315843753702574094567864
 97790 E-102*I
 100.57794333849687249028215428579024415
-Total time spent: 1344
+Total time spent: 1132
diff --git a/src/test/32/zn b/src/test/32/zn
index bac685d..15a3bce 100644
--- a/src/test/32/zn
+++ b/src/test/32/zn
@@ -25,6 +25,11 @@ Mod(84, 148)
 []
 []
 []
+0
+0
+[]
+[]
+[]
 1
 48
 []
@@ -42,4 +47,4 @@ _MAT).")
 error("incorrect type in generic discrete logarithm (order factorization) (t
 _MAT).")
 []
-Total time spent: 1392
+Total time spent: 1401
diff --git a/src/test/64/bnr b/src/test/64/bnr
deleted file mode 100644
index 7ce77ea..0000000
--- a/src/test/64/bnr
+++ /dev/null
@@ -1,44 +0,0 @@
-[]
-[[4, 0, 0; 0, 2, 0; 0, 0, 2], [4, 0, 2; 0, 2, 1; 0, 0, 1], [4, 2, 0; 0, 1, 0
-; 0, 0, 2], [4, 0, 2; 0, 2, 0; 0, 0, 1], [2, 0, 0; 0, 2, 0; 0, 0, 2], [4, 0,
- 0; 0, 2, 1; 0, 0, 1], [4, 0, 0; 0, 1, 0; 0, 0, 2], [4, 0, 0; 0, 2, 0; 0, 0,
- 1], [2, 0, 1; 0, 2, 1; 0, 0, 1], [1, 0, 0; 0, 2, 0; 0, 0, 2], [2, 0, 0; 0, 
-2, 1; 0, 0, 1], [4, 0, 2; 0, 1, 0; 0, 0, 1], [4, 2, 2; 0, 1, 0; 0, 0, 1], [2
-, 0, 0; 0, 1, 0; 0, 0, 2], [4, 2, 0; 0, 1, 0; 0, 0, 1], [2, 0, 0; 0, 2, 0; 0
-, 0, 1], [4, 0, 0; 0, 1, 0; 0, 0, 1], [1, 0, 0; 0, 2, 1; 0, 0, 1]]
-[[1, 0, 0; 0, 2, 1; 0, 0, 1]]
-[[1, 0, 0; 0, 2, 1; 0, 0, 1], [2, 0, 1; 0, 1, 0; 0, 0, 1], [2, 1, 1; 0, 1, 0
-; 0, 0, 1], [1, 0, 0; 0, 1, 0; 0, 0, 2], [2, 1, 0; 0, 1, 0; 0, 0, 1], [1, 0,
- 0; 0, 2, 0; 0, 0, 1], [2, 0, 0; 0, 1, 0; 0, 0, 1], [1, 0, 0; 0, 1, 0; 0, 0,
- 1]]
-  ***   at top-level: bnrL1(bnrinit(bnfini
-  ***                 ^--------------------
-  *** bnrL1: incorrect type in bnrL1 [subgroup] (t_INT).
-[32, 0, 27656345068767491604576153420888539136]
-0, 12, [24, 12, 40621487921685401825918161408203125]
-0, 12, [24, 12, 40621487921685401825918161408203125]
-1, 12, [24, 12, 40621487921685401825918161408203125]
-1, 6, [12, 12, 18026977100265125]
-12
-2
-12
-2
-[24, 12, 40621487921685401825918161408203125]
-[4, 4, 262205]
-[24, 12, 40621487921685401825918161408203125]
-[4, 4, 262205]
-[[5, 3; 0, 1], [1, 0]]
-[[5, 3; 0, 1], [0, 0]]
-[[5, 3; 0, 1], [1, 0]]
-[[5, 3; 0, 1], [0, 0]]
-[2, 2, [5, 3; 0, 1]]
-0
-0
-[4, 4, 262205]
-[2, 2, [5, 3; 0, 1]]
-6
-0.99197791640852265169404803750682485966 + 0.1264112865127400184730959576238
-0269659*I
-[4, [2, 2], [[3, 1; 0, 1], [114, 1; 0, 1]]]
-[[1, 0, 0; 0, 1, 0; 0, 0, 1], [0]]
-Total time spent: 28
diff --git a/src/test/64/bnrL1 b/src/test/64/bnrL1
deleted file mode 100644
index 0544e8a..0000000
--- a/src/test/64/bnrL1
+++ /dev/null
@@ -1,33 +0,0 @@
-[[1, 0.38224508584003564132935849918485739404 + 0.E-38*I], [1, 0.38224508584
-003564132935849918485739404 + 0.E-38*I], [0, -3/2]]
-[[2, 2.9500952396964494033818838179661887250 - 0.788700989456330674320020455
-38518403783*I], [2, 1.9859006356377427761789576705596841597], [2, 2.95009523
-96964494033818838179661887250 + 0.78870098945633067432002045538518403783*I],
- [1, -0.65847894846240835431252317365398422201]]
-[[1, 1.5356246494250488796129024765168058300 - 1.753485276139541406647384954
-4183759911*I], [2, 2.9500952396964494033818838179661887250 + 0.7887009894563
-3067432002045538518403783*I], [1, 1.1816366573593674455773236880707753793 - 
-2.7350893332487963668865434012735333609*I], [2, 1.98590063563774277617895767
-05596841597], [1, 1.1816366573593674455773236880707753793 + 2.73508933324879
-63668865434012735333609*I], [2, 2.9500952396964494033818838179661887250 - 0.
-78870098945633067432002045538518403783*I], [1, 1.535624649425048879612902476
-5168058300 + 1.7534852761395414066473849544183759911*I], [1, -0.658478948462
-40835431252317365398422201]]
-[[1, 1.1816366573593674455773236880707753792 + 2.735089333248796366886543401
-2735333609*I], [2, 2.9500952396964494033818838179661887250 + 0.7887009894563
-3067432002045538518403783*I], [1, 1.5356246494250488796129024765168058300 + 
-1.7534852761395414066473849544183759911*I], [2, 1.98590063563774277617895767
-05596841597], [1, 1.5356246494250488796129024765168058300 - 1.75348527613954
-14066473849544183759911*I], [2, 2.9500952396964494033818838179661887250 - 0.
-78870098945633067432002045538518403783*I], [1, 1.181636657359367445577323688
-0707753792 - 2.7350893332487963668865434012735333609*I], [0, 4.0000000000000
-000000000000000000000000], [1, 0.49056950319423383962705716863100284403 - 1.
-7496558360390569095857738490658820097*I], [0, 1.6000000000000000000000000000
-000000000 - 0.80000000000000000000000000000000000000*I], [1, -0.286637225639
-49733694072756623658748705 - 1.1610559298277086090237596773995345405*I], [0,
- 0.16666666666666666666666666666666666670], [1, -0.2866372256394973369407275
-6623658748705 + 1.1610559298277086090237596773995345405*I], [0, 1.6000000000
-000000000000000000000000000 + 0.80000000000000000000000000000000000000*I], [
-1, 0.49056950319423383962705716863100284403 + 1.7496558360390569095857738490
-658820097*I], [1, -0.65847894846240835431252317365398422201]]
-Total time spent: 108
diff --git a/src/test/64/compat b/src/test/64/compat
deleted file mode 100644
index 7392970..0000000
--- a/src/test/64/compat
+++ /dev/null
@@ -1,2593 +0,0 @@
-   echo = 1 (on)
-? default(compatible,3)
-  *** default: Warning: user functions re-initialized.
-? +3
-3
-? -5
--5
-? 5+3
-8
-? 5-3
-2
-? 5/3
-5/3
-? 5\3
-1
-? 5\/3
-2
-? 5%3
-2
-? 5^3
-125
-? \precision=154
-   realprecision = 154 significant digits
-? pi
-3.14159265358979323846264338327950288419716939937510582097494459230781640628
-6208998628034825342117067982148086513282306647093844609550582231725359408128
-481
-? \precision=38
-   realprecision = 38 significant digits
-? o(x^12)
-O(x^12)
-? padicno=(5/3)*127+o(127^5)
-44*127 + 42*127^2 + 42*127^3 + 42*127^4 + O(127^5)
-? initrect(0,500,500)
-? abs(-0.01)
-0.010000000000000000000000000000000000000
-? acos(0.5)
-1.0471975511965977461542144610931676281
-? acosh(3)
-1.7627471740390860504652186499595846181
-? acurve=initell([0,0,1,-1,0])
-[0, 0, 1, -1, 0, 0, -2, 1, -1, 48, -216, 37, 110592/37, Vecsmall([1]), [Vecs
-mall([128, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]
-? apoint=[2,2]
-[2, 2]
-? isoncurve(acurve,apoint)
-1
-? addell(acurve,apoint,apoint)
-[21/25, -56/125]
-? addprimes([nextprime(10^9),nextprime(10^10)])
-[1000000007, 10000000019]
-? adj([1,2;3,4])
-
-[ 4 -2]
-
-[-3  1]
-
-? agm(1,2)
-1.4567910310469068691864323832650819750
-? agm(1+o(7^5),8+o(7^5))
-1 + 4*7 + 6*7^2 + 5*7^3 + 2*7^4 + O(7^5)
-? algdep(2*cos(2*pi/13),6)
-x^6 + x^5 - 5*x^4 - 4*x^3 + 6*x^2 + 3*x - 1
-? algdep2(2*cos(2*pi/13),6,15)
-x^6 + x^5 - 5*x^4 - 4*x^3 + 6*x^2 + 3*x - 1
-? akell(acurve,1000000007)
-43800
-? nfpol=x^5-5*x^3+5*x+25
-x^5 - 5*x^3 + 5*x + 25
-? nf=initalg(nfpol)
-[x^5 - 5*x^3 + 5*x + 25, [1, 2], 595125, 45, [[1, -1.08911514572050482502495
-27946671612684, -2.4285174907194186068992069565359418365, 0.7194669112891317
-8943997506477288225737, -2.5558200350691694950646071159426779972; 1, -0.1383
-8372073406036365047976417441696637 - 0.4918163765776864349975328551474152510
-7*I, 1.9647119211288133163138753392090569931 + 0.809714924188978951282940822
-19556466857*I, -0.072312766896812300380582649294307897074 + 2.19808037538462
-76641195195160383234878*I, -0.98796319352507039803950539735452837193 + 1.570
-1452385894131769052374806001981109*I; 1, 1.682941293594312776162956161507997
-6006 + 2.0500351226010726172974286983598602164*I, -0.75045317576910401286427
-186094108607489 + 1.3101462685358123283560773619310445916*I, -0.787420688747
-75359433940488309213323154 + 2.1336633893126618034168454610457936018*I, 1.26
-58732110596551455718089553258673705 - 2.716479010374315056657802803578983483
-5*I], [1, -1.0891151457205048250249527946671612684, -2.428517490719418606899
-2069565359418365, 0.71946691128913178943997506477288225737, -2.5558200350691
-694950646071159426779972; 1, -0.63020009731174679864801261932183221743, 2.77
-44268453177922675968161614046216617, 2.1257676084878153637389368667440155907
-, 0.58218204506434277886573208324566973897; 1, 0.353432655843626071347053090
-97299828470, 1.1549969969398343650309345170134923246, -2.2703931422814399645
-001021653326313849, -2.5581084321144835749447428779547264828; 1, 3.732976416
-1953853934603848598678578170, 0.55969309276670831549180550098995851667, 1.34
-62427005649082090774405779536603703, -1.450605799314659911085993848253116112
-9; 1, -0.36709382900675984113447253685186261580, -2.060599444304916341220349
-2228721306665, -2.9210840780604153977562503441379268334, 3.98235222143397020
-22296117589048508540], [1, -1, -2, 1, -3; 1, -1, 3, 2, 1; 1, 0, 1, -2, -3; 1
-, 4, 1, 1, -1; 1, 0, -2, -3, 4], [5, 2, 0, -1, -2; 2, -2, -5, -10, 20; 0, -5
-, 10, -10, 5; -1, -10, -10, -17, 1; -2, 20, 5, 1, -8], [345, 0, 200, 110, 17
-7; 0, 345, 95, 1, 145; 0, 0, 5, 4, 3; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], [63, 3,
- 0, -6, -9; 3, 8, -5, -1, 16; 0, -5, 22, -10, 0; -6, -1, -10, -14, -9; -9, 1
-6, 0, -9, -2], [345, [138, 117, 330, 288, -636; -172, -88, 65, 118, -116; 53
-, 1, 138, -173, 65; 1, -172, 54, 191, 106; 0, 118, 173, 225, -34]], [3, 5, 2
-3]], [-2.4285174907194186068992069565359418365, 1.96471192112881331631387533
-92090569931 + 0.80971492418897895128294082219556466857*I, -0.750453175769104
-01286427186094108607489 + 1.3101462685358123283560773619310445916*I], [1, 1/
-15*x^4 - 2/3*x^2 + 1/3*x + 4/3, x, 2/15*x^4 - 1/3*x^2 + 2/3*x - 1/3, -1/15*x
-^4 + 1/3*x^3 + 1/3*x^2 - 4/3*x - 2/3], [1, 0, 3, 1, 10; 0, 0, -2, 1, -5; 0, 
-1, 0, 3, -5; 0, 0, 1, 1, 10; 0, 0, 0, 3, 0], [1, 0, 0, 0, 0, 0, -1, -1, -2, 
-4, 0, -1, 3, -1, 1, 0, -2, -1, -3, -1, 0, 4, 1, -1, -1; 0, 1, 0, 0, 0, 1, 1,
- -1, -1, 1, 0, -1, -2, -1, 1, 0, -1, -1, -1, 3, 0, 1, 1, 3, -3; 0, 0, 1, 0, 
-0, 0, 0, 0, 1, -1, 1, 0, 0, 0, -2, 0, 1, 0, -1, -1, 0, -1, -2, -1, -1; 0, 0,
- 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 2, 1, 0, 1, 0, 0, 0, 0, 2, 0, -1; 0, 0,
- 0, 0, 1, 0, -1, -1, -1, 1, 0, -1, 0, 1, 0, 0, -1, 1, 0, 0, 1, 1, 0, 0, -1]]
-? ba=algtobasis(nf,mod(x^3+5,nfpol))
-[6, 1, 3, 1, 3]~
-? anell(acurve,100)
-[1, -2, -3, 2, -2, 6, -1, 0, 6, 4, -5, -6, -2, 2, 6, -4, 0, -12, 0, -4, 3, 1
-0, 2, 0, -1, 4, -9, -2, 6, -12, -4, 8, 15, 0, 2, 12, -1, 0, 6, 0, -9, -6, 2,
- -10, -12, -4, -9, 12, -6, 2, 0, -4, 1, 18, 10, 0, 0, -12, 8, 12, -8, 8, -6,
- -8, 4, -30, 8, 0, -6, -4, 9, 0, -1, 2, 3, 0, 5, -12, 4, 8, 9, 18, -15, 6, 0
-, -4, -18, 0, 4, 24, 2, 4, 12, 18, 0, -24, 4, 12, -30, -2]
-? apell(acurve,10007)
-66
-? apell2(acurve,10007)
-66
-? apol=x^3+5*x+1
-x^3 + 5*x + 1
-? apprpadic(apol,1+o(7^8))
-[1 + 6*7 + 4*7^2 + 4*7^3 + 3*7^4 + 4*7^5 + 6*7^7 + O(7^8)]~
-? apprpadic(x^3+5*x+1,mod(x*(1+o(7^8)),x^2+x-1))
-[mod((1 + 3*7 + 3*7^2 + 4*7^3 + 4*7^4 + 4*7^5 + 2*7^6 + 3*7^7 + O(7^8))*x + 
-(2*7 + 6*7^2 + 6*7^3 + 3*7^4 + 3*7^5 + 4*7^6 + 5*7^7 + O(7^8)), x^2 + x - 1)
-]~
-? 4*arg(3+3*i)
-3.1415926535897932384626433832795028842
-? 3*asin(sqrt(3)/2)
-3.1415926535897932384626433832795028842
-? asinh(0.5)
-0.48121182505960344749775891342436842314
-? assmat(x^5-12*x^3+0.0005)
-
-[0 0 0 0 -0.00050000000000000000000000000000000000000]
-
-[1 0 0 0                                            0]
-
-[0 1 0 0                                            0]
-
-[0 0 1 0                                           12]
-
-[0 0 0 1                                            0]
-
-? 3*atan(sqrt(3))
-3.1415926535897932384626433832795028842
-? atanh(0.5)
-0.54930614433405484569762261846126285232
-? basis(x^3+4*x+5)
-[1, x, 1/7*x^2 - 1/7*x - 2/7]
-? basis2(x^3+4*x+5)
-[1, x, 1/7*x^2 - 1/7*x - 2/7]
-? basistoalg(nf,ba)
-mod(x^3 + 5, x^5 - 5*x^3 + 5*x + 25)
-? bernreal(12)
--0.25311355311355311355311355311355311355
-? bernvec(6)
-[1, 1/6, -1/30, 1/42, -1/30, 5/66, -691/2730]
-? bestappr(pi,10000)
-355/113
-? bezout(123456789,987654321)
-[-8, 1, 9]
-? bigomega(12345678987654321)
-8
-? mcurve=initell([0,0,0,-17,0])
-[0, 0, 0, -17, 0, 0, -34, 0, -289, 816, 0, 314432, 1728, Vecsmall([1]), [Vec
-small([128, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]
-? mpoints=[[-1,4],[-4,2]]~
-[[-1, 4], [-4, 2]]~
-? mhbi=bilhell(mcurve,mpoints,[9,24])
-[-0.72448571035980184146215805860545027441, 1.307328627832055544492943428892
-1943056]~
-? bin(1.1,5)
--0.0045457500000000000000000000000000000000
-? binary(65537)
-[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
-? bittest(10^100,100)
-1
-? boundcf(pi,5)
-[3, 7, 15, 1, 292]
-? boundfact(40!+1,100000)
-
-[                                         41 1]
-
-[                                         59 1]
-
-[                                        277 1]
-
-[1217669507565553887239873369513188900554127 1]
-
-? move(0,0,0);box(0,500,500)
-? setrand(1);buchimag(1-10^7,1,1)
-[2416, [1208, 2], [qfi(277, 55, 9028), qfi(1700, 1249, 1700)], 1]
-? setrand(1);bnf=buchinitfu(x^2-x-57,0.2,0.2)
-[mat(3), mat([1, 1, 2]), [-2.7124653051843439746808795106061300699 + 3.14159
-26535897932384626433832795028842*I; 2.7124653051843439746808795106061300699]
-, [1.7903417566977293763292119206302198761, 1.289761953065273502503008607239
-5031018 + 3.1415926535897932384626433832795028842*I, 0.E-37, 0.5005798036324
-5587382620331339071677436; -1.7903417566977293763292119206302198761, -1.2897
-619530652735025030086072395031018, 0.E-38, -0.500579803632455873826203313390
-71677436 + 3.1415926535897932384626433832795028842*I], [[3, [-1, 1]~, 1, 1, 
-[0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 57; 1, 2]], [3, [0, 1]~, 1, 1, [-1, 
-57; 1, 0]], [5, [1, 1]~, 1, 1, [-2, 57; 1, -1]]], 0, [x^2 - x - 57, [2, 0], 
-229, 1, [[1, -7.0663729752107779635959310246705326059; 1, 8.0663729752107779
-635959310246705326058], [1, -7.0663729752107779635959310246705326059; 1, 8.0
-663729752107779635959310246705326058], [1, -7; 1, 8], [2, 1; 1, 115], [229, 
-114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]], [229]], [-7.06637297
-52107779635959310246705326059, 8.0663729752107779635959310246705326058], [1,
- x], [1, 0; 0, 1], [1, 0, 0, 57; 0, 1, 1, 1]], [[3, [3], [[3, 2; 0, 1]]], 2.
-7124653051843439746808795106061300699, 1, [2, -1], [x + 7]], [mat(1), [[0, 0
-]], [[1.7903417566977293763292119206302198761, -1.79034175669772937632921192
-06302198761]]], [0, 0]]
-? buchcertify(bnf)
-1
-? buchfu(bnf)
-[x + 7]
-? setrand(1);buchinitforcefu(x^2-x-100000)
-[mat(5), mat([3, 2, 1, 2, 0, 3, 4, 1, 3, 2, 0, 0, 2, 3, 3, 2, 2, 3]), [-129.
-82045011403975460991182396195022419 + 6.771228821958152128 E-113*I; 129.8204
-5011403975460991182396195022419 + 5.796659156428942826 E-113*I], [-41.811264
-589129943393339502258694361489, 9.2399004147902289816376260438840931575 + 3.
-1415926535897932384626433832795028842*I, -11.8746098810754067250973159974311
-61032, 129.82045011403975460991182396195022419 + 3.1415926535897932384626433
-832795028842*I, 78.769285110119582234934695659371769545 + 3.1415926535897932
-384626433832795028842*I, 843.83292574125840496442685575267645724 + 3.1415926
-535897932384626433832795028842*I, 99.883795405985217941669637700687023734 + 
-6.2831853071795864769252867665590057684*I, -594.2238464718864434047370989340
-7797533 + 2.761280718999426355 E-113*I, 552.41258188275650001139759667538361
-384 + 6.2831853071795864769252867665590057684*I, -943.8166642091125376019420
-3404129129272 + 5.197704882822449609 E-113*I, 512.54404927786333037886705989
-674625866 + 6.2831853071795864769252867665590057684*I, 47.668319071568233997
-332918482707687879 + 3.1415926535897932384626433832795028842*I, -1086.231919
-9838862708766275101783094814 + 5.847417993175255810 E-113*I, 232.80982374359
-817890011490485449930607 + 6.2831853071795864769252867665590057684*I, 504.30
-161235151040536601653665850767759 + 6.2831853071795864769252867665590057684*
-I, -541.38631597877289632049789027161711131 + 3.1415926535897932384626433832
-795028842*I, -1447.7317003209533662215189714163306131 + 3.141592653589793238
-4626433832795028842*I, 912.61944444475616477613125021268707696 + 6.283185307
-1795864769252867665590057684*I, -954.43070903388610816947075247138143845 + 4
-.223135217293240308 E-113*I; 41.811264589129943393339502258694361489 + 6.497
-131103528062012 E-114*I, -9.2399004147902289816376260438840931575 + 6.283185
-3071795864769252867665590057684*I, 11.874609881075406725097315997431161032 +
- 3.1415926535897932384626433832795028842*I, -129.820450114039754609911823961
-95022419 + 3.1415926535897932384626433832795028842*I, -78.769285110119582234
-934695659371769545 + 6.2831853071795864769252867665590057684*I, -843.8329257
-4125840496442685575267645724 + 6.2831853071795864769252867665590057684*I, -9
-9.883795405985217941669637700687023734 + 3.141592653589793238462643383279502
-8842*I, 594.22384647188644340473709893407797533 + 4.263742286690290695 E-113
-*I, -552.41258188275650001139759667538361384 + 6.283185307179586476925286766
-5590057684*I, 943.81666420911253760194203404129129272 + 3.141592653589793238
-4626433832795028842*I, -512.54404927786333037886705989674625866 + 3.14159265
-35897932384626433832795028842*I, -47.668319071568233997332918482707687879 + 
-3.1415926535897932384626433832795028842*I, 1086.2319199838862708766275101783
-094814 + 7.877771463027775189 E-113*I, -232.80982374359817890011490485449930
-607 + 3.1415926535897932384626433832795028842*I, -504.3016123515104053660165
-3665850767759 + 3.1415926535897932384626433832795028842*I, 541.3863159787728
-9632049789027161711131 + 4.588598841866693796 E-113*I, 1447.7317003209533662
-215189714163306131 + 1.0882694598409503869 E-112*I, -912.6194444447561647761
-3125021268707696 + 6.2831853071795864769252867665590057684*I, 954.4307090338
-8610816947075247138143845 + 6.172274548351658911 E-113*I], [[2, [1, 1]~, 1, 
-1, [0, 100000; 1, 1]], [5, [4, 1]~, 1, 1, [0, 100000; 1, 1]], [13, [-6, 1]~,
- 1, 1, [5, 100000; 1, 6]], [2, [2, 1]~, 1, 1, [1, 100000; 1, 2]], [5, [5, 1]
-~, 1, 1, [-1, 100000; 1, 0]], [7, [3, 1]~, 2, 1, [3, 100000; 1, 4]], [13, [5
-, 1]~, 1, 1, [-6, 100000; 1, -5]], [29, [-14, 1]~, 1, 1, [13, 100000; 1, 14]
-], [29, [13, 1]~, 1, 1, [-14, 100000; 1, -13]], [17, [14, 1]~, 1, 1, [2, 100
-000; 1, 3]], [17, [19, 1]~, 1, 1, [-3, 100000; 1, -2]], [23, [-7, 1]~, 1, 1,
- [6, 100000; 1, 7]], [23, [6, 1]~, 1, 1, [-7, 100000; 1, -6]], [31, [23, 1]~
-, 1, 1, [7, 100000; 1, 8]], [31, [38, 1]~, 1, 1, [-8, 100000; 1, -7]], [41, 
-[-7, 1]~, 1, 1, [6, 100000; 1, 7]], [41, [6, 1]~, 1, 1, [-7, 100000; 1, -6]]
-, [43, [-16, 1]~, 1, 1, [15, 100000; 1, 16]], [43, [15, 1]~, 1, 1, [-16, 100
-000; 1, -15]]], 0, [x^2 - x - 100000, [2, 0], 400001, 1, [[1, -315.728161301
-29840161392089489603747004; 1, 316.72816130129840161392089489603747004], [1,
- -315.72816130129840161392089489603747004; 1, 316.72816130129840161392089489
-603747004], [1, -316; 1, 317], [2, 1; 1, 200001], [400001, 200000; 0, 1], [2
-00001, -1; -1, 2], [400001, [200000, 100000; 1, 200001]], [7, 57143]], [-315
-.72816130129840161392089489603747004, 316.7281613012984016139208948960374700
-4], [1, x], [1, 0; 0, 1], [1, 0, 0, 100000; 0, 1, 1, 1]], [[5, [5], [[2, 1; 
-0, 1]]], 129.82045011403975460991182396195022419, 1, [2, -1], [3795548840190
-13781006303254896369154068336082609238336*x + 119836165644250789990462835950
-022871665178127611316131167]], [mat(1), [[0, 0]], [[-41.81126458912994339333
-9502258694361489, 41.811264589129943393339502258694361489 + 6.49713110352806
-2012 E-114*I]]], [0, 0]]
-? setrand(1);bnf=buchinitfu(x^2-x-57,0.2,0.2)
-[mat(3), mat([1, 1, 2]), [-2.7124653051843439746808795106061300699 + 3.14159
-26535897932384626433832795028842*I; 2.7124653051843439746808795106061300699]
-, [1.7903417566977293763292119206302198761, 1.289761953065273502503008607239
-5031018 + 3.1415926535897932384626433832795028842*I, 0.E-37, 0.5005798036324
-5587382620331339071677436; -1.7903417566977293763292119206302198761, -1.2897
-619530652735025030086072395031018, 0.E-38, -0.500579803632455873826203313390
-71677436 + 3.1415926535897932384626433832795028842*I], [[3, [-1, 1]~, 1, 1, 
-[0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 57; 1, 2]], [3, [0, 1]~, 1, 1, [-1, 
-57; 1, 0]], [5, [1, 1]~, 1, 1, [-2, 57; 1, -1]]], 0, [x^2 - x - 57, [2, 0], 
-229, 1, [[1, -7.0663729752107779635959310246705326059; 1, 8.0663729752107779
-635959310246705326058], [1, -7.0663729752107779635959310246705326059; 1, 8.0
-663729752107779635959310246705326058], [1, -7; 1, 8], [2, 1; 1, 115], [229, 
-114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]], [229]], [-7.06637297
-52107779635959310246705326059, 8.0663729752107779635959310246705326058], [1,
- x], [1, 0; 0, 1], [1, 0, 0, 57; 0, 1, 1, 1]], [[3, [3], [[3, 2; 0, 1]]], 2.
-7124653051843439746808795106061300699, 1, [2, -1], [x + 7]], [mat(1), [[0, 0
-]], [[1.7903417566977293763292119206302198761, -1.79034175669772937632921192
-06302198761]]], [0, 0]]
-? setrand(1);buchreal(10^9-3,0,0.5,0.5)
-[4, [4], [qfr(211, 31405, -16263, 0.E-57)], 2800.625251907016076486370621737
-0745514]
-? setrand(1);buchgen(x^4-7,0.2,0.2)
-
-[                                                     x^4 - 7]
-
-[                                                      [2, 1]]
-
-[                                                 [-87808, 1]]
-
-[                                            [1, x, x^2, x^3]]
-
-[[2, [2], [[3, 2, 2, 2; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1]]]]
-
-[                     14.229975145405511722395637833443108790]
-
-[                                                           1]
-
-[                                                     [2, -1]]
-
-[                                  [x^2 - x - 1, x^2 + x - 1]]
-
-? setrand(1);buchgenfu(x^2-x-100000)
-
-[                       x^2 - x - 100000]
-
-[                                 [2, 0]]
-
-[                            [400001, 1]]
-
-[                                 [1, x]]
-
-[              [5, [5], [[13, 7; 0, 1]]]]
-
-[129.82045011403975460991182396195022417]
-
-[                                      1]
-
-[                                [2, -1]]
-
-[                                    [;]]
-
-? setrand(1);buchgenforcefu(x^2-x-100000)
-
-[x^2 - x - 100000]
-
-[[2, 0]]
-
-[[400001, 1]]
-
-[[1, x]]
-
-[[5, [5], [[2, 1; 0, 1]]]]
-
-[129.82045011403975460991182396195022419]
-
-[1]
-
-[[2, -1]]
-
-[[379554884019013781006303254896369154068336082609238336*x + 119836165644250
-789990462835950022871665178127611316131167]]
-
-? setrand(1);buchgenfu(x^4+24*x^2+585*x+1791,0.1,0.1)
-
-[x^4 + 24*x^2 + 585*x + 1791]
-
-[[0, 2]]
-
-[[18981, 3087]]
-
-[[1, -10/1029*x^3 + 13/343*x^2 - 165/343*x - 1135/343, 17/1029*x^3 - 32/1029
-*x^2 + 109/343*x + 2444/343, -26/1029*x^3 + 170/1029*x^2 - 429/343*x - 3294/
-343]]
-
-[[4, [4], [[7, 2, 0, 1; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1]]]]
-
-[3.7941269688216589341408274220859400303]
-
-[1]
-
-[[6, 10/1029*x^3 - 13/343*x^2 + 165/343*x + 1478/343]]
-
-[[1/343*x^3 - 46/1029*x^2 - 122/343*x - 174/343]]
-
-? buchnarrow(bnf)
-[3, [3], [[3, 2; 0, 1]]]
-? buchray(bnf,[[5,3;0,1],[1,0]])
-[12, [12], [[3, 2; 0, 1]]]
-? bnr=buchrayinitgen(bnf,[[5,3;0,1],[1,0]])
-[[mat(3), mat([1, 1, 2]), [-2.7124653051843439746808795106061300699 + 3.1415
-926535897932384626433832795028842*I; 2.7124653051843439746808795106061300699
-], [1.7903417566977293763292119206302198761, 1.28976195306527350250300860723
-95031018 + 3.1415926535897932384626433832795028842*I, 0.E-37, 0.500579803632
-45587382620331339071677436; -1.7903417566977293763292119206302198761, -1.289
-7619530652735025030086072395031018, 0.E-38, -0.50057980363245587382620331339
-071677436 + 3.1415926535897932384626433832795028842*I], [[3, [-1, 1]~, 1, 1,
- [0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 57; 1, 2]], [3, [0, 1]~, 1, 1, [-1,
- 57; 1, 0]], [5, [1, 1]~, 1, 1, [-2, 57; 1, -1]]], 0, [x^2 - x - 57, [2, 0],
- 229, 1, [[1, -7.0663729752107779635959310246705326059; 1, 8.066372975210777
-9635959310246705326058], [1, -7.0663729752107779635959310246705326059; 1, 8.
-0663729752107779635959310246705326058], [1, -7; 1, 8], [2, 1; 1, 115], [229,
- 114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]], [229]], [-7.0663729
-752107779635959310246705326059, 8.0663729752107779635959310246705326058], [1
-, x], [1, 0; 0, 1], [1, 0, 0, 57; 0, 1, 1, 1]], [[3, [3], [[3, 2; 0, 1]]], 2
-.7124653051843439746808795106061300699, 1, [2, -1], [x + 7]], [mat(1), [[0, 
-0]], [[1.7903417566977293763292119206302198761, -1.7903417566977293763292119
-206302198761]]], [0, [mat([[5, 1]~, 1])]]], [[[5, 3; 0, 1], [1, 0]], [8, [4,
- 2], [2, [-4, 0]~]], mat([[5, [-2, 1]~, 1, 1, [1, 57; 1, 2]], 1]), [[[[4], [
-2], [2], [Vecsmall([0])], 1]], [[2], [-4], [Vecsmall([1])]]], [1, 0; 0, 1]],
- [1], mat([1, -3, -6]), [12, [12], [[3, 2; 0, 1]]], [[0, 1; 0, 0], [-1, -1; 
-1, -1], 1]]
-? bnr2=buchrayinitgen(bnf,[[25,13;0,1],[1,1]])
-[[mat(3), mat([1, 1, 2]), [-2.7124653051843439746808795106061300699 + 3.1415
-926535897932384626433832795028842*I; 2.7124653051843439746808795106061300699
-], [1.7903417566977293763292119206302198761, 1.28976195306527350250300860723
-95031018 + 3.1415926535897932384626433832795028842*I, 0.E-37, 0.500579803632
-45587382620331339071677436; -1.7903417566977293763292119206302198761, -1.289
-7619530652735025030086072395031018, 0.E-38, -0.50057980363245587382620331339
-071677436 + 3.1415926535897932384626433832795028842*I], [[3, [-1, 1]~, 1, 1,
- [0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 57; 1, 2]], [3, [0, 1]~, 1, 1, [-1,
- 57; 1, 0]], [5, [1, 1]~, 1, 1, [-2, 57; 1, -1]]], 0, [x^2 - x - 57, [2, 0],
- 229, 1, [[1, -7.0663729752107779635959310246705326059; 1, 8.066372975210777
-9635959310246705326058], [1, -7.0663729752107779635959310246705326059; 1, 8.
-0663729752107779635959310246705326058], [1, -7; 1, 8], [2, 1; 1, 115], [229,
- 114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]], [229]], [-7.0663729
-752107779635959310246705326059, 8.0663729752107779635959310246705326058], [1
-, x], [1, 0; 0, 1], [1, 0, 0, 57; 0, 1, 1, 1]], [[3, [3], [[3, 2; 0, 1]]], 2
-.7124653051843439746808795106061300699, 1, [2, -1], [x + 7]], [mat(1), [[0, 
-0]], [[1.7903417566977293763292119206302198761, -1.7903417566977293763292119
-206302198761]]], [0, [mat([[5, 1]~, 1])]]], [[[25, 13; 0, 1], [1, 1]], [80, 
-[20, 2, 2], [2, [-24, 0]~, [2, 2]~]], mat([[5, [-2, 1]~, 1, 1, [1, 57; 1, 2]
-], 2]), [[[[4], [2], [2], [Vecsmall([0, 0])], 1], [[5], [6], [6], [Vecsmall(
-[0, 0])], mat([1/5, -13/5])]], [[2, 2], [-24, [2, 2]~], [Vecsmall([0, 1]), V
-ecsmall([1, 1])]]], [1, -12, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1]], [1], mat([1, -3
-, -6, -6]), [12, [12], [[3, 2; 0, 1]]], [[0, 2, 0; -1, 10, 0], [-2, 0; 0, -1
-0], 2]]
-? bytesize(%)
-9216
-? ceil(-2.5)
--2
-? centerlift(mod(456,555))
--99
-? cf(pi)
-[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, 13, 1, 4, 2, 6, 6]
-? cf2([1,3,5,7,9],(exp(1)-1)/(exp(1)+1))
-[0, 6, 10, 42, 30]
-? changevar(x+y,[z,t])
-  ***   at top-level: changevar(x+y,[z,t])
-  ***                 ^--------------------
-  *** changevar: this function no longer exists.
-? char([1,2;3,4],z)
-z^2 - 5*z - 2
-? char(mod(x^2+x+1,x^3+5*x+1),z)
-z^3 + 7*z^2 + 16*z - 19
-? char1([1,2;3,4],z)
-z^2 - 5*z - 2
-? char2(mod(1,8191)*[1,2;3,4],z)
-z^2 + mod(8186, 8191)*z + mod(8189, 8191)
-? acurve=chell(acurve,[-1,1,2,3])
-[-4, -1, -7, -12, -12, 12, 4, 1, -1, 48, -216, 37, 110592/37, Vecsmall([1]),
- [Vecsmall([128, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]
-? chinese(mod(7,15),mod(13,21))
-mod(97, 105)
-? apoint=chptell(apoint,[-1,1,2,3])
-[1, 3]
-? isoncurve(acurve,apoint)
-1
-? classno(-12391)
-63
-? classno(1345)
-6
-? classno2(-12391)
-63
-? classno2(1345)
-6
-? coeff(sin(x),7)
--1/5040
-? compimag(qfi(2,1,3),qfi(2,1,3))
-qfi(2, -1, 3)
-? compo(1+o(7^4),3)
-1
-? compositum(x^4-4*x+2,x^3-x-1)
-[x^12 - 4*x^10 + 8*x^9 + 12*x^8 + 12*x^7 + 138*x^6 + 132*x^5 - 43*x^4 + 58*x
-^2 - 128*x - 5]
-? compositum2(x^4-4*x+2,x^3-x-1)
-[[x^12 - 4*x^10 + 8*x^9 + 12*x^8 + 12*x^7 + 138*x^6 + 132*x^5 - 43*x^4 + 58*
-x^2 - 128*x - 5, mod(-279140305176/29063006931199*x^11 + 129916611552/290630
-06931199*x^10 + 1272919322296/29063006931199*x^9 - 2813750209005/29063006931
-199*x^8 - 2859411937992/29063006931199*x^7 - 414533880536/29063006931199*x^6
- - 35713977492936/29063006931199*x^5 - 17432607267590/29063006931199*x^4 + 4
-9785595543672/29063006931199*x^3 + 9423768373204/29063006931199*x^2 - 427797
-76146743/29063006931199*x + 37962587857138/29063006931199, x^12 - 4*x^10 + 8
-*x^9 + 12*x^8 + 12*x^7 + 138*x^6 + 132*x^5 - 43*x^4 + 58*x^2 - 128*x - 5), m
-od(-279140305176/29063006931199*x^11 + 129916611552/29063006931199*x^10 + 12
-72919322296/29063006931199*x^9 - 2813750209005/29063006931199*x^8 - 28594119
-37992/29063006931199*x^7 - 414533880536/29063006931199*x^6 - 35713977492936/
-29063006931199*x^5 - 17432607267590/29063006931199*x^4 + 49785595543672/2906
-3006931199*x^3 + 9423768373204/29063006931199*x^2 - 13716769215544/290630069
-31199*x + 37962587857138/29063006931199, x^12 - 4*x^10 + 8*x^9 + 12*x^8 + 12
-*x^7 + 138*x^6 + 132*x^5 - 43*x^4 + 58*x^2 - 128*x - 5), -1]]
-? comprealraw(qfr(5,3,-1,0.),qfr(7,1,-1,0.))
-qfr(35, 43, 13, 0.E-38)
-? concat([1,2],[3,4])
-[1, 2, 3, 4]
-? conductor(bnf,[[25,13;0,1],[1,1]])
-[[[5, 3; 0, 1], [1, 0]], [12, [12], [[3, 2; 0, 1]]], mat(12)]
-? conductorofchar(bnr,[2])
-[[5, 3; 0, 1], [0, 0]]
-? conj(1+i)
-1 - I
-? conjvec(mod(x^2+x+1,x^3-x-1))
-[4.0795956234914387860104177508366260326, 0.46020218825428060699479112458168
-698369 + 0.18258225455744299269398828369501930574*I, 0.460202188254280606994
-79112458168698369 - 0.18258225455744299269398828369501930574*I]~
-? content([123,456,789,234])
-3
-? convol(sin(x),x*cos(x))
-x + 1/12*x^3 + 1/2880*x^5 + 1/3628800*x^7 + 1/14631321600*x^9 + 1/1448500838
-40000*x^11 + 1/2982752926433280000*x^13 + 1/114000816848279961600000*x^15 + 
-O(x^17)
-? core(54713282649239)
-5471
-? core2(54713282649239)
-[5471, 100003]
-? coredisc(54713282649239)
-21884
-? coredisc2(54713282649239)
-[21884, 100003/2]
-? cos(1)
-0.54030230586813971740093660744297660373
-? cosh(1)
-1.5430806348152437784779056207570616826
-? move(0,200,150)
-? cursor(0)
-? cvtoi(1.7)
-1
-? cyclo(105)
-x^48 + x^47 + x^46 - x^43 - x^42 - 2*x^41 - x^40 - x^39 + x^36 + x^35 + x^34
- + x^33 + x^32 + x^31 - x^28 - x^26 - x^24 - x^22 - x^20 + x^17 + x^16 + x^1
-5 + x^14 + x^13 + x^12 - x^9 - x^8 - 2*x^7 - x^6 - x^5 + x^2 + x + 1
-? degree(x^3/(x-1))
-2
-? denom(12345/54321)
-18107
-? deplin(mod(1,7)*[2,-1;1,3])
-[-3, 1]~
-? deriv((x+y)^5,y)
-5*x^4 + 20*y*x^3 + 30*y^2*x^2 + 20*y^3*x + 5*y^4
-? ((x+y)^5)'
-5*x^4 + 20*y*x^3 + 30*y^2*x^2 + 20*y^3*x + 5*y^4
-? det([1,2,3;1,5,6;9,8,7])
--30
-? det2([1,2,3;1,5,6;9,8,7])
--30
-? detint([1,2,3;4,5,6])
-3
-? diagonal([2,4,6])
-
-[2 0 0]
-
-[0 4 0]
-
-[0 0 6]
-
-? dilog(0.5)
-0.58224052646501250590265632015968010874
-? dz=vector(30,k,1);dd=vector(30,k,k==1);dm=dirdiv(dd,dz)
-[1, -1, -1, 0, -1, 1, -1, 0, 0, 1, -1, 0, -1, 1, 1, 0, -1, 0, -1, 0, 1, 1, -
-1, 0, 0, 1, 0, 0, -1, -1]
-? deu=direuler(p=2,100,1/(1-apell(acurve,p)*x+if(acurve[12]%p,p,0)*x^2))
-[1, -2, -3, 2, -2, 6, -1, 0, 6, 4, -5, -6, -2, 2, 6, -4, 0, -12, 0, -4, 3, 1
-0, 2, 0, -1, 4, -9, -2, 6, -12, -4, 8, 15, 0, 2, 12, -1, 0, 6, 0, -9, -6, 2,
- -10, -12, -4, -9, 12, -6, 2, 0, -4, 1, 18, 10, 0, 0, -12, 8, 12, -8, 8, -6,
- -8, 4, -30, 8, 0, -6, -4, 9, 0, -1, 2, 3, 0, 5, -12, 4, 8, 9, 18, -15, 6, 0
-, -4, -18, 0, 4, 24, 2, 4, 12, 18, 0, -24, 4, 12, -30, -2]
-? anell(acurve,100)==deu
-1
-? dirmul(abs(dm),dz)
-[1, 2, 2, 2, 2, 4, 2, 2, 2, 4, 2, 4, 2, 4, 4, 2, 2, 4, 2, 4, 4, 4, 2, 4, 2, 
-4, 2, 4, 2, 8]
-? dirzetak(initalg(x^3-10*x+8),30)
-[1, 2, 0, 3, 1, 0, 0, 4, 0, 2, 1, 0, 0, 0, 0, 5, 1, 0, 0, 3, 0, 2, 0, 0, 2, 
-0, 1, 0, 1, 0]
-? disc(x^3+4*x+12)
--4144
-? discf(x^3+4*x+12)
--1036
-? discrayabs(bnr,mat(6))
-[12, 12, 18026977100265125]
-? discrayabs(bnr)
-[24, 12, 40621487921685401825918161408203125]
-? discrayabscond(bnr2)
-0
-? lu=ideallistunitgen(bnf,55);discrayabslist(bnf,lu)
-[[[6, 6, mat([229, 3])]], [], [[], []], [[]], [[12, 12, [5, 3; 229, 6]], [12
-, 12, [5, 3; 229, 6]]], [], [], [], [[], [], []], [], [[], []], [[], []], []
-, [], [[24, 24, [3, 6; 5, 9; 229, 12]], [], [], [24, 24, [3, 6; 5, 9; 229, 1
-2]]], [[]], [[], []], [], [[18, 18, [19, 6; 229, 9]], [18, 18, [19, 6; 229, 
-9]]], [[], []], [], [], [], [], [[], [24, 24, [5, 12; 229, 12]], []], [], [[
-], [], [], []], [], [], [], [], [], [[], [12, 12, [3, 3; 11, 3; 229, 6]], [1
-2, 12, [3, 3; 11, 3; 229, 6]], []], [], [], [[18, 18, [2, 12; 3, 12; 229, 9]
-], [], [18, 18, [2, 12; 3, 12; 229, 9]]], [[12, 12, [37, 3; 229, 6]], [12, 1
-2, [37, 3; 229, 6]]], [], [], [], [], [], [[], []], [[], []], [[], [], [], [
-], [], []], [], [], [[12, 12, [2, 12; 3, 3; 229, 6]], [12, 12, [2, 12; 3, 3;
- 229, 6]]], [[18, 18, [7, 12; 229, 9]]], [], [[], [], [], []], [], [[], []],
- [], [[], [24, 24, [5, 9; 11, 6; 229, 12]], [24, 24, [5, 9; 11, 6; 229, 12]]
-, []]]
-? discrayabslistlong(bnf,20)
-[[[[matrix(0,2,j,k,0), 6, 6, mat([229, 3])]], [], [[mat([12, 1]), 0, 0, 0], 
-[mat([13, 1]), 0, 0, 0]], [[mat([10, 1]), 0, 0, 0]], [[mat([20, 1]), 12, 12,
- [5, 3; 229, 6]], [mat([21, 1]), 12, 12, [5, 3; 229, 6]]], [], [], [], [[mat
-([12, 2]), 0, 0, 0], [[12, 1; 13, 1], 0, 0, 0], [mat([13, 2]), 0, 0, 0]], []
-, [[mat([44, 1]), 0, 0, 0], [mat([45, 1]), 0, 0, 0]], [[[10, 1; 12, 1], 0, 0
-, 0], [[10, 1; 13, 1], 0, 0, 0]], [], [], [[[12, 1; 20, 1], 24, 24, [3, 6; 5
-, 9; 229, 12]], [[13, 1; 20, 1], 0, 0, 0], [[12, 1; 21, 1], 0, 0, 0], [[13, 
-1; 21, 1], 24, 24, [3, 6; 5, 9; 229, 12]]], [[mat([10, 2]), 0, 0, 0]], [[mat
-([68, 1]), 0, 0, 0], [mat([69, 1]), 0, 0, 0]], [], [[mat([76, 1]), 18, 18, [
-19, 6; 229, 9]], [mat([77, 1]), 18, 18, [19, 6; 229, 9]]], [[[10, 1; 20, 1],
- 0, 0, 0], [[10, 1; 21, 1], 0, 0, 0]]]]
-? discrayrel(bnr,mat(6))
-[6, 2, [125, 13; 0, 1]]
-? discrayrel(bnr)
-[12, 1, [1953125, 1160888; 0, 1]]
-? discrayrelcond(bnr2)
-0
-? divisors(8!)
-[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 24, 28, 30, 32, 
-35, 36, 40, 42, 45, 48, 56, 60, 63, 64, 70, 72, 80, 84, 90, 96, 105, 112, 12
-0, 126, 128, 140, 144, 160, 168, 180, 192, 210, 224, 240, 252, 280, 288, 315
-, 320, 336, 360, 384, 420, 448, 480, 504, 560, 576, 630, 640, 672, 720, 840,
- 896, 960, 1008, 1120, 1152, 1260, 1344, 1440, 1680, 1920, 2016, 2240, 2520,
- 2688, 2880, 3360, 4032, 4480, 5040, 5760, 6720, 8064, 10080, 13440, 20160, 
-40320]
-? divres(345,123)
-[2, 99]~
-? divres(x^7-1,x^5+1)
-[x^2, -x^2 - 1]~
-? divsum(8!,x,x)
-159120
-? postdraw([0,0,0])
-? eigen([1,2,3;4,5,6;7,8,9])
-
-[1 -1.2833494518006402717978106547571267252 0.283349451800640271797810654757
-12672521]
-
-[-2 -0.14167472590032013589890532737856336261 0.6416747259003201358989053273
-7856336260]
-
-[1 1 1]
-
-? eint1(2)
-0.048900510708061119567239835228049522315
-? erfc(2)
-0.0046777349810472658379307436327470713891
-? eta(q)
-1 - q - q^2 + q^5 + q^7 - q^12 - q^15 + O(q^17)
-? euler
-0.57721566490153286060651209008240243104
-? z=y;y=x;eval(z)
-x
-? exp(1)
-2.7182818284590452353602874713526624978
-? extract([1,2,3,4,5,6,7,8,9,10],1000)
-[4, 6, 7, 8, 9, 10]
-? 10!
-3628800
-? fact(10)
-3628800.0000000000000000000000000000000
-? factcantor(x^11+1,7)
-
-[mod(1, 7)*x + mod(1, 7) 1]
-
-[mod(1, 7)*x^10 + mod(6, 7)*x^9 + mod(1, 7)*x^8 + mod(6, 7)*x^7 + mod(1, 7)*
-x^6 + mod(6, 7)*x^5 + mod(1, 7)*x^4 + mod(6, 7)*x^3 + mod(1, 7)*x^2 + mod(6,
- 7)*x + mod(1, 7) 1]
-
-? centerlift(lift(factfq(x^3+x^2+x-1,3,t^3+t^2+t-1)))
-
-[            x - t 1]
-
-[x + (t^2 + t - 1) 1]
-
-[   x + (-t^2 - 1) 1]
-
-? factmod(x^11+1,7)
-
-[mod(1, 7)*x + mod(1, 7) 1]
-
-[mod(1, 7)*x^10 + mod(6, 7)*x^9 + mod(1, 7)*x^8 + mod(6, 7)*x^7 + mod(1, 7)*
-x^6 + mod(6, 7)*x^5 + mod(1, 7)*x^4 + mod(6, 7)*x^3 + mod(1, 7)*x^2 + mod(6,
- 7)*x + mod(1, 7) 1]
-
-? factor(17!+1)
-
-[    661 1]
-
-[ 537913 1]
-
-[1000357 1]
-
-? p=x^5+3021*x^4-786303*x^3-6826636057*x^2-546603588746*x+3853890514072057
-x^5 + 3021*x^4 - 786303*x^3 - 6826636057*x^2 - 546603588746*x + 385389051407
-2057
-? fa=[11699,6;2392997,2;4987333019653,2]
-
-[        11699 6]
-
-[      2392997 2]
-
-[4987333019653 2]
-
-? factoredbasis(p,fa)
-[1, x, x^2, 1/11699*x^3 + 1847/11699*x^2 - 132/11699*x - 2641/11699, 1/13962
-3738889203638909659*x^4 - 1552451622081122020/139623738889203638909659*x^3 +
- 418509858130821123141/139623738889203638909659*x^2 - 6810913798507599407313
-4/139623738889203638909659*x - 13185339461968406/58346808996920447]
-? factoreddiscf(p,fa)
-136866601
-? factoredpolred(p,fa)
-[x - 1, x^5 - 80*x^3 - 223*x^2 + 800*x + 2671]
-? factoredpolred2(p,fa)
-[x - 1, x^5 - 80*x^3 - 223*x^2 + 800*x + 2671]
-? factornf(x^3+x^2-2*x-1,t^3+t^2-2*t-1)
-
-[         x + mod(-t, t^3 + t^2 - 2*t - 1) 1]
-
-[   x + mod(-t^2 + 2, t^3 + t^2 - 2*t - 1) 1]
-
-[x + mod(t^2 + t - 1, t^3 + t^2 - 2*t - 1) 1]
-
-? factorpadic(apol,7,8)
-
-[(1 + O(7^8))*x + (6 + 2*7^2 + 2*7^3 + 3*7^4 + 2*7^5 + 6*7^6 + O(7^8)) 1]
-
-[(1 + O(7^8))*x^2 + (1 + 6*7 + 4*7^2 + 4*7^3 + 3*7^4 + 4*7^5 + 6*7^7 + O(7^8
-))*x + (6 + 5*7 + 3*7^2 + 6*7^3 + 7^4 + 3*7^5 + 2*7^6 + 5*7^7 + O(7^8)) 1]
-
-? factorpadic2(apol,7,8)
-
-[(1 + O(7^8))*x + (6 + 2*7^2 + 2*7^3 + 3*7^4 + 2*7^5 + 6*7^6 + O(7^8)) 1]
-
-[(1 + O(7^8))*x^2 + (1 + 6*7 + 4*7^2 + 4*7^3 + 3*7^4 + 4*7^5 + 6*7^7 + O(7^8
-))*x + (6 + 5*7 + 3*7^2 + 6*7^3 + 7^4 + 3*7^5 + 2*7^6 + 5*7^7 + O(7^8)) 1]
-
-? factpol(x^15-1,3,1)
-
-[                              x - 1 1]
-
-[                        x^2 + x + 1 1]
-
-[            x^4 + x^3 + x^2 + x + 1 1]
-
-[x^8 - x^7 + x^5 - x^4 + x^3 - x + 1 1]
-
-? factpol(x^15-1,0,1)
-
-[                              x - 1 1]
-
-[                        x^2 + x + 1 1]
-
-[            x^4 + x^3 + x^2 + x + 1 1]
-
-[x^8 - x^7 + x^5 - x^4 + x^3 - x + 1 1]
-
-? fibo(100)
-354224848179261915075
-? floor(-1/2)
--1
-? floor(-2.5)
--3
-? for(x=1,5,print(x!))
-1
-2
-6
-24
-120
-? fordiv(10,x,print(x))
-1
-2
-5
-10
-? forprime(p=1,30,print(p))
-2
-3
-5
-7
-11
-13
-17
-19
-23
-29
-? forstep(x=0,pi,pi/12,print(sin(x)))
-0.E-38
-0.25881904510252076234889883762404832835
-0.50000000000000000000000000000000000000
-0.70710678118654752440084436210484903928
-0.86602540378443864676372317075293618347
-0.96592582628906828674974319972889736763
-1.0000000000000000000000000000000000000
-0.96592582628906828674974319972889736764
-0.86602540378443864676372317075293618348
-0.70710678118654752440084436210484903931
-0.50000000000000000000000000000000000003
-0.25881904510252076234889883762404832839
-4.701977403289150032 E-38
-? forvec(x=[[1,3],[-2,2]],print1([x[1],x[2]]," "));print(" ");
-[1, -2] [1, -1] [1, 0] [1, 1] [1, 2] [2, -2] [2, -1] [2, 0] [2, 1] [2, 2] [3
-, -2] [3, -1] [3, 0] [3, 1] [3, 2]  
-? frac(-2.7)
-0.30000000000000000000000000000000000000
-? galois(x^6-3*x^2-1)
-[12, 1, 1, "A_4(6) = [2^2]3"]
-? nf3=initalg(x^6+108);galoisconj(nf3)
-[-x, x, -1/12*x^4 - 1/2*x, -1/12*x^4 + 1/2*x, 1/12*x^4 - 1/2*x, 1/12*x^4 + 1
-/2*x]~
-? aut=%[2];galoisapply(nf3,aut,mod(x^5,x^6+108))
-mod(x^5, x^6 + 108)
-? gamh(10)
-1133278.3889487855673345741655888924756
-? gamma(10.5)
-1133278.3889487855673345741655888924756
-? gauss(hilbert(10),[1,2,3,4,5,6,7,8,9,0]~)
-[9236800, -831303990, 18288515520, -170691240720, 832112321040, -23298940665
-00, 3883123564320, -3803844432960, 2020775945760, -449057772020]~
-? gaussmodulo([2,3;5,4],[7,11]~,[1,4]~)
-[-5, -1]~
-? gaussmodulo2([2,3;5,4],[7,11]~,[1,4]~)
-[[-5, -1]~, [4, 9; -5, 8]]
-? gcd(12345678,87654321)
-9
-? getrand()
-Vecsmall([-696235626332558091, -7363039021536514678, -3123062006620239999, -
-2510915082749224356, -5278885121447018503, 8033304491650294704, 333461878925
-5801153, -4832266575436120673, 5861272496338969128, -5636745352271241140, -8
-607028155296715188, -2043539049048791177, -2842859901633655235, 690428093846
-572717, 6906280973824914900, 6398713593090797853, -1497282003360819453, 3975
-034254136078416, 1627271192805803924, 5189434097992515925, 92808575969012367
-5, -7043904930238153560, -8983157976956081156, -5952879933245555180, 2152499
-775656320938, 4269213403952002558, -8158273861213025959, 9081732703698285391
-, -968017538072501892, -1829026030745713069, -7068326569863156221, -33123451
-58404984065, 5646154901651443941, 8401460694091262829, 5443723805913372967, 
--6498478506213724335, -7440916561918862159, 6706000563295944300, 60772564257
-86072811, -6121231345839840470, -6231072835177963555, 581918341205122502, 39
-42269887095438680, 696327281251301999, -6893563203940457921, 200727759119899
-8199, 7105508585849937036, 5457053460371917318, -5526524089828180513, 703267
-9944660440486, 7855791284947948178, -8184369163059197809, 334420549169131260
-6, 2606551983777159860, 4711304445555935711, -1411378265676602388, 538367195
-0969683929, 1186259937007930248, -3095483643856126747, 7159506599077310177, 
--8545857881376569117, 8750587220496604824, -6606875118057441902, -8141165263
-118337473, 58, 8891599926458724970])
-? globalred(acurve)
-[37, [1, -1, 2, 2], 1, mat([37, 1]), [[1, 5, 0, 1]]]
-? hclassno(2000003)
-357
-? hell(acurve,apoint)
-0.81778253183950144377417759611107234575
-? hell2(acurve,apoint)
-0.81778253183950144377417759611107234597
-? hermite(amat=1/hilbert(7))
-
-[420   0    0    0   210  168   175]
-
-[  0 840    0    0     0    0   504]
-
-[  0   0 2520    0     0    0  1260]
-
-[  0   0    0 2520     0    0   840]
-
-[  0   0    0    0 13860    0  6930]
-
-[  0   0    0    0     0 5544     0]
-
-[  0   0    0    0     0    0 12012]
-
-? hermite2(amat)
-[[420, 0, 0, 0, 210, 168, 175; 0, 840, 0, 0, 0, 0, 504; 0, 0, 2520, 0, 0, 0,
- 1260; 0, 0, 0, 2520, 0, 0, 840; 0, 0, 0, 0, 13860, 0, 6930; 0, 0, 0, 0, 0, 
-5544, 0; 0, 0, 0, 0, 0, 0, 12012], [420, 420, 840, 630, 2982, 1092, 4159; 21
-0, 280, 630, 504, 2415, 876, 3395; 140, 210, 504, 420, 2050, 749, 2901; 105,
- 168, 420, 360, 1785, 658, 2542; 84, 140, 360, 315, 1582, 588, 2266; 70, 120
-, 315, 280, 1421, 532, 2046; 60, 105, 280, 252, 1290, 486, 1866]]
-? hermitemod(amat,detint(amat))
-
-[420   0    0    0   210  168   175]
-
-[  0 840    0    0     0    0   504]
-
-[  0   0 2520    0     0    0  1260]
-
-[  0   0    0 2520     0    0   840]
-
-[  0   0    0    0 13860    0  6930]
-
-[  0   0    0    0     0 5544     0]
-
-[  0   0    0    0     0    0 12012]
-
-? hermiteperm(amat)
-[[360360, 0, 0, 0, 0, 144144, 300300; 0, 27720, 0, 0, 0, 0, 22176; 0, 0, 277
-20, 0, 0, 0, 6930; 0, 0, 0, 2520, 0, 0, 840; 0, 0, 0, 0, 2520, 0, 1260; 0, 0
-, 0, 0, 0, 168, 0; 0, 0, 0, 0, 0, 0, 7], [51480, 4620, 5544, 630, 840, 20676
-, 48619; 45045, 3960, 4620, 504, 630, 18074, 42347; 40040, 3465, 3960, 420, 
-504, 16058, 37523; 36036, 3080, 3465, 360, 420, 14448, 33692; 32760, 2772, 3
-080, 315, 360, 13132, 30574; 30030, 2520, 2772, 280, 315, 12036, 27986; 2772
-0, 2310, 2520, 252, 280, 11109, 25803], Vecsmall([7, 6, 5, 4, 3, 2, 1])]
-? hess(hilbert(7))
-
-[1 90281/58800 -1919947/4344340 4858466341/1095033030 -77651417539/819678732
-6 3386888964/106615355 1/2]
-
-[1/3 43/48 38789/5585580 268214641/109503303 -581330123627/126464718744 4365
-450643/274153770 1/4]
-
-[0 217/2880 442223/7447440 53953931/292008808 -32242849453/168619624992 1475
-457901/1827691800 1/80]
-
-[0 0 1604444/264539275 24208141/149362505292 847880210129/47916076768560 -45
-44407141/103873817300 -29/40920]
-
-[0 0 0 9773092581/35395807550620 -24363634138919/107305824577186620 72118203
-606917/60481351061158500 55899/3088554700]
-
-[0 0 0 0 67201501179065/8543442888354179988 -9970556426629/74082861999267660
-0 -3229/13661312210]
-
-[0 0 0 0 0 -258198800769/9279048099409000 -13183/38381527800]
-
-? hilb(2/3,3/4,5)
-1
-? hilbert(5)
-
-[  1 1/2 1/3 1/4 1/5]
-
-[1/2 1/3 1/4 1/5 1/6]
-
-[1/3 1/4 1/5 1/6 1/7]
-
-[1/4 1/5 1/6 1/7 1/8]
-
-[1/5 1/6 1/7 1/8 1/9]
-
-? hilbp(mod(5,7),mod(6,7))
-1
-? hvector(10,x,1/x)
-[1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10]
-? hyperu(1,1,1)
-0.59634736232319407434107849936927937607
-? i^2
--1
-? initalgred(nfpol)
-[x^5 - 2*x^4 + 3*x^3 + 8*x^2 + 3*x + 2, [1, 2], 595125, 4, [[1, -1.089115145
-7205048250249527946671612684, -2.4285174907194186068992069565359418365, 0.71
-946691128913178943997506477288225735, -2.55582003506916949506460711594267799
-71; 1, -0.13838372073406036365047976417441696637 + 0.49181637657768643499753
-285514741525107*I, 1.9647119211288133163138753392090569931 - 0.8097149241889
-7895128294082219556466857*I, -0.072312766896812300380582649294307897123 - 2.
-1980803753846276641195195160383234878*I, -0.98796319352507039803950539735452
-837195 - 1.5701452385894131769052374806001981109*I; 1, 1.6829412935943127761
-629561615079976006 + 2.0500351226010726172974286983598602164*I, -0.750453175
-76910401286427186094108607490 + 1.3101462685358123283560773619310445915*I, -
-0.78742068874775359433940488309213323160 + 2.1336633893126618034168454610457
-936016*I, 1.2658732110596551455718089553258673704 - 2.7164790103743150566578
-028035789834836*I], [1, -1.0891151457205048250249527946671612684, -2.4285174
-907194186068992069565359418365, 0.71946691128913178943997506477288225735, -2
-.5558200350691694950646071159426779971; 1, 0.3534326558436260713470530909729
-9828470, 1.1549969969398343650309345170134923246, -2.27039314228143996450010
-21653326313849, -2.5581084321144835749447428779547264828; 1, -0.630200097311
-74679864801261932183221744, 2.7744268453177922675968161614046216617, 2.12576
-76084878153637389368667440155906, 0.58218204506434277886573208324566973893; 
-1, 3.7329764161953853934603848598678578170, 0.559693092766708315491805500989
-95851657, 1.3462427005649082090774405779536603700, -1.4506057993146599110859
-938482531161132; 1, -0.36709382900675984113447253685186261580, -2.0605994443
-049163412203492228721306664, -2.9210840780604153977562503441379268332, 3.982
-3522214339702022296117589048508541], [1, -1, -2, 1, -3; 1, 0, 1, -2, -3; 1, 
--1, 3, 2, 1; 1, 4, 1, 1, -1; 1, 0, -2, -3, 4], [5, 2, 0, -1, -2; 2, -2, -5, 
--10, 20; 0, -5, 10, -10, 5; -1, -10, -10, -17, 1; -2, 20, 5, 1, -8], [345, 0
-, 200, 110, 177; 0, 345, 95, 1, 145; 0, 0, 5, 4, 3; 0, 0, 0, 1, 0; 0, 0, 0, 
-0, 1], [63, 3, 0, -6, -9; 3, 8, -5, -1, 16; 0, -5, 22, -10, 0; -6, -1, -10, 
--14, -9; -9, 16, 0, -9, -2], [345, [138, 117, 330, 288, -636; -172, -88, 65,
- 118, -116; 53, 1, 138, -173, 65; 1, -172, 54, 191, 106; 0, 118, 173, 225, -
-34]], [3, 5, 23]], [-1.0891151457205048250249527946671612684, -0.13838372073
-406036365047976417441696637 + 0.49181637657768643499753285514741525107*I, 1.
-6829412935943127761629561615079976006 + 2.0500351226010726172974286983598602
-164*I], [1, x, -1/2*x^4 + 3/2*x^3 - 5/2*x^2 - 2*x + 1, -1/2*x^4 + x^3 - x^2 
-- 9/2*x - 1, -1/2*x^4 + x^3 - 2*x^2 - 7/2*x - 2], [1, 0, -1, -7, -14; 0, 1, 
-1, -2, -15; 0, 0, 0, 2, 4; 0, 0, 1, 1, -2; 0, 0, -1, -3, -4], [1, 0, 0, 0, 0
-, 0, -1, -1, -2, 4, 0, -1, 3, -1, 1, 0, -2, -1, -3, -1, 0, 4, 1, -1, -1; 0, 
-1, 0, 0, 0, 1, 1, -1, -1, 1, 0, -1, -2, -1, 1, 0, -1, -1, -1, 3, 0, 1, 1, 3,
- -3; 0, 0, 1, 0, 0, 0, 0, 0, 1, -1, 1, 0, 0, 0, -2, 0, 1, 0, -1, -1, 0, -1, 
--2, -1, -1; 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 2, 1, 0, 1, 0, 0, 0, 0
-, 2, 0, -1; 0, 0, 0, 0, 1, 0, -1, -1, -1, 1, 0, -1, 0, 1, 0, 0, -1, 1, 0, 0,
- 1, 1, 0, 0, -1]]
-? initalgred2(nfpol)
-[[x^5 - 2*x^4 + 3*x^3 + 8*x^2 + 3*x + 2, [1, 2], 595125, 4, [[1, -1.08911514
-57205048250249527946671612684, -2.4285174907194186068992069565359418365, 0.7
-1946691128913178943997506477288225735, -2.5558200350691694950646071159426779
-971; 1, -0.13838372073406036365047976417441696637 + 0.4918163765776864349975
-3285514741525107*I, 1.9647119211288133163138753392090569931 - 0.809714924188
-97895128294082219556466857*I, -0.072312766896812300380582649294307897123 - 2
-.1980803753846276641195195160383234878*I, -0.9879631935250703980395053973545
-2837195 - 1.5701452385894131769052374806001981109*I; 1, 1.682941293594312776
-1629561615079976006 + 2.0500351226010726172974286983598602164*I, -0.75045317
-576910401286427186094108607490 + 1.3101462685358123283560773619310445915*I, 
--0.78742068874775359433940488309213323160 + 2.133663389312661803416845461045
-7936016*I, 1.2658732110596551455718089553258673704 - 2.716479010374315056657
-8028035789834836*I], [1, -1.0891151457205048250249527946671612684, -2.428517
-4907194186068992069565359418365, 0.71946691128913178943997506477288225735, -
-2.5558200350691694950646071159426779971; 1, 0.353432655843626071347053090972
-99828470, 1.1549969969398343650309345170134923246, -2.2703931422814399645001
-021653326313849, -2.5581084321144835749447428779547264828; 1, -0.63020009731
-174679864801261932183221744, 2.7744268453177922675968161614046216617, 2.1257
-676084878153637389368667440155906, 0.58218204506434277886573208324566973893;
- 1, 3.7329764161953853934603848598678578170, 0.55969309276670831549180550098
-995851657, 1.3462427005649082090774405779536603700, -1.450605799314659911085
-9938482531161132; 1, -0.36709382900675984113447253685186261580, -2.060599444
-3049163412203492228721306664, -2.9210840780604153977562503441379268332, 3.98
-23522214339702022296117589048508541], [1, -1, -2, 1, -3; 1, 0, 1, -2, -3; 1,
- -1, 3, 2, 1; 1, 4, 1, 1, -1; 1, 0, -2, -3, 4], [5, 2, 0, -1, -2; 2, -2, -5,
- -10, 20; 0, -5, 10, -10, 5; -1, -10, -10, -17, 1; -2, 20, 5, 1, -8], [345, 
-0, 200, 110, 177; 0, 345, 95, 1, 145; 0, 0, 5, 4, 3; 0, 0, 0, 1, 0; 0, 0, 0,
- 0, 1], [63, 3, 0, -6, -9; 3, 8, -5, -1, 16; 0, -5, 22, -10, 0; -6, -1, -10,
- -14, -9; -9, 16, 0, -9, -2], [345, [138, 117, 330, 288, -636; -172, -88, 65
-, 118, -116; 53, 1, 138, -173, 65; 1, -172, 54, 191, 106; 0, 118, 173, 225, 
--34]], [3, 5, 23]], [-1.0891151457205048250249527946671612684, -0.1383837207
-3406036365047976417441696637 + 0.49181637657768643499753285514741525107*I, 1
-.6829412935943127761629561615079976006 + 2.050035122601072617297428698359860
-2164*I], [1, x, -1/2*x^4 + 3/2*x^3 - 5/2*x^2 - 2*x + 1, -1/2*x^4 + x^3 - x^2
- - 9/2*x - 1, -1/2*x^4 + x^3 - 2*x^2 - 7/2*x - 2], [1, 0, -1, -7, -14; 0, 1,
- 1, -2, -15; 0, 0, 0, 2, 4; 0, 0, 1, 1, -2; 0, 0, -1, -3, -4], [1, 0, 0, 0, 
-0, 0, -1, -1, -2, 4, 0, -1, 3, -1, 1, 0, -2, -1, -3, -1, 0, 4, 1, -1, -1; 0,
- 1, 0, 0, 0, 1, 1, -1, -1, 1, 0, -1, -2, -1, 1, 0, -1, -1, -1, 3, 0, 1, 1, 3
-, -3; 0, 0, 1, 0, 0, 0, 0, 0, 1, -1, 1, 0, 0, 0, -2, 0, 1, 0, -1, -1, 0, -1,
- -2, -1, -1; 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 2, 1, 0, 1, 0, 0, 0, 
-0, 2, 0, -1; 0, 0, 0, 0, 1, 0, -1, -1, -1, 1, 0, -1, 0, 1, 0, 0, -1, 1, 0, 0
-, 1, 1, 0, 0, -1]], mod(-1/2*x^4 + 3/2*x^3 - 5/2*x^2 - 2*x + 1, x^5 - 2*x^4 
-+ 3*x^3 + 8*x^2 + 3*x + 2)]
-? vp=primedec(nf,3)[1]
-[3, [1, 0, 1, 0, 0]~, 1, 1, [1, 4, -1, 6, -4; -1, 2, 4, 3, -5; -1, -1, 1, 0,
- 4; -1, -1, -2, 0, -2; 0, 3, 0, 0, 0]]
-? idx=idealmul(nf,idmat(5),vp)
-
-[3 2 1 0 1]
-
-[0 1 0 0 0]
-
-[0 0 1 0 0]
-
-[0 0 0 1 0]
-
-[0 0 0 0 1]
-
-? idy=ideallllred(nf,idx,[1,5,6])
-
-[5 0 0 0 2]
-
-[0 5 0 0 2]
-
-[0 0 5 0 1]
-
-[0 0 0 5 2]
-
-[0 0 0 0 1]
-
-? idealadd(nf,idx,idy)
-
-[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]
-
-? idealaddone(nf,idx,idy)
-[[0, -1, -3, -1, 2]~, [1, 1, 3, 1, -2]~]
-? idealaddmultone(nf,[idy,idx])
-[[-5, 0, 0, 0, 0]~, [6, 0, 0, 0, 0]~]
-? idealappr(nf,idy)
-[-1, 4, 2, -1, -3]~
-? idealapprfact(nf,idealfactor(nf,idy))
-[-1, 4, 2, -1, -3]~
-? idealcoprime(nf,idx,idx)
-[-1/3, 1/3, 1/3, 1/3, 0]~
-? idz=idealintersect(nf,idx,idy)
-
-[15 10 5 0 12]
-
-[ 0  5 0 0  2]
-
-[ 0  0 5 0  1]
-
-[ 0  0 0 5  2]
-
-[ 0  0 0 0  1]
-
-? idealfactor(nf,idz)
-
-[[3, [1, 0, 1, 0, 0]~, 1, 1, [1, 4, -1, 6, -4; -1, 2, 4, 3, -5; -1, -1, 1, 0
-, 4; -1, -1, -2, 0, -2; 0, 3, 0, 0, 0]] 1]
-
-[[5, [-1, 0, 0, 0, 2]~, 4, 1, [2, -3, 0, -12, 6; 2, 2, -5, -2, 6; 1, 1, 0, -
-1, -7; 2, 2, 5, 3, 1; 1, -4, 0, -1, 3]] 3]
-
-[[5, [2, 0, 0, 0, -2]~, 1, 1, [2, 1, 10, -4, 2; 0, 0, -5, 0, 0; 3, -1, 0, -1
-, -7; 0, 0, 5, 5, 5; 1, -2, 0, 3, 1]] 1]
-
-? ideallist(bnf,20)
-[[[1, 0; 0, 1]], [], [[3, 2; 0, 1], [3, 0; 0, 1]], [[2, 0; 0, 2]], [[5, 3; 0
-, 1], [5, 1; 0, 1]], [], [], [], [[9, 5; 0, 1], [3, 0; 0, 3], [9, 3; 0, 1]],
- [], [[11, 9; 0, 1], [11, 1; 0, 1]], [[6, 4; 0, 2], [6, 0; 0, 2]], [], [], [
-[15, 8; 0, 1], [15, 3; 0, 1], [15, 11; 0, 1], [15, 6; 0, 1]], [[4, 0; 0, 4]]
-, [[17, 14; 0, 1], [17, 2; 0, 1]], [], [[19, 18; 0, 1], [19, 0; 0, 1]], [[10
-, 6; 0, 2], [10, 2; 0, 2]]]
-? idx2=idealmul(nf,idx,idx)
-
-[9 5 7 0 4]
-
-[0 1 0 0 0]
-
-[0 0 1 0 0]
-
-[0 0 0 1 0]
-
-[0 0 0 0 1]
-
-? idt=idealmulred(nf,idx,idx)
-
-[2 0 0 0 0]
-
-[0 2 0 0 0]
-
-[0 0 2 0 0]
-
-[0 0 0 2 1]
-
-[0 0 0 0 1]
-
-? idealdiv(nf,idy,idt)
-
-[5   0 5/2   0   1]
-
-[0 5/2   0   0   1]
-
-[0   0 5/2   0 1/2]
-
-[0   0   0 5/2   1]
-
-[0   0   0   0 1/2]
-
-? idealdivexact(nf,idx2,idx)
-
-[3 2 1 0 1]
-
-[0 1 0 0 0]
-
-[0 0 1 0 0]
-
-[0 0 0 1 0]
-
-[0 0 0 0 1]
-
-? idealhermite(nf,vp)
-
-[3 2 1 0 1]
-
-[0 1 0 0 0]
-
-[0 0 1 0 0]
-
-[0 0 0 1 0]
-
-[0 0 0 0 1]
-
-? idealhermite2(nf,vp[2],3)
-
-[3 2 1 0 1]
-
-[0 1 0 0 0]
-
-[0 0 1 0 0]
-
-[0 0 0 1 0]
-
-[0 0 0 0 1]
-
-? idealnorm(nf,idt)
-16
-? idp=idealpow(nf,idx,7)
-
-[2187 1436 1807 630 1822]
-
-[   0    1    0   0    0]
-
-[   0    0    1   0    0]
-
-[   0    0    0   1    0]
-
-[   0    0    0   0    1]
-
-? idealpowred(nf,idx,7)
-
-[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]
-
-? idealtwoelt(nf,idy)
-[5, [2, 2, 1, 2, 1]~]
-? idealtwoelt2(nf,idy,10)
-[-1, 4, 2, 4, 2]~
-? idealval(nf,idp,vp)
-7
-? idmat(5)
-
-[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]
-
-? if(3<2,print("bof"),print("ok"));
-ok
-? imag(2+3*i)
-3
-? image([1,3,5;2,4,6;3,5,7])
-
-[1 3]
-
-[2 4]
-
-[3 5]
-
-? image(pi*[1,3,5;2,4,6;3,5,7])
-
-[3.1415926535897932384626433832795028842 9.424777960769379715387930149838508
-6526]
-
-[6.2831853071795864769252867665590057684 12.56637061435917295385057353311801
-1537]
-
-[9.4247779607693797153879301498385086526 15.70796326794896619231321691639751
-4421]
-
-? incgam(2,1)
-0.73575888234288464319104754032292173491
-? incgam3(2,1)
-0.26424111765711535680895245967707826509
-? incgam4(4,1,6)
-5.8860710587430771455283803225833738791
-? indexrank([1,1,1;1,1,1;1,1,2])
-[Vecsmall([1, 3]), Vecsmall([1, 3])]
-? indsort([8,7,6,5])
-Vecsmall([4, 3, 2, 1])
-? initell([0,0,0,-1,0])
-[0, 0, 0, -1, 0, 0, -2, 0, -1, 48, 0, 64, 1728, Vecsmall([1]), [Vecsmall([12
-8, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]
-? initrect(1,700,700)
-? nfz=initzeta(x^2-2);
-? integ(sin(x),x)
-1/2*x^2 - 1/24*x^4 + 1/720*x^6 - 1/40320*x^8 + 1/3628800*x^10 - 1/479001600*
-x^12 + 1/87178291200*x^14 - 1/20922789888000*x^16 + O(x^18)
-? integ((-x^2-2*a*x+8*a)/(x^4-14*x^3+(2*a+49)*x^2-14*a*x+a^2),x)
-(x + a)/(x^2 - 7*x + a)
-? intersect([1,2;3,4;5,6],[2,3;7,8;8,9])
-
-[-1]
-
-[-1]
-
-[-1]
-
-? \precision=19
-   realprecision = 19 significant digits
-? intgen(x=0,pi,sin(x))
-2.000000000000000018
-? sqr(2*intgen(x=0,4,exp(-x^2)))
-3.141592556720305686
-? 4*intinf(x=1,10^20,1/(1+x^2))
-3.141592653589793209
-? intnum(x=-0.5,0.5,1/sqrt(1-x^2))
-1.047197551196597746
-? 2*intopen(x=0,100,sin(x)/x)
-3.124450933778112629
-? \precision=38
-   realprecision = 38 significant digits
-? inverseimage([1,1;2,3;5,7],[2,2,6]~)
-[4, -2]~
-? isdiagonal([1,0,0;0,5,0;0,0,0])
-1
-? isfund(12345)
-1
-? isideal(bnf[7],[5,1;0,1])
-1
-? isincl(x^2+1,x^4+1)
-[-x^2, x^2]
-? isinclfast(initalg(x^2+1),initalg(x^4+1))
-[-x^2, x^2]
-? isirreducible(x^5+3*x^3+5*x^2+15)
-0
-? isisom(x^3+x^2-2*x-1,x^3+x^2-2*x-1)
-[x, -x^2 - x + 1, x^2 - 2]
-? isisomfast(initalg(x^3-2),initalg(x^3-6*x^2-6*x-30))
-[-1/25*x^2 + 13/25*x - 2/5]
-? isprime(12345678901234567)
-0
-? isprincipal(bnf,[5,1;0,1])
-[1]~
-? isprincipalgen(bnf,[5,1;0,1])
-[[1]~, [-2, -1/3]~]
-? isprincipalraygen(bnr,primedec(bnf,7)[1])
-[[9]~, [32879/6561, 13958/19683]~]
-? ispsp(73!+1)
-1
-? isqrt(10!^2+1)
-3628800
-? isset([-3,5,7,7])
-0
-? issqfree(123456789876543219)
-0
-? issquare(12345678987654321)
-1
-? isunit(bnf,mod(3405*x-27466,x^2-x-57))
-[-4, mod(1, 2)]~
-? jacobi(hilbert(6))
-[[1.0827994845655497685388772372251778091 E-7, 1.257075712262519492298239799
-6498755378 E-5, 0.00061574835418265769764919938428527140434, 0.0163215213198
-75822124345079564191505890, 0.24236087057520955213572841585070114077, 1.6188
-998589243390969705881471257800713]~, [-0.00124819408408217511693981630463878
-36342, 0.011144320930724710530678340374220998345, -0.06222658815019768177515
-2126611810492941, 0.24032536934252330399154228873240534569, -0.6145448282925
-8676899320019644273870646, 0.74871921887909485900280109200517845109; 0.03560
-6642944287635266122848131812051370, -0.1797327572407600375877689780374064077
-9, 0.49083920971092436297498316169060045043, -0.6976513752773701229620833504
-6678265583, 0.21108248167867048675227675845247769095, 0.44071750324351206127
-160083580231701802; -0.24067907958842295837736719558855680218, 0.60421220675
-295973004426567844103061740, -0.53547692162107486593474491750949545605, -0.2
-3138937333290388042251363554209048307, 0.36589360730302614149086554211117169
-623, 0.32069686982225190106359024326699463107; 0.625460386549227244577534410
-39459331707, -0.44357471627623954554460416705180104473, -0.41703769221897886
-840494514780771076351, 0.13286315850933553530333839628101576048, 0.394706776
-09501756783094636145991581709, 0.25431138634047419251788312792590944672; -0.
-68980719929383668419801738006926828754, -0.441536641012289662221436497529772
-04448, 0.047034018933115649705614518466541245344, 0.362714921464871475252994
-57604461742112, 0.38819043387388642863111448825992418974, 0.2115308400789652
-4664213667673977991960; 0.27160545336631286930015536176213646338, 0.45911481
-681642960284551392793050867151, 0.54068156310385293880022293448123781988, 0.
-50276286675751538489260566368647786274, 0.3706959077673628086177550108480739
-4603, 0.18144297664876947372217005457727093716]]
-? jbesselh(1,1)
-0.24029783912342701089584304474193368046
-? jell(i)
-1728.0000000000000000000000000000000000
-? kbessel(1+i,1)
-0.32545977186584141085464640324923711950 + 0.2894280370259921276345671592415
-2302743*I
-? kbessel2(1+i,1)
-0.32545977186584141085464640324923711950 + 0.2894280370259921276345671592415
-2302743*I
-? x
-x
-? y
-x
-? ker(matrix(4,4,x,y,x/y))
-
-[-1/2 -1/3 -1/4]
-
-[   1    0    0]
-
-[   0    1    0]
-
-[   0    0    1]
-
-? ker(matrix(4,4,x,y,sin(x+y)))
-
-[1.0000000000000000000000000000000000000 1.080604611736279434801873214885953
-2075]
-
-[-1.0806046117362794348018732148859532075 -0.1677063269057152260048635409984
-7562047]
-
-[1 0]
-
-[0 1]
-
-? keri(matrix(4,4,x,y,x+y))
-
-[ 1  2]
-
-[-2 -3]
-
-[ 1  0]
-
-[ 0  1]
-
-? kerint(matrix(4,4,x,y,x*y))
-
-[-1 -1 -1]
-
-[-1  0  1]
-
-[ 1 -1  1]
-
-[ 0  1 -1]
-
-? kerint1(matrix(4,4,x,y,x*y))
-
-[-1 -1 -1]
-
-[-1  0  1]
-
-[ 1 -1  1]
-
-[ 0  1 -1]
-
-? f(u)=u+1;
-? print(f(5));kill(f);
-6
-? f=12
-12
-? killrect(1)
-? kro(5,7)
--1
-? kro(3,18)
-0
-? laplace(x*exp(x*y)/(exp(x)-1))
-1 - 1/2*x + 13/6*x^2 - 3*x^3 + 419/30*x^4 - 30*x^5 + 6259/42*x^6 - 420*x^7 +
- 22133/10*x^8 - 7560*x^9 + 2775767/66*x^10 - 166320*x^11 + 2655339269/2730*x
-^12 - 4324320*x^13 + 264873251/10*x^14 - 129729600*x^15 + O(x^16)
-? lcm(15,-21)
-105
-? length(divisors(1000))
-16
-? legendre(10)
-46189/256*x^10 - 109395/256*x^8 + 45045/128*x^6 - 15015/128*x^4 + 3465/256*x
-^2 - 63/256
-? lex([1,3],[1,3,5])
--1
-? lexsort([[1,5],[2,4],[1,5,1],[1,4,2]])
-[[1, 4, 2], [1, 5], [1, 5, 1], [2, 4]]
-? lift(chinese(mod(7,15),mod(4,21)))
-67
-? lindep([(1-3*sqrt(2))/(3-2*sqrt(3)),1,sqrt(2),sqrt(3),sqrt(6)])
-[3, 3, -9, 2, -6]~
-? lindep2([(1-3*sqrt(2))/(3-2*sqrt(3)),1,sqrt(2),sqrt(3),sqrt(6)],14)
-[-3, -3, 9, -2, 6]~
-? move(0,0,900);line(0,900,0)
-? lines(0,vector(5,k,50*k),vector(5,k,10*k*k))
-? m=1/hilbert(7)
-
-[    49    -1176      8820    -29400      48510     -38808     12012]
-
-[ -1176    37632   -317520   1128960   -1940400    1596672   -504504]
-
-[  8820  -317520   2857680 -10584000   18711000  -15717240   5045040]
-
-[-29400  1128960 -10584000  40320000  -72765000   62092800 -20180160]
-
-[ 48510 -1940400  18711000 -72765000  133402500 -115259760  37837800]
-
-[-38808  1596672 -15717240  62092800 -115259760  100590336 -33297264]
-
-[ 12012  -504504   5045040 -20180160   37837800  -33297264  11099088]
-
-? mp=concat(m,idmat(7))
-
-[49 -1176 8820 -29400 48510 -38808 12012 1 0 0 0 0 0 0]
-
-[-1176 37632 -317520 1128960 -1940400 1596672 -504504 0 1 0 0 0 0 0]
-
-[8820 -317520 2857680 -10584000 18711000 -15717240 5045040 0 0 1 0 0 0 0]
-
-[-29400 1128960 -10584000 40320000 -72765000 62092800 -20180160 0 0 0 1 0 0 
-0]
-
-[48510 -1940400 18711000 -72765000 133402500 -115259760 37837800 0 0 0 0 1 0
- 0]
-
-[-38808 1596672 -15717240 62092800 -115259760 100590336 -33297264 0 0 0 0 0 
-1 0]
-
-[12012 -504504 5045040 -20180160 37837800 -33297264 11099088 0 0 0 0 0 0 1]
-
-? lll(m)
-
-[-420 -420 840 630 -1092 757 2982]
-
-[-210 -280 630 504  -876 700 2415]
-
-[-140 -210 504 420  -749 641 2050]
-
-[-105 -168 420 360  -658 589 1785]
-
-[ -84 -140 360 315  -588 544 1582]
-
-[ -70 -120 315 280  -532 505 1421]
-
-[ -60 -105 280 252  -486 471 1290]
-
-? lllgram(m)
-
-[1 1 27 -27 69   0 141]
-
-[0 1  5 -23 35 -24  50]
-
-[0 1  4 -22 19 -24  24]
-
-[0 1  4 -21 11 -19  14]
-
-[0 1  4 -20  7 -14   9]
-
-[0 1  4 -19  5 -10   6]
-
-[0 1  4 -18  4  -7   4]
-
-? lllgramint(m)
-
-[1 1 27 -27 69   0 141]
-
-[0 1  5 -23 35 -24  50]
-
-[0 1  4 -22 19 -24  24]
-
-[0 1  4 -21 11 -19  14]
-
-[0 1  4 -20  7 -14   9]
-
-[0 1  4 -19  5 -10   6]
-
-[0 1  4 -18  4  -7   4]
-
-? lllgramkerim(mp~*mp)
-[[-420, -420, 840, 630, 2982, -1092, 757; -210, -280, 630, 504, 2415, -876, 
-700; -140, -210, 504, 420, 2050, -749, 641; -105, -168, 420, 360, 1785, -658
-, 589; -84, -140, 360, 315, 1582, -588, 544; -70, -120, 315, 280, 1421, -532
-, 505; -60, -105, 280, 252, 1290, -486, 471; 420, 0, 0, 0, -210, 168, 35; 0,
- 840, 0, 0, 0, 0, 336; 0, 0, -2520, 0, 0, 0, -1260; 0, 0, 0, -2520, 0, 0, -8
-40; 0, 0, 0, 0, -13860, 0, 6930; 0, 0, 0, 0, 0, 5544, 0; 0, 0, 0, 0, 0, 0, -
-12012], [0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0; 0, 0
-, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 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, 0, 0, 0; 0, 0, 0, 
-1, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 1]]
-? lllint(m)
-
-[-420 -420 840 630 -1092 757 2982]
-
-[-210 -280 630 504  -876 700 2415]
-
-[-140 -210 504 420  -749 641 2050]
-
-[-105 -168 420 360  -658 589 1785]
-
-[ -84 -140 360 315  -588 544 1582]
-
-[ -70 -120 315 280  -532 505 1421]
-
-[ -60 -105 280 252  -486 471 1290]
-
-? lllintpartial(m)
-
-[-420 -420 -630 840 1092 2982 -83]
-
-[-210 -280 -504 630  876 2415  70]
-
-[-140 -210 -420 504  749 2050 137]
-
-[-105 -168 -360 420  658 1785 169]
-
-[ -84 -140 -315 360  588 1582 184]
-
-[ -70 -120 -280 315  532 1421 190]
-
-[ -60 -105 -252 280  486 1290 191]
-
-? lllkerim(mp)
-[[-420, -420, 840, 630, 2982, -1092, 757; -210, -280, 630, 504, 2415, -876, 
-700; -140, -210, 504, 420, 2050, -749, 641; -105, -168, 420, 360, 1785, -658
-, 589; -84, -140, 360, 315, 1582, -588, 544; -70, -120, 315, 280, 1421, -532
-, 505; -60, -105, 280, 252, 1290, -486, 471; 420, 0, 0, 0, -210, 168, 35; 0,
- 840, 0, 0, 0, 0, 336; 0, 0, -2520, 0, 0, 0, -1260; 0, 0, 0, -2520, 0, 0, -8
-40; 0, 0, 0, 0, -13860, 0, 6930; 0, 0, 0, 0, 0, 5544, 0; 0, 0, 0, 0, 0, 0, -
-12012], [0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0; 0, 0
-, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 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, 0, 0, 0; 0, 0, 0, 
-1, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 1]]
-? \precision=96
-   realprecision = 96 significant digits
-? ln(2)
-0.69314718055994530941723212145817656807550013436025525412068000949339362196
-9694715605863326996419
-? lngamma(10^50*i)
--157079632679489661923132169163975144209858469968811.93673753887608474948977
-0941153418951907406848 + 114129254649702284200899572734218210380055074431438
-64.0947684761073895534327259165813042649761556*I
-? \precision=2000
-   realprecision = 2003 significant digits (2000 digits displayed)
-? log(2)
-0.69314718055994530941723212145817656807550013436025525412068000949339362196
-9694715605863326996418687542001481020570685733685520235758130557032670751635
-0759619307275708283714351903070386238916734711233501153644979552391204751726
-8157493206515552473413952588295045300709532636664265410423915781495204374043
-0385500801944170641671518644712839968171784546957026271631064546150257207402
-4816377733896385506952606683411372738737229289564935470257626520988596932019
-6505855476470330679365443254763274495125040606943814710468994650622016772042
-4524529612687946546193165174681392672504103802546259656869144192871608293803
-1727143677826548775664850856740776484514644399404614226031930967354025744460
-7030809608504748663852313818167675143866747664789088143714198549423151997354
-8803751658612753529166100071053558249879414729509293113897155998205654392871
-7000721808576102523688921324497138932037843935308877482597017155910708823683
-6275898425891853530243634214367061189236789192372314672321720534016492568727
-4778234453534764811494186423867767744060695626573796008670762571991847340226
-5146283790488306203306114463007371948900274364396500258093651944304119115060
-8094879306786515887090060520346842973619384128965255653968602219412292420757
-4321757489097706752687115817051137009158942665478595964890653058460258668382
-9400228330053820740056770530467870018416240441883323279838634900156312188956
-0650553151272199398332030751408426091479001265168243443893572472788205486271
-5527418772430024897945401961872339808608316648114909306675193393128904316413
-7068139777649817697486890388778999129650361927071088926410523092478391737350
-1229842420499568935992206602204654941510613918788574424557751020683703086661
-9480896412186807790208181588580001688115973056186676199187395200766719214592
-2367206025395954365416553112951759899400560003665135675690512459268257439464
-8316833262490180382424082423145230614096380570070255138770268178516306902551
-3703234053802145019015374029509942262995779647427138157363801729873940704242
-17997226696297993931270694
-? logagm(2)
-0.69314718055994530941723212145817656807550013436025525412068000949339362196
-9694715605863326996418687542001481020570685733685520235758130557032670751635
-0759619307275708283714351903070386238916734711233501153644979552391204751726
-8157493206515552473413952588295045300709532636664265410423915781495204374043
-0385500801944170641671518644712839968171784546957026271631064546150257207402
-4816377733896385506952606683411372738737229289564935470257626520988596932019
-6505855476470330679365443254763274495125040606943814710468994650622016772042
-4524529612687946546193165174681392672504103802546259656869144192871608293803
-1727143677826548775664850856740776484514644399404614226031930967354025744460
-7030809608504748663852313818167675143866747664789088143714198549423151997354
-8803751658612753529166100071053558249879414729509293113897155998205654392871
-7000721808576102523688921324497138932037843935308877482597017155910708823683
-6275898425891853530243634214367061189236789192372314672321720534016492568727
-4778234453534764811494186423867767744060695626573796008670762571991847340226
-5146283790488306203306114463007371948900274364396500258093651944304119115060
-8094879306786515887090060520346842973619384128965255653968602219412292420757
-4321757489097706752687115817051137009158942665478595964890653058460258668382
-9400228330053820740056770530467870018416240441883323279838634900156312188956
-0650553151272199398332030751408426091479001265168243443893572472788205486271
-5527418772430024897945401961872339808608316648114909306675193393128904316413
-7068139777649817697486890388778999129650361927071088926410523092478391737350
-1229842420499568935992206602204654941510613918788574424557751020683703086661
-9480896412186807790208181588580001688115973056186676199187395200766719214592
-2367206025395954365416553112951759899400560003665135675690512459268257439464
-8316833262490180382424082423145230614096380570070255138770268178516306902551
-3703234053802145019015374029509942262995779647427138157363801729873940704242
-17997226696297993931270694
-? \precision=19
-   realprecision = 19 significant digits
-? bcurve=initell([0,0,0,-3,0])
-[0, 0, 0, -3, 0, 0, -6, 0, -9, 144, 0, 1728, 1728, Vecsmall([1]), [Vecsmall(
-[64, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]
-? localred(bcurve,2)
-[6, 2, [1, 1, 1, 0], 1]
-? ccurve=initell([0,0,-1,-1,0])
-[0, 0, -1, -1, 0, 0, -2, 1, -1, 48, -216, 37, 110592/37, Vecsmall([1]), [Vec
-small([64, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]
-? l=lseriesell(ccurve,2,-37,1)
-0.3815754082607112109
-? lseriesell(ccurve,2,-37,1.2)-l
--8.131516293641283255 E-20
-? sbnf=smallbuchinit(x^3-x^2-14*x-1)
-[x^3 - x^2 - 14*x - 1, 3, 10889, [1, x, x^2 - x - 9], [-3.233732695981516673
-, -0.07182350902743636345, 4.305556205008953036], 0, mat(2), mat([1, 1, 0, 1
-, 0, 1]), [9, 15, 16, 17, 39, 33, 10], [2, -1], [[0, 1, 0]~, [5, 3, 1]~], [[
-[4, -1, 0]~, [-1, 1, 0]~, [2, 1, 0]~, [3, 1, 0]~, [-10, -5, -1]~, [-1, -1, 0
-]~, [-3, 0, 0]~], 0]]
-? makebigbnf(sbnf)
-[mat(2), mat([1, 1, 0, 1, 0, 1]), [1.173637103435061715 + 3.1415926535897932
-38*I, -4.562279014988837902 + 3.141592653589793238*I; -2.633543432738976050 
-+ 3.141592653589793238*I, 1.420330600779487358 + 3.141592653589793238*I; 1.4
-59906329303914335, 3.141948414209350544], [1.246346989334819161, 0.540400637
-6129469728 + 3.141592653589793238*I, -0.6926391142471042845 + 3.141592653589
-793238*I, -1.990056445584799714 + 3.141592653589793238*I, -0.830562594660718
-8640, 0.004375616572659815402, 0; 0.6716827432867392936, -0.8333219883742404
-172 + 3.141592653589793238*I, -0.2461086674077943078, 0.5379005671092853267,
- -1.552661549868775854 + 3.141592653589793238*I, -0.8738318043071131265 + 3.
-141592653589793238*I, 0; -1.918029732621558455 + 3.141592653589793238*I, 0.2
-929213507612934444, 0.9387477816548985923, 1.452155878475514387, 2.383224144
-529494718 + 3.141592653589793238*I, 0.8694561877344533111 + 3.14159265358979
-3238*I, 0], [[3, [-1, 1, 0]~, 1, 1, [1, 10, 45; 1, 7, 6; 1, 1, -3]], [5, [-1
-, 1, 0]~, 1, 1, [0, 10, 45; 1, 6, 6; 1, 1, -4]], [5, [2, 1, 0]~, 1, 1, [1, -
-17, 42; -2, 4, -9; 1, -2, -3]], [5, [3, 1, 0]~, 1, 1, [2, 19, 46; 2, 9, 11; 
-1, 2, -2]], [13, [19, 1, 0]~, 1, 1, [-2, -53, 38; -6, -3, -29; 1, -6, -6]], 
-[11, [1, 1, 0]~, 1, 1, [-3, -8, 43; -1, 1, -4; 1, -1, -7]], [3, [10, 1, 1]~,
- 1, 2, [-1, 9, 1; 1, 0, 5; 0, 1, -1]]]~, 0, [x^3 - x^2 - 14*x - 1, [3, 0], 1
-0889, 1, [[1, -3.233732695981516673, 4.690759845041404812; 1, -0.07182350902
-743636345, -8.923017874523549404; 1, 4.305556205008953036, 5.232258029482144
-592], [1, -3.233732695981516673, 4.690759845041404812; 1, -0.071823509027436
-36345, -8.923017874523549404; 1, 4.305556205008953036, 5.232258029482144592]
-, [1, -3, 5; 1, 0, -9; 1, 4, 5], [3, 1, 1; 1, 29, 8; 1, 8, 129], [10889, 569
-8, 8994; 0, 1, 0; 0, 0, 1], [3677, -121, -21; -121, 386, -23; -21, -23, 86],
- [10889, [1899, 46720, 5235; 5191, 7095, 25956; 1, 5191, 1895]], []], [-3.23
-3732695981516673, -0.07182350902743636345, 4.305556205008953036], [1, x, x^2
- - x - 9], [1, 0, 9; 0, 1, 1; 0, 0, 1], [1, 0, 0, 0, 9, 1, 0, 1, 44; 0, 1, 0
-, 1, 1, 5, 0, 5, 1; 0, 0, 1, 0, 1, 0, 1, 0, -4]], [[2, [2], [[3, 2, 0; 0, 1,
- 0; 0, 0, 1]]], 10.34800724602767998, 1, [2, -1], [x, x^2 + 2*x - 4]], [mat(
-1), [[0, 0, 0]], [[1.246346989334819161, 0.6716827432867392936, -1.918029732
-621558455 + 3.141592653589793238*I]]], [[[4, -1, 0]~, [-1, 1, 0]~, [2, 1, 0]
-~, [3, 1, 0]~, [-10, -5, -1]~, [-1, -1, 0]~, [-3, 0, 0]~], 0]]
-? concat(mat(vector(4,x,x)~),vector(4,x,10+x)~)
-
-[1 11]
-
-[2 12]
-
-[3 13]
-
-[4 14]
-
-? matextract(matrix(15,15,x,y,x+y),vector(5,x,3*x),vector(3,y,3*y))
-
-[ 6  9 12]
-
-[ 9 12 15]
-
-[12 15 18]
-
-[15 18 21]
-
-[18 21 24]
-
-? ma=mathell(mcurve,mpoints)
-
-[ 1.172183098700697011 0.4476973883408951692]
-
-[0.4476973883408951692  1.755026016172950714]
-
-? gauss(ma,mhbi)
-[-0.9999999999999999999, 0.9999999999999999999]~
-? (1.*hilbert(7))^(-1)
-
-[49.00000000002167189 -1176.000000000824159 8820.000000007689380 -29400.0000
-0002921115 48510.00000005262155 -38808.00000004484400 12012.00000001456215]
-
-[-1176.000000000829440 37632.00000003144616 -317520.0000002927650 1128960.00
-0001110352 -1940400.000001997563 1596672.000001700589 -504504.0000005516749]
-
-[8820.000000007770381 -317520.0000002939542 2857680.000002732420 -10584000.0
-0001035058 18711000.00001860328 -15717240.00001582519 5045040.000005130356]
-
-[-29400.00000002960234 1128960.000001118000 -10584000.00001037971 40320000.0
-0003928254 -72765000.00007055130 62092800.00005997937 -20180160.00001943491]
-
-[48510.00000005343676 -1940400.000002015506 18711000.00001869438 -72765000.0
-0007069760 133402500.0001268981 -115259760.0001078308 37837800.00003492601]
-
-[-38808.00000004561365 1596672.000001718594 -15717240.00001592797 62092800.0
-0006019943 -115259760.0001080025 100590336.0000917382 -33297264.00002970394]
-
-[12012.00000001482901 -504504.0000005582180 5045040.000005170209 -20180160.0
-0001953088 37837800.00003502588 -33297264.00002974149 11099088.00000962736]
-
-? matsize([1,2;3,4;5,6])
-[3, 2]
-? matrix(5,5,x,y,gcd(x,y))
-
-[1 1 1 1 1]
-
-[1 2 1 2 1]
-
-[1 1 3 1 1]
-
-[1 2 1 4 1]
-
-[1 1 1 1 5]
-
-? matrixqz([1,3;3,5;5,7],0)
-
-[1 1]
-
-[3 2]
-
-[5 3]
-
-? matrixqz2([1/3,1/4,1/6;1/2,1/4,-1/4;1/3,1,0])
-
-[19 12 2]
-
-[ 0  1 0]
-
-[ 0  0 1]
-
-? matrixqz3([1,3;3,5;5,7])
-
-[2 -1]
-
-[1  0]
-
-[0  1]
-
-? max(2,3)
-3
-? min(2,3)
-2
-? minim([2,1;1,2],4,6)
-[6, 2, [0, -1, 1; 1, 1, 0]]
-? mod(-12,7)
-mod(2, 7)
-? modp(-12,7)
-mod(2, 7)
-? mod(10873,49649)^-1
-  ***   at top-level: mod(10873,49649)^-1
-  ***                                 ^---
-  *** _^_: impossible inverse in Fp_inv: mod(131, 49649).
-? modreverse(mod(x^2+1,x^3-x-1))
-mod(x^2 - 3*x + 2, x^3 - 5*x^2 + 8*x - 5)
-? move(0,243,583);cursor(0)
-? mu(3*5*7*11*13)
--1
-? newtonpoly(x^4+3*x^3+27*x^2+9*x+81,3)
-[2, 2/3, 2/3, 2/3]
-? nextprime(100000000000000000000000)
-100000000000000000000117
-? setrand(1);n=10^8;a=matrix(3,5,j,k,vvector(5,l,random()\n))
-
-[[15, 8, 17, 7, 12]~ [1, 4, 10, 6, 4]~ [1, 12, 9, 11, 11]~ [5, 0, 12, 21, 7]
-~ [18, 12, 18, 3, 8]~]
-
-[[16, 15, 20, 18, 14]~ [0, 3, 21, 15, 8]~ [10, 0, 18, 0, 7]~ [11, 18, 15, 7,
- 20]~ [13, 2, 0, 4, 4]~]
-
-[[11, 11, 12, 7, 2]~ [9, 20, 11, 7, 16]~ [0, 12, 3, 12, 2]~ [0, 20, 20, 17, 
-5]~ [5, 11, 14, 7, 0]~]
-
-? aid=[idx,idy,idz,idmat(5),idx]
-[[3, 2, 1, 0, 1; 0, 1, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1]
-, [5, 0, 0, 0, 2; 0, 5, 0, 0, 2; 0, 0, 5, 0, 1; 0, 0, 0, 5, 2; 0, 0, 0, 0, 1
-], [15, 10, 5, 0, 12; 0, 5, 0, 0, 2; 0, 0, 5, 0, 1; 0, 0, 0, 5, 2; 0, 0, 0, 
-0, 1], [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], [3, 2, 1, 0, 1; 0, 1, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0, 0, 0
-, 0, 1]]
-? bb=algtobasis(nf,mod(x^3+x,nfpol))
-[1, 1, 4, 1, 3]~
-? da=nfdetint(nf,[a,aid])
-
-[15 10 5 0 12]
-
-[ 0  5 0 0  2]
-
-[ 0  0 5 0  1]
-
-[ 0  0 0 5  2]
-
-[ 0  0 0 0  1]
-
-? nfdiv(nf,ba,bb)
-[584/373, 66/373, -32/373, -105/373, 120/373]~
-? nfdiveuc(nf,ba,bb)
-[2, 0, 0, 0, 0]~
-? nfdivres(nf,ba,bb)
-[[2, 0, 0, 0, 0]~, [4, -1, -5, -1, -3]~]
-? nfhermite(nf,[a,aid])
-[[1, 1, 4; 0, 1, 0; 0, 0, 1], [[15, 2, 10, 12, 4; 0, 1, 0, 0, 0; 0, 0, 1, 0,
- 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], 1, 1]]
-? nfhermitemod(nf,[a,aid],da)
-[[1, 1, 4; 0, 1, 0; 0, 0, 1], [[15, 2, 10, 12, 4; 0, 1, 0, 0, 0; 0, 0, 1, 0,
- 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], 1, 1]]
-? nfmod(nf,ba,bb)
-[4, -1, -5, -1, -3]~
-? nfmul(nf,ba,bb)
-[50, -15, -35, 60, 15]~
-? nfpow(nf,bb,5)
-[-291920, 136855, 230560, -178520, 74190]~
-? nfreduce(nf,ba,idx)
-[1, 0, 0, 0, 0]~
-? nfsmith(nf,[a[,1..3],[1,1,1],[idealinv(nf,idx),idealinv(nf,idy),1]])
-[[15706993357777254170417850, 1636878763571210697462070, 1307908830618593502
-9427775, 1815705333955314515809980, 7581330311082212790621785; 0, 5, 0, 0, 0
-; 0, 0, 5, 0, 0; 0, 0, 0, 5, 0; 0, 0, 0, 0, 5], [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], [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]]
-? nfval(nf,ba,vp)
-0
-? norm(1+i)
-2
-? norm(mod(x+5,x^3+x+1))
-129
-? norml2(vector(10,x,x))
-385
-? nucomp(qfi(2,1,9),qfi(4,3,5),3)
-qfi(2, -1, 9)
-? form=qfi(2,1,9);nucomp(form,form,3)
-qfi(4, -3, 5)
-? numdiv(2^99*3^49)
-5000
-? numer((x+1)/(x-1))
-x + 1
-? nupow(form,111)
-qfi(2, -1, 9)
-? 1/(1+x)+o(x^20)
-1 - x + x^2 - x^3 + x^4 - x^5 + x^6 - x^7 + x^8 - x^9 + x^10 - x^11 + x^12 -
- x^13 + x^14 - x^15 + x^16 - x^17 + x^18 - x^19 + O(x^20)
-? omega(100!)
-25
-? ordell(acurve,1)
-[8, 3]
-? order(mod(33,2^16+1))
-2048
-? tcurve=initell([1,0,1,-19,26]);
-? orderell(tcurve,[1,2])
-6
-? ordred(x^3-12*x+45*x-1)
-[x - 1, x^3 + 33*x - 1]
-? padicprec(padicno,127)
-5
-? pascal(8)
-
-[1 0  0  0  0  0  0 0 0]
-
-[1 1  0  0  0  0  0 0 0]
-
-[1 2  1  0  0  0  0 0 0]
-
-[1 3  3  1  0  0  0 0 0]
-
-[1 4  6  4  1  0  0 0 0]
-
-[1 5 10 10  5  1  0 0 0]
-
-[1 6 15 20 15  6  1 0 0]
-
-[1 7 21 35 35 21  7 1 0]
-
-[1 8 28 56 70 56 28 8 1]
-
-? perf([2,0,1;0,2,1;1,1,2])
-6
-? permutation(7,1035)
-[2, 4, 6, 1, 5, 7, 3]
-? permutation2num([4,7,1,6,3,5,2])
-2781
-? pf(-44,3)
-qfi(3, 2, 4)
-? phi(257^2)
-65792
-? pi
-3.141592653589793239
-? b=10;a=1<<b;plot(x=-5,5,round(sin(x)<<b)/a)
-
-        1 x""x_''''''''''''''''''''''''''''''''''_x""x'''''''''''''''''''|
-          |    x                                _     "_                 |
-          |     x                              _        _                |
-          |      x                            _                          |
-          |       _                                      "               |
-          |                                  "            x              |
-          |        x                        _                            |
-          |                                                "             |
-          |         "                      x                _            |
-          |          _                                                   |
-          |                               "                  x           |
-          ````````````x``````````````````_````````````````````````````````
-          |                                                   "          |
-          |            "                x                      _         |
-          |             _                                                |
-          |                            "                        x        |
-          |              x            _                                  |
-          |               _                                      "       |
-          |                          "                            x      |
-          |                "        "                              x     |
-          |                 "_     "                                x    |
-       -1 |...................x__x".................................."x__x
-          -5                                                             5
-? pnqn([2,6,10,14,18,22,26])
-
-[19318376 741721]
-
-[ 8927353 342762]
-
-? pnqn([1,1,1,1,1,1,1,1;1,1,1,1,1,1,1,1])
-
-[34 21]
-
-[21 13]
-
-? point(0,225,334)
-? points(0,vector(10,k,10*k),vector(10,k,5*k*k))
-? pointell(acurve,zell(acurve,apoint))
-[1.000000000000000000, 3.000000000000000000]
-? polint([0,2,3],[0,4,9],5)
-25
-? polred(x^5-2*x^4-4*x^3-96*x^2-352*x-568)
-[x - 1, x^5 - x^4 + 2*x^3 - 4*x^2 + x - 1]
-? polred2(x^4-28*x^3-458*x^2+9156*x-25321)
-
-[                                                1           x - 1]
-
-[                   1/115*x^2 - 14/115*x - 212/115   x^2 - 2*x - 9]
-
-[                  -1/115*x^2 + 14/115*x + 442/115   x^2 - 2*x - 9]
-
-[                   1/115*x^2 - 14/115*x - 327/115        x^2 - 10]
-
-[1/4485*x^3 - 7/1495*x^2 - 1034/4485*x + 7924/4485 x^4 - 8*x^2 + 6]
-
-? polredabs(x^5-2*x^4-4*x^3-96*x^2-352*x-568)
-x^5 - x^4 + 2*x^3 - 4*x^2 + x - 1
-? polredabs2(x^5-2*x^4-4*x^3-96*x^2-352*x-568)
-[x^5 - x^4 + 2*x^3 - 4*x^2 + x - 1, mod(2*x^4 - x^3 + 3*x^2 - 3*x - 1, x^5 -
- x^4 + 2*x^3 - 4*x^2 + x - 1)]
-? polsym(x^17-1,17)
-[17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17]~
-? polvar(name^4-other)
-name
-? poly(sin(x),x)
--1/1307674368000*x^15 + 1/6227020800*x^13 - 1/39916800*x^11 + 1/362880*x^9 -
- 1/5040*x^7 + 1/120*x^5 - 1/6*x^3 + x
-? polylog(5,0.5)
-0.5084005792422687074
-? polylog(-4,t)
-(t^4 + 11*t^3 + 11*t^2 + t)/(-t^5 + 5*t^4 - 10*t^3 + 10*t^2 - 5*t + 1)
-? polylogd(5,0.5)
-1.033792745541689064
-? polylogdold(5,0.5)
-1.034459423449010486
-? polylogp(5,0.5)
-0.9495693489964922601
-? poly([1,2,3,4,5],x)
-x^4 + 2*x^3 + 3*x^2 + 4*x + 5
-? polyrev([1,2,3,4,5],x)
-5*x^4 + 4*x^3 + 3*x^2 + 2*x + 1
-? polzag(6,3)
-4608*x^6 - 13824*x^5 + 46144/3*x^4 - 23168/3*x^3 + 5032/3*x^2 - 120*x + 1
-? postdraw([0,20,20])
-? postploth(x=-5,5,sin(x))
-[-5.000000000000000000, 5.000000000000000000, -0.9999964107564721649, 0.9999
-964107564721649]
-? postploth2(t=0,2*pi,[sin(5*t),sin(7*t)])
-[-0.9999994509568810308, 0.9999994509568810308, -0.9999994509568810308, 0.99
-99994509568810308]
-? postplothraw(vector(100,k,k),vector(100,k,k*k/100))
-[1.000000000000000000, 100.0000000000000000, 0.01000000000000000021, 100.000
-0000000000000]
-? powell(acurve,apoint,10)
-[-28919032218753260057646013785951999/292736325329248127651484680640160000, 
-478051489392386968218136375373985436596569736643531551/158385319626308443937
-475969221994173751192384064000000]
-? cmcurve=initell([0,-3/4,0,-2,-1])
-[0, -3/4, 0, -2, -1, -3, -4, -4, -1, 105, 1323, -343, -3375, Vecsmall([1]), 
-[Vecsmall([64, -1])], [0, 0, 0, 0, 0, 0, 0, 0]]
-? powell(cmcurve,[x,y],quadgen(-7))
-[((-2 + 3*w)*x^2 + (6 - w))/((-2 - 5*w)*x + (-4 - 2*w)), ((34 - 11*w)*x^3 + 
-(40 - 28*w)*x^2 + (22 + 23*w)*x)/((-90 - w)*x^2 + (-136 + 44*w)*x + (-40 + 2
-8*w))]
-? powrealraw(qfr(5,3,-1,0.),3)
-qfr(125, 23, 1, 0.E-18)
-? pprint((x-12*y)/(y+13*x));
--11/14
-? pprint([1,2;3,4])
-[1, 2; 3, 4]
-? pprint1(x+y);pprint(x+y);
-2*x2*x
-? \precision=96
-   realprecision = 96 significant digits
-? pi
-3.14159265358979323846264338327950288419716939937510582097494459230781640628
-620899862803482534212
-? prec(pi,20)
-3.14159265358979323846264338327950288420
-? precision(cmcurve)
-38
-? \precision=38
-   realprecision = 38 significant digits
-? prime(100)
-541
-? primedec(nf,2)
-[[2, [3, 0, 1, 0, 0]~, 1, 1, [0, 2, 0, -4, -2; 0, 0, 0, 2, 0; 0, 0, -2, -2, 
--2; 1, 0, 3, 0, -1; 1, 0, 1, 0, -1]], [2, [12, -4, -2, 11, 3]~, 1, 4, [1, -1
-, 3, -1, 1; 0, 0, -2, -1, 1; 1, 0, 1, 0, -2; 0, 0, 1, 2, 2; 0, -1, 0, 1, 1]]
-]
-? primedec(nf,3)
-[[3, [1, 0, 1, 0, 0]~, 1, 1, [1, 4, -1, 6, -4; -1, 2, 4, 3, -5; -1, -1, 1, 0
-, 4; -1, -1, -2, 0, -2; 0, 3, 0, 0, 0]], [3, [1, 1, 1, 0, 0]~, 2, 2, [0, -6,
- 3, -9, 9; 2, -1, -7, -5, 7; 2, 1, 0, 1, -7; 1, 2, 3, 2, 4; 0, -5, -1, 0, 2]
-]]
-? primedec(nf,11)
-[[11, [11, 0, 0, 0, 0]~, 1, 5, 1]]
-? primes(100)
-[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
- 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 
-157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 2
-39, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 33
-1, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421
-, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509,
- 521, 523, 541]
-? forprime(p=2,100,print(p," ",lift(primroot(p))))
-2 1
-3 2
-5 2
-7 3
-11 2
-13 2
-17 3
-19 2
-23 5
-29 2
-31 3
-37 2
-41 6
-43 3
-47 5
-53 2
-59 2
-61 2
-67 2
-71 7
-73 5
-79 3
-83 2
-89 3
-97 5
-? principalideal(nf,mod(x^3+5,nfpol))
-[6, 1, 3, 1, 3]~
-? print((x-12*y)/(y+13*x));
--11/14
-? print([1,2;3,4])
-[1, 2; 3, 4]
-? print1(x+y);print1(" equals ");print(x+y);
-2*x equals 2*x
-? prod(1,k=1,10,1+1/k!)
-3335784368058308553334783/905932868585678438400000
-? prod(1.,k=1,10,1+1/k!)
-3.6821540356142043935732308433185262946
-? pi^2/6*prodeuler(p=2,10000,1-p^-2)
-1.0000098157493066238697591433298145222
-? prodinf(n=0,(1+2^-n)/(1+2^(-n+1)))
-0.33333333333333333333333333333333333329
-? prodinf1(n=0,-2^-n/(1+2^(-n+1)))
-0.33333333333333333333333333333333333329
-? psi(1)
--0.57721566490153286060651209008240243104
-? quaddisc(-252)
--7
-? quadgen(-11)
-w
-? quadpoly(-11)
-x^2 - x + 3
-? rank(matrix(5,5,x,y,x+y))
-2
-? rayclassno(bnf,[[5,3;0,1],[1,0]])
-12
-? rayclassnolist(bnf,lu)
-[[3], [], [3, 3], [3], [6, 6], [], [], [], [3, 3, 3], [], [3, 3], [3, 3], []
-, [], [12, 6, 6, 12], [3], [3, 3], [], [9, 9], [6, 6], [], [], [], [], [6, 1
-2, 6], [], [3, 3, 3, 3], [], [], [], [], [], [3, 6, 6, 3], [], [], [9, 3, 9]
-, [6, 6], [], [], [], [], [], [3, 3], [3, 3], [12, 12, 6, 6, 12, 12], [], []
-, [6, 6], [9], [], [3, 3, 3, 3], [], [3, 3], [], [6, 12, 12, 6]]
-? move(0,50,50);rbox(0,50,50)
-? print1("give a value for s? ");s=read();print(1/s)
-give a value for s? 37.
-0.027027027027027027027027027027027027027
-? real(5-7*i)
-5
-? recip(3*x^7-5*x^3+6*x-9)
--9*x^7 + 6*x^6 - 5*x^4 + 3
-? redimag(qfi(3,10,12))
-qfi(3, -2, 4)
-? redreal(qfr(3,10,-20,1.5))
-qfr(3, 16, -7, 1.5000000000000000000000000000000000000)
-? redrealnod(qfr(3,10,-20,1.5),18)
-qfr(3, 16, -7, 1.5000000000000000000000000000000000000)
-? reduceddisc(x^3+4*x+12)
-[1036, 4, 1]
-? regula(17)
-2.0947125472611012942448228460655286535
-? kill(y);print(x+y);
-x + y
-? resultant(x^3-1,x^3+1)
-8
-? resultant2(x^3-1.,x^3+1.)
-8.0000000000000000000000000000000000000
-? bezoutres(x^2+1,x^2-1)
-[2, -2, 4]
-? reverse(tan(x))
-x - 1/3*x^3 + 1/5*x^5 - 1/7*x^7 + 1/9*x^9 - 1/11*x^11 + 1/13*x^13 - 1/15*x^1
-5 + O(x^17)
-? rhoreal(qfr(3,10,-20,1.5))
-qfr(-20, -10, 3, 2.1074451073987839947135880252731470616)
-? rhorealnod(qfr(3,10,-20,1.5),18)
-qfr(-20, -10, 3, 1.5000000000000000000000000000000000000)
-? rline(0,200,150)
-? cursor(0)
-? rmove(0,5,5);cursor(0)
-? rndtoi(prod(1,k=1,17,x-exp(2*i*pi*k/17)))
-x^17 - 1
-? qpol=y^3-y-1;setrand(1);bnf2=buchinit(qpol);nf2=bnf2[7];
-? un=mod(1,qpol);w=mod(y,qpol);p=un*(x^5-5*x+w)
-mod(1, y^3 - y - 1)*x^5 + mod(-5, y^3 - y - 1)*x + mod(y, y^3 - y - 1)
-? aa=rnfpseudobasis(nf2,p)
-[[1, 0, 0, -2, [3, 1, 0]~; 0, 1, 0, 2, [0, -1, 0]~; 0, 0, 1, 1, [-5, -2, 0]~
-; 0, 0, 0, 1, -2; 0, 0, 0, 0, 1], [1, 1, 1, [1, 0, 2/5; 0, 1, 3/5; 0, 0, 1/5
-], [1, 0, 22/25; 0, 1, 8/25; 0, 0, 1/25]], [416134375, 202396875, 60056800; 
-0, 3125, 2700; 0, 0, 25], [-1275, 5, 5]~]
-? rnfbasis(bnf2,aa)
-
-[1 0 0  [-26/25, 11/25, -8/25]~         [0, 4, -7]~]
-
-[0 1 0   [53/25, -8/25, -1/25]~ [6/5, -41/5, 53/5]~]
-
-[0 0 1 [-14/25, -21/25, 13/25]~  [-16/5, 1/5, 7/5]~]
-
-[0 0 0     [7/25, -2/25, 6/25]~  [2/5, -2/5, 11/5]~]
-
-[0 0 0     [9/25, 1/25, -3/25]~   [2/5, -7/5, 6/5]~]
-
-? rnfdiscf(nf2,p)
-[[416134375, 202396875, 60056800; 0, 3125, 2700; 0, 0, 25], [-1275, 5, 5]~]
-? rnfequation(nf2,p)
-x^15 - 15*x^11 + 75*x^7 - x^5 - 125*x^3 + 5*x + 1
-? rnfequation2(nf2,p)
-[x^15 - 15*x^11 + 75*x^7 - x^5 - 125*x^3 + 5*x + 1, mod(-x^5 + 5*x, x^15 - 1
-5*x^11 + 75*x^7 - x^5 - 125*x^3 + 5*x + 1), 0]
-? rnfhermitebasis(bnf2,aa)
-
-[1 0 0 [-6/5, -4/5, 2/5]~   [3/25, -8/25, 24/25]~]
-
-[0 1 0  [6/5, 4/5, -2/5]~   [-9/25, -1/25, 3/25]~]
-
-[0 0 1  [3/5, 2/5, -1/5]~ [-8/25, 13/25, -39/25]~]
-
-[0 0 0  [3/5, 2/5, -1/5]~   [4/25, 6/25, -18/25]~]
-
-[0 0 0                  0   [-2/25, -3/25, 9/25]~]
-
-? rnfisfree(bnf2,aa)
-1
-? rnfsteinitz(nf2,aa)
-[[1, 0, 0, [-26/25, 11/25, -8/25]~, [29/125, -2/25, 8/125]~; 0, 1, 0, [53/25
-, -8/25, -1/25]~, [-53/125, 7/125, 1/125]~; 0, 0, 1, [-14/25, -21/25, 13/25]
-~, [9/125, 19/125, -13/125]~; 0, 0, 0, [7/25, -2/25, 6/25]~, [-9/125, 2/125,
- -6/125]~; 0, 0, 0, [9/25, 1/25, -3/25]~, [-8/125, -1/125, 3/125]~], [1, 1, 
-1, 1, [125, 0, 22; 0, 125, 108; 0, 0, 1]], [416134375, 202396875, 60056800; 
-0, 3125, 2700; 0, 0, 25], [-1275, 5, 5]~]
-? rootmod(x^16-1,41)
-[mod(1, 41), mod(3, 41), mod(9, 41), mod(14, 41), mod(27, 41), mod(32, 41), 
-mod(38, 41), mod(40, 41)]~
-? rootpadic(x^4+1,41,6)
-[3 + 22*41 + 27*41^2 + 15*41^3 + 27*41^4 + 33*41^5 + O(41^6), 14 + 20*41 + 2
-5*41^2 + 24*41^3 + 4*41^4 + 18*41^5 + O(41^6), 27 + 20*41 + 15*41^2 + 16*41^
-3 + 36*41^4 + 22*41^5 + O(41^6), 38 + 18*41 + 13*41^2 + 25*41^3 + 13*41^4 + 
-7*41^5 + O(41^6)]~
-? roots(x^5-5*x^2-5*x-5)
-[2.0509134529831982130058170163696514536 + 0.E-38*I, -0.67063790319207539268
-663382582902335603 - 0.84813118358634026680538906224199030918*I, -0.67063790
-319207539268663382582902335603 + 0.84813118358634026680538906224199030918*I,
- -0.35481882329952371381627468235580237078 - 1.39980287391035466982975228340
-62081965*I, -0.35481882329952371381627468235580237078 + 1.399802873910354669
-8297522834062081965*I]~
-? rootsold(x^4-1000000000000000000000)
-  ***   at top-level: rootsold(x^4-1000000
-  ***                 ^--------------------
-  *** rootsold: this function no longer exists.
-? round(prod(1,k=1,17,x-exp(2*i*pi*k/17)))
-x^17 - 1
-? rounderror(prod(1,k=1,17,x-exp(2*i*pi*k/17)))
--35
-? rpoint(0,20,20)
-? initrect(3,600,600);scale(3,-7,7,-2,2);cursor(3)
-? q*series(anell(acurve,100),q)
-q - 2*q^2 - 3*q^3 + 2*q^4 - 2*q^5 + 6*q^6 - q^7 + 6*q^9 + 4*q^10 - 5*q^11 - 
-6*q^12 - 2*q^13 + 2*q^14 + 6*q^15 - 4*q^16 - 12*q^18 - 4*q^20 + 3*q^21 + 10*
-q^22 + 2*q^23 - q^25 + 4*q^26 - 9*q^27 - 2*q^28 + 6*q^29 - 12*q^30 - 4*q^31 
-+ 8*q^32 + 15*q^33 + 2*q^35 + 12*q^36 - q^37 + 6*q^39 - 9*q^41 - 6*q^42 + 2*
-q^43 - 10*q^44 - 12*q^45 - 4*q^46 - 9*q^47 + 12*q^48 - 6*q^49 + 2*q^50 - 4*q
-^52 + q^53 + 18*q^54 + 10*q^55 - 12*q^58 + 8*q^59 + 12*q^60 - 8*q^61 + 8*q^6
-2 - 6*q^63 - 8*q^64 + 4*q^65 - 30*q^66 + 8*q^67 - 6*q^69 - 4*q^70 + 9*q^71 -
- q^73 + 2*q^74 + 3*q^75 + 5*q^77 - 12*q^78 + 4*q^79 + 8*q^80 + 9*q^81 + 18*q
-^82 - 15*q^83 + 6*q^84 - 4*q^86 - 18*q^87 + 4*q^89 + 24*q^90 + 2*q^91 + 4*q^
-92 + 12*q^93 + 18*q^94 - 24*q^96 + 4*q^97 + 12*q^98 - 30*q^99 - 2*q^100 + O(
-q^101)
-? aset=set([5,-2,7,3,5,1])
-[-2, 1, 3, 5, 7]
-? bset=set([7,5,-5,7,2])
-[-5, 2, 5, 7]
-? setintersect(aset,bset)
-[5, 7]
-? setminus(aset,bset)
-[-2, 1, 3]
-? setprecision(28)
-38
-? setrand(10)
-? setsearch(aset,3)
-3
-? setsearch(bset,3)
-0
-? setserieslength(12)
-16
-? setunion(aset,bset)
-[-5, -2, 1, 2, 3, 5, 7]
-? shift(1,50)
-1125899906842624
-? shift([3,4,-11,-12],-2)
-[0, 1, -2, -3]
-? shiftmul([3,4,-11,-12],-2)
-[3/4, 1, -11/4, -3]
-? sigma(100)
-217
-? sigmak(2,100)
-13671
-? sigmak(-3,100)
-1149823/1000000
-? sign(-1)
--1
-? sign(0)
-0
-? sign(0.)
-0
-? signat(hilbert(5)-0.11*idmat(5))
-[2, 3]
-? signunit(bnf)
-
-[-1]
-
-[ 1]
-
-? simplefactmod(x^11+1,7)
-
-[ 1 1]
-
-[10 1]
-
-? simplify(((x+i+1)^2-x^2-2*x*(i+1))^2)
--4
-? sin(pi/6)
-0.5000000000000000000000000000
-? sinh(1)
-1.175201193643801456882381851
-? size([1.3*10^5,2*i*pi*exp(4*pi)])
-7
-? smallbasis(x^3+4*x+12)
-[1, x, 1/2*x^2]
-? smalldiscf(x^3+4*x+12)
--1036
-? smallfact(100!+1)
-
-[101 1]
-
-[14303 1]
-
-[149239 1]
-
-[432885273849892962613071800918658949059679308685024481795740765527568493010
-727023757461397498800981521440877813288657839195622497225621499427628453 1]
-
-? smallinitell([0,0,0,-17,0])
-[0, 0, 0, -17, 0, 0, -34, 0, -289, 816, 0, 314432, 1728, Vecsmall([1]), [Vec
-small([128, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]
-? smallpolred(x^4+576)
-[x - 1, x^2 - 3*x + 3, x^2 - 2*x + 2, x^2 - x + 1, x^2 + 1, x^4 - x^2 + 1]
-? smallpolred2(x^4+576)
-
-[                           1         x - 1]
-
-[    -1/192*x^3 - 1/8*x + 3/2 x^2 - 3*x + 3]
-
-[                1/24*x^2 + 1 x^2 - 2*x + 2]
-
-[               -1/24*x^2 + 1 x^2 - 2*x + 2]
-
-[    -1/192*x^3 - 1/8*x + 1/2   x^2 - x + 1]
-
-[     1/192*x^3 + 1/8*x + 1/2   x^2 - x + 1]
-
-[                    1/24*x^2       x^2 + 1]
-
-[1/192*x^3 + 1/48*x^2 - 1/8*x x^4 - x^2 + 1]
-
-? smith(matrix(5,5,j,k,random()))
-[5310167935312697687837910465800456021217135496, 2, 1, 1, 1]
-? smith(1/hilbert(6))
-[27720, 2520, 2520, 840, 210, 6]
-? smithpol(x*idmat(5)-matrix(5,5,j,k,1))
-[x^2 - 5*x, x, x, x, 1]
-? solve(x=1,4,sin(x))
-3.141592653589793238462643383
-? sort(vector(17,x,5*x%17))
-[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
-? sqr(1+o(2))
-1 + O(2^3)
-? sqred(hilbert(5))
-
-[1  1/2   1/3    1/4     1/5]
-
-[0 1/12     1   9/10     4/5]
-
-[0    0 1/180    3/2    12/7]
-
-[0    0     0 1/2800       2]
-
-[0    0     0      0 1/44100]
-
-? sqrt(13+o(127^12))
-34 + 125*127 + 83*127^2 + 107*127^3 + 53*127^4 + 42*127^5 + 22*127^6 + 98*12
-7^7 + 127^8 + 23*127^9 + 122*127^10 + 79*127^11 + O(127^12)
-? srgcd(x^10-1,x^15-1)
-x^5 - 1
-? move(0,100,100);string(0,pi)
-? move(0,200,200);string(0,"(0,0)")
-? postdraw([0,10,10])
-? apol=0.3+legendre(10)
-46189/256*x^10 - 109395/256*x^8 + 45045/128*x^6 - 15015/128*x^4 + 3465/256*x
-^2 + 0.05390625000000000000000000000
-? sturm(apol)
-4
-? sturmpart(apol,0.91,1)
-1
-? subcyclo(31,5)
-x^5 + x^4 - 12*x^3 - 21*x^2 + x + 5
-? subell(initell([0,0,0,-17,0]),[-1,4],[-4,2])
-[9, -24]
-? subst(sin(x),x,y)
-y - 1/6*y^3 + 1/120*y^5 - 1/5040*y^7 + 1/362880*y^9 - 1/39916800*y^11 + O(y^
-13)
-? subst(sin(x),x,x+x^2)
-x + x^2 - 1/6*x^3 - 1/2*x^4 - 59/120*x^5 - 1/8*x^6 + 419/5040*x^7 + 59/720*x
-^8 + 13609/362880*x^9 + 19/13440*x^10 - 273241/39916800*x^11 - 14281/3628800
-*x^12 + O(x^13)
-? sum(0,k=1,10,2^-k)
-1023/1024
-? sum(0.,k=1,10,2^-k)
-0.9990234375000000000000000000
-? sylvestermatrix(a2*x^2+a1*x+a0,b1*x+b0)
-
-[a2 b1  0]
-
-[a1 b0 b1]
-
-[a0  0 b0]
-
-? \precision=38
-? 4*sumalt(n=0,(-1)^n/(2*n+1))
-3.1415926535897932384626433832795028842
-? 4*sumalt2(n=0,(-1)^n/(2*n+1))
-3.1415926535897932384626433832795028842
-? suminf(n=1,2.^-n)
-0.99999999999999999999999999999999999999
-? 6/pi^2*sumpos(n=1,n^-2)
-1.0000000000000000000000000000000000000
-? supplement([1,3;2,4;3,6])
-
-[1 3 0]
-
-[2 4 0]
-
-[3 6 1]
-
-? sqr(tan(pi/3))
-3.0000000000000000000000000000000000000
-? tanh(1)
-0.76159415595576488811945828260479359041
-? taniyama(bcurve)
-[x^-2 - x^2 + 3*x^6 - 2*x^10 + O(x^11), -x^-3 + 3*x - 3*x^5 + 8*x^9 + O(x^10
-)]
-? taylor(y/(x-y),y)
-(O(y^12)*x^11 + y*x^10 + y^2*x^9 + y^3*x^8 + y^4*x^7 + y^5*x^6 + y^6*x^5 + y
-^7*x^4 + y^8*x^3 + y^9*x^2 + y^10*x + y^11)/x^11
-? tchebi(10)
-512*x^10 - 1280*x^8 + 1120*x^6 - 400*x^4 + 50*x^2 - 1
-? teich(7+o(127^12))
-7 + 57*127 + 58*127^2 + 83*127^3 + 52*127^4 + 109*127^5 + 74*127^6 + 16*127^
-7 + 60*127^8 + 47*127^9 + 65*127^10 + 5*127^11 + O(127^12)
-? texprint((x+y)^3/(x-y)^2)
-\frac{x^3
- + 3 y x^2
- + 3 y^2 x
- + y^3}{x^2
- - 2 y x
- + y^2}
-? theta(0.5,3)
-0.080806418251894691299871683210466298523
-? thetanullk(0.5,7)
--804.63037320243369422783730584965684023
-? torsell(tcurve)
-[12, [6, 2], [[1, 2], [3, -2]]]
-? trace(1+i)
-2
-? trace(mod(x+5,x^3+x+1))
-15
-? trans(vector(2,x,x))
-[1, 2]~
-? %*%~
-
-[1 2]
-
-[2 4]
-
-? trunc(-2.7)
--2
-? trunc(sin(x^2))
-1/120*x^10 - 1/6*x^6 + x^2
-? tschirnhaus(x^5-x-1)
-x^5 - 5*x^4 - 8*x^3 + 71*x^2 + 302*x - 604
-? type(mod(x,x^2+1))
-9
-? unit(17)
-3 + 2*w
-? n=33;until(n==1,print1(n," ");if(n%2,n=3*n+1,n=n/2));print(1)
-33 100 50 25 76 38 19 58 29 88 44 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
-? valuation(6^10000-1,5)
-5
-? vec(sin(x))
-[1, 0, -1/6, 0, 1/120, 0, -1/5040, 0, 1/362880, 0, -1/39916800, 0]
-? vecmax([-3,7,-2,11])
-11
-? vecmin([-3,7,-2,11])
--3
-? vecsort([[1,8,5],[2,5,8],[3,6,-6],[4,8,6]],2)
-[[2, 5, 8], [3, 6, -6], [1, 8, 5], [4, 8, 6]]
-? vecsort([[1,8,5],[2,5,8],[3,6,-6],[4,8,6]],[2,1])
-[[2, 5, 8], [3, 6, -6], [1, 8, 5], [4, 8, 6]]
-? weipell(acurve)
-x^-2 + 1/5*x^2 - 1/28*x^4 + 1/75*x^6 - 3/1540*x^8 + O(x^10)
-? wf(i)
-1.1892071150027210667174999705604759153
-? wf2(i)
-1.0905077326652576592070106557607079790
-? m=5;while(m<20,print1(m," ");m=m+1);print()
-5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
-? zell(acurve,apoint)
-0.72491221490962306778878739838332384646
-? zeta(3)
-1.2020569031595942853997381615114499908
-? zeta(0.5+14.1347251*i)
-5.2043097453468479398562848599360610966 E-9 - 3.2690639869786982176409251733
-763732423 E-8*I
-? zetak(nfz,-3)
-0.091666666666666666666666666666666666667
-? zetak(nfz,1.5+3*i)
-0.88324345992059326405525724366416928892 - 0.2067536250233895222724230899142
-7938848*I
-? zidealstar(nf2,54)
-[132678, [1638, 9, 9], [[3, -26, 1]~, 31, [1, 0, -24]~]]
-? bid=zidealstarinit(nf2,54)
-[[[54, 0, 0; 0, 54, 0; 0, 0, 54], [0]], [132678, [1638, 9, 9]], [[2, [2, 0, 
-0]~, 1, 3, 1], 1; [3, [3, 0, 0]~, 1, 3, 1], 3], [[[[7], [[1, 1, 1]~], [[1, -
-27, -27]~], [Vecsmall([])], 1]], [[[26], [[3, 2, 0]~], [[3, 2, 0]~], [Vecsma
-ll([])], 1], [[3, 3, 3], [4, [1, 3, 0]~, [1, 0, 3]~], [-77, [1, -24, 0]~, [1
-, 0, -24]~], [Vecsmall([]), Vecsmall([]), Vecsmall([])], [1/3, 0, 0; 0, 1/3,
- 0; 0, 0, 1/3]], [[3, 3, 3], [10, [1, 9, 0]~, [1, 0, 9]~], [-233, [1, -18, 0
-]~, [1, 0, -18]~], [Vecsmall([]), Vecsmall([]), Vecsmall([])], [1/9, 0, 0; 0
-, 1/9, 0; 0, 0, 1/9]]], [[], [], []]], [468, 469, 0, 0, -728, 0, 0, -546; 0,
- 0, 1, 0, -6, -6, 0, 0; 0, 0, 0, 1, -3, 0, -6, 0]]
-? zideallog(nf2,w,bid)
-[922, 8, 0]~
-? znstar(3120)
-[768, [12, 4, 4, 2, 2], [mod(2641, 3120), mod(2341, 3120), mod(2497, 3120), 
-mod(391, 3120), mod(2081, 3120)]]
-? sin'(4)
--0.65364362086361191463916818309775038142
-? m=3;if(m==1,2,m==3,4,5)
-4
-? a=[1,2,3];
-? deplin(a)
-[-2, 1, 0]~
-? deplin(mod(a,2))
-[0, 1, 0]~
-? deplin(mod(a,7))
-[-2, 1, 0]~
-? deplin(mod(a,2^64+13))
-[-2, 1, 0]~
-? p=2^64+13;t=char(mod(4*p*y+1,y^4+1),x);discf2(t)
-256
-? getstack()
-200
-? getheap()
-[721, 98442]
-? print("Total time spent: ",gettime);
-Total time spent: 132
diff --git a/src/test/64/ell b/src/test/64/ell
deleted file mode 100644
index b2ddd63..0000000
--- a/src/test/64/ell
+++ /dev/null
@@ -1,405 +0,0 @@
--1
-0
-152
-1031:[504, 2]
-2053:[1008, 2]
-4099:[4196]
-8209:[8291]
-16411:[8280, 2]
-32771:[32545]
-65537:[65115]
-131101:[130579]
-262147:[261873]
-524309:[525362]
-1048583:[1048721]
-2097169:[2099343]
-4194319:[4190448]
-8388617:[4196176, 2]
-16777259:[16776451]
-33554467:[33556544]
-67108879:[33553348, 2]
-134217757:[134207016]
-268435459:[268450764]
-536870923:[536886729]
-1073741827:[1073696739]
-2147483659:[2147445985]
-4294967311:[4294892145]
-8589934609:[8589800815]
-17179869209:[17179907771]
-34359738421:[34359891299]
-68719476767:[68719109932]
-137438953481:[137439150447]
-274877906951:[274876963417]
-549755813911:[549755723143]
-1099511627791:[1099510624080]
-2199023255579:[1099512197774, 2]
-4398046511119:[4398049864270]
-8796093022237:[8796090641581]
-17592186044423:[17592179180564]
-35184372088891:[35184377696395]
-70368744177679:[70368735914810]
-140737488355333:[140737466844674]
-281474976710677:[281474967245574]
-562949953421381:[562949910045019]
-1125899906842679:[562949923357406, 2]
-2251799813685269:[2251799812875502]
-4503599627370517:[4503599672855988]
-9007199254740997:[9007199395723803]
-18014398509482143:[18014398460825440]
-36028797018963971:[18014398463069820, 2]
-72057594037928017:[36028797145369816, 2]
-144115188075855881:[144115187446866113]
-288230376151711813:[288230375567209858]
-576460752303423619:[576460752721346915]
-1152921504606847009:[1152921506693313952]
-2305843009213693967:[2305843010596733829]
-4611686018427388039:[4611686021547019756]
-9223372036854775837:[9223372041689460430]
-15
-1
-1
-163663
-121661
-1
-1023
-494
-[4, [2, 2], [[-2147484185, 0], [0, 0]]]
-2
-2
-0
-0
-0
-1728
-j
-0
-Mod(0, 5)
-Mod(3, 5)
-Mod(1, 2)*j
-0
-Mod(1, 3)*j
-a
-a
-8*x^9 + 54*x^8 + 393*x^7 + 2373*x^6 + 6993*x^5 + 15267*x^4 + 19998*x^3 + 473
-4*x^2 - 25880*x - 30932
-16*x^33 + 20048*x^30 - 524864*x^27 - 20273280*x^24 - 35051520*x^21 - 1832755
-20*x^18 - 818626560*x^15 - 1017937920*x^12 - 390856704*x^9 + 74973184*x^6 + 
-102760448*x^3 + 4194304
-[3.1096482423243803285501491221965830079, 1.55482412116219016427507456109829
-15039 + 1.0643747452102737569438859937299427442*I]
-[6.2192964846487606571002982443931660158, 3.10964824232438032855014912219658
-30079 + 2.1287494904205475138877719874598854884*I]
-[5.5614800275334595421263952543627169988, 2.78074001376672977106319762718135
-84994 - 2.1374995527123861323185270948750077575*I]
-[6.2192964846487606571002982443931660158, 3.10964824232438032855014912219658
-30079 + 2.1287494904205475138877719874598854884*I]
-[-1.1547274830668428355945002349018042438, -0.828886258466578582202749882549
-09787812 + 0.52313677422798965199542236165917364573*I, -0.828886258466578582
-20274988254909787812 - 0.52313677422798965199542236165917364573*I]
-[10351, [1/2, -1, -2, 5/4], 1, [11, 1; 941, 1], [[1, 5, 0, 1], [1, 5, 0, 1]]
-]
-[10351, [1, -1, 0, -1], 1, [11, 1; 941, 1], [[1, 5, 0, 1], [1, 5, 0, 1]]]
-  ***   at top-level: E.omega
-  ***                   ^-----
-  *** _.omega: incorrect type in omega [not defined over C] (t_VEC).
-[9, [9], [[Mod(3, 7), Mod(5, 7)]]]
-[0, 0, 0, 413748, 716503104, 0, 827496, 2866012416, -171187407504, -19859904
-, -619058681856, -226311754192704000000, 97158364170048/2807086984375, Vecsm
-all([1]), [Vecsmall([128, -1])], [0, 0, 0, 0, 0, 0, 0, [[2, 3]~]]]
-[1/30, -13/150, -1/10, -79/500]
-1
-[36, [36], [[a^4 + a^3 + a^2, a^2]]]
-1
-[3, [3], [[0, 2]]]
-1
-[4, [4], [[Mod(3, 5), Mod(3, 5)]]]
-[1 + 2*3 + 3^2 + 2*3^3 + 3^4 + 3^5 + 2*3^6 + 3^7 + O(3^8), 1 + 3 + 3^3 + 3^4
- + 2*3^5 + 2*3^6 + 2*3^7 + O(3^8), 3 + 2*3^3 + O(3^6), [1 + 2*3 + 3^2 + 2*3^
-3 + 3^4 + 3^6 + 2*3^7 + O(3^8), 1 + 3 + 2*3^2 + 3^3 + 2*3^4 + 2*3^5 + 3^6 + 
-3^7 + O(3^8)]]
-[3^-1 + 2 + 2*3^2 + 2*3^5 + 2*3^6 + O(3^8)]~
-[3^2 + 2*3^3 + 3^4 + 2*3^5 + 3^6 + 3^7 + 2*3^8 + 3^9 + O(3^10), 3 + 3^2 + 3^
-4 + 3^5 + 2*3^6 + 2*3^7 + 2*3^8 + O(3^9), 3 + 2*3^3 + O(3^6), [3^-2 + 2*3^-1
- + 1 + 2*3 + 3^2 + 3^4 + 2*3^5 + O(3^6), 3^-2 + 3^-1 + 2 + 3 + 2*3^2 + 2*3^3
- + 3^4 + 3^5 + O(3^6)]]
-error("incorrect type in obj_check (t_VEC).")
-[2 + 2^6 + 2^10 + O(2^11), Mod(u, u^2 + (2 + 2^2 + 2^3 + 2^4 + 2^5 + 2^7 + 2
-^8 + 2^9 + O(2^11))), 2^3 + 2^4 + O(2^8), [2^-3 + 2^2 + 2^4 + 2^7 + 2^10 + O
-(2^11), 2^-3 + 2^2 + 2^5 + 2^6 + 2^10 + O(2^13)]]
-x^-2 + 31/15*x^2 + 2501/756*x^4 + 961/675*x^6 + 77531/41580*x^8 + O(x^9)
-[-1, -2*w]
-[I, 1]
-[[I, 1], [-3.1415926535897932384626433832795028842*I, 3.14159265358979323846
-26433832795028842]]
-[1, 1]
-x^-2 - 1/5*x^2 - 1/7*x^4 + 1/75*x^6 + 3/385*x^8 + 277/238875*x^10 - 2/5775*x
-^12 + O(x^14)
-x^-2 - 1/5*x^2 - 1/7*x^4 + 1/75*x^6 + O(x^7)
-8.9760336058655702799613054290253052728
--8.9795585687185301843619815765809019104
-0.0070737179180847219897019688523688143761 - 4.54459013280902760664280136539
-71181201*I
-[1, 2]
-x^-2 + 9.4536360064616926146530698267460656697*x^2 + 6.577345622160325336 E-
-37*x^4 + 29.790411247556326629130082765180921498*x^6 + 1.6958135836526736817
- E-36*x^8 + 43.327339141107674122263886023453990048*x^10 + 3.562578745481278
-561 E-36*x^12 + O(x^14)
-x^-2 + 9.4536360064616926146530698267460656697*x^2 + 6.577345622160325336 E-
-37*x^4 + 29.790411247556326629130082765180921498*x^6 + O(x^7)
-10.092015307351769584764433105625607145
--10.092015307351769584764433105625607145
-3.2557987470773994635555990212606293690 E-38 - 2.704147351607435273075740713
-3303875089*I
-[1, 3]
-x^-2 + 9.4536360064616926146530698267460656697*x^2 + 6.577345622160325336 E-
-37*x^4 + 29.790411247556326629130082765180921498*x^6 + 1.6958135836526736817
- E-36*x^8 + 43.327339141107674122263886023453990048*x^10 + 3.562578745481278
-561 E-36*x^12 + O(x^14)
-x^-2 + 9.4536360064616926146530698267460656697*x^2 + 6.577345622160325336 E-
-37*x^4 + 29.790411247556326629130082765180921498*x^6 + O(x^7)
-10.092015307351769584764433105625607145
--10.092015307351769584764433105625607145
-3.2557987470773994635555990212606293690 E-38 - 2.704147351607435273075740713
-3303875089*I
-[2, 1]
-x^-1 + 1/15*x^3 + 1/35*x^5 - 1/525*x^7 - 1/1155*x^9 - 277/2627625*x^11 + 2/7
-5075*x^13 + O(x^15)
-x^-1 + 1/15*x^3 + 1/35*x^5 - 1/525*x^7 + O(x^8)
-3.0025857981852417376980007365038576528
--3.0023507303355942712341893343171384978*I
-1.4945837634650773441141478432745008118 - 1.49552579635851441107083905597206
-14467*I
-[2, 2]
-x^-1 - 3.1512120021538975382176899422486885566*x^3 - 1.3154691244320650671 E
--37*x^5 - 4.2557730353651895184471546807401316426*x^7 - 1.884237315169637424
- E-37*x^9 - 3.9388490128279703747512623657685445499*x^11 - 2.740445188831752
-739 E-37*x^13 + O(x^15)
-x^-1 - 3.1512120021538975382176899422486885566*x^3 - 1.3154691244320650671 E
--37*x^5 - 4.2557730353651895184471546807401316426*x^7 + O(x^8)
-2.8609969154308155967482927187353233603
--2.8813199850735158607638401394492232764*I
-1.7185329556464940714815988649194112975 - 1.71853295564649407148159886491941
-12976*I
-[2, 3]
-x^-1 - 3.1512120021538975382176899422486885566*x^3 - 1.3154691244320650671 E
--37*x^5 - 4.2557730353651895184471546807401316426*x^7 - 1.884237315169637424
- E-37*x^9 - 3.9388490128279703747512623657685445499*x^11 - 2.740445188831752
-739 E-37*x^13 + O(x^15)
-x^-1 - 3.1512120021538975382176899422486885566*x^3 - 1.3154691244320650671 E
--37*x^5 - 4.2557730353651895184471546807401316426*x^7 + O(x^8)
-2.8609969154308155967482927187353233603
--2.8813199850735158607638401394492232764*I
-1.7185329556464940714815988649194112975 - 1.71853295564649407148159886491941
-12976*I
-[3, 1]
-x + 1/60*x^5 + 1/210*x^7 - 1/10080*x^9 - 1/138600*x^11 - 167/259459200*x^13 
-- 19/1513512000*x^15 + O(x^17)
-x + 1/60*x^5 + 1/210*x^7 - 1/10080*x^9 + O(x^10)
-0.33340409272605175654322174351877926789
-0.33339973807064633526799756411632693200*I
-0.33307632454406929865753194192439552171 + 0.3330414840427217068846417452694
-8964209*I
-[3, 2]
-x - 0.78780300053847438455442248556217213914*x^5 - 2.1924485407201084452 E-3
-8*x^7 - 0.22165484559193695408578930628854852305*x^9 - 1.5701977626413645215
- E-39*x^11 + 0.0093619303173614540570518182056750707483*x^13 + 1.29138042132
-44866734 E-40*x^15 + O(x^17)
-x - 0.78780300053847438455442248556217213914*x^5 - 2.1924485407201084452 E-3
-8*x^7 - 0.22165484559193695408578930628854852305*x^9 + O(x^10)
-0.33008009031657824359527653587336069208
-0.33008009031657824359527653587336069208*I
-0.34612072856429482856153662202577445445 + 0.3461207285642948285615366220257
-7445446*I
-[3, 3]
-x - 0.78780300053847438455442248556217213914*x^5 - 2.1924485407201084452 E-3
-8*x^7 - 0.22165484559193695408578930628854852305*x^9 - 1.5701977626413645215
- E-39*x^11 + 0.0093619303173614540570518182056750707483*x^13 + 1.29138042132
-44866734 E-40*x^15 + O(x^17)
-x - 0.78780300053847438455442248556217213914*x^5 - 2.1924485407201084452 E-3
-8*x^7 - 0.22165484559193695408578930628854852305*x^9 + O(x^10)
-0.33008009031657824359527653587336069208
-0.33008009031657824359527653587336069208*I
-0.34612072856429482856153662202577445445 + 0.3461207285642948285615366220257
-7445446*I
-[4, 1]
-0
-0
--1.0984000330177788282680372407424344829
--1.0984130942966868400436474225688716324 + 1.5707963267948966192313216916397
-514421*I
--0.75286232322707031868584884787482252469 + 0.785345859584418994173505759767
-90041015*I
-[4, 2]
-0
-0
--1.1084199560389642415209208807828823872
--1.1084199560389642415209208807828823872 + 1.5707963267948966192313216916397
-514421*I
--0.71439404801872849905771074604935970853 + 0.785398163397448309615660845819
-87572105*I
-[4, 3]
-0
-0
--1.1084199560389642415209208807828823872
--1.1084199560389642415209208807828823872 + 1.5707963267948966192313216916397
-514421*I
--0.71439404801872849905771074604935970853 + 0.785398163397448309615660845819
-87572105*I
-[2.5135797437238231405782694715779164652, 1.25678987186191157028913473578895
-82326 + 0.78959476569186174055147277865716603189*I]
-[3.1415926535897932384626433832795028842, 9.42477796076937971538793014983850
-86526*I]
-(x)->elleisnum(x,2)
--2.9936282668967606065680548947245432597 - 7.1637767384648910133063235008836
-078048*I
--37.699111843077518861551720599354034610
--37.699111843077518861551720599354034610
-(x)->elleisnum(x,4,1)
--3.9999999999999999999999999999999999999 - 5.485640303837341704 E-38*I
-189.07272012923385229306139653492131339
-189.07272012923385229306139653492131339
-(x)->elleisnum(x,6,1)
--4.0000000000000000000000000000000000000 - 1.2538606408771066752 E-37*I
-1.8416567742048910940 E-35
-1.8416567742048910940 E-35
-(x)->elleisnum(x,10)
--41471.999999999999999999999999999999998 - 7.703719777548943412 E-34*I
--2.8181184198060280543 E-30
--2.8181184198060280543 E-30
--1
-[0]
-347813742467679407541/38941611811810745401
-[1, [], []]
-[2, [2], [[15, -8]]]
-[3, [3], [[5, 9]]]
-[4, [4], [[5, -2]]]
-[5, [5], [[5, 5]]]
-[6, [6], [[9, 23]]]
-[7, [7], [[-1, 2]]]
-[8, [8], [[2, 6]]]
-[9, [9], [[-3, 7]]]
-[10, [10], [[0, 9]]]
-[12, [12], [[-9, 49]]]
-[4, [2, 2], [[-29/4, 25/8], [-7, 3]]]
-[8, [4, 2], [[-2, 3], [-1, 0]]]
-[12, [6, 2], [[1, 2], [3, -2]]]
-[16, [8, 2], [[4, 58], [-36, 18]]]
-[16, [8, 2], [[117433600, 6734213027200], [352179456, -176089728]]]
-[4, [2, 2], [[-1377493124511464657, 0], [-691668349248679055, 0]]]
-[0.49999999999999999999999999999999999978 - 2.0571151139390031389 E-38*I, 1.
-9216402159513147090074725264936203858 + 0.2601943880282882461780139076976017
-6484*I]
-3 + 11^2 + 2*11^3 + 3*11^4 + O(11^5)
-Mod((2 + 3 + O(3^4))*u + (2*3 + 3^2 + O(3^4)), u^2 + (1 + 3 + 2*3^4 + 3^8 + 
-2*3^9 + O(3^10)))
-Mod((1 + 3 + 3^3 + 3^4 + 2*3^6 + 2*3^8 + 2*3^9 + O(3^10))*u + (1 + 3 + 3^2 +
- 3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 3^9 + O(3^10)), u^2 + (3 + 3^3 + 2*3^4 + 3^5 
-+ 2*3^6 + 3^7 + 2*3^8 + 3^9 + 2*3^10 + 3^11 + 2*3^12 + O(3^13)))
-Mod((2^3 + 2^7 + O(2^8))*u + (1 + 2 + 2^2 + 2^3 + 2^4 + O(2^6)), u^2 + (1 + 
-2^2 + 2^4 + 2^5 + 2^7 + 2^8 + 2^9 + O(2^13)))
-[Mod(0, 11), Mod(0, 11), Mod(0, 11), Mod(1, 11), Mod(1, 11), Mod(0, 11), Mod
-(2, 11), Mod(4, 11), Mod(10, 11), Mod(7, 11), Mod(5, 11), Mod(10, 11), Mod(9
-, 11), Vecsmall([3]), [11, [9, 5, [6, 0, 0, 0]]], [0, 0, 0, 0]]
-1
-[0.86602540378443864676372317075293618347 - 1/2*I, -0.8660254037844386467637
-2317075293618348 - 1/2*I]
-[-2, 3]
-[0, 1]
-[1, 0, 0, 0]
-0.035247504442186170440172838583518049039
-[0, 0, 0, 1, 1, 0, 2, 4, -1, -48, -864, -496, 6912/31, Vecsmall([1]), [Vecsm
-all([128, -1])], [0, 0, 0, 0, 0, 0, 0, [[2, 3]~]]]
-[0, 0, 0, 1/16, 1/64, 0, 1/8, 1/16, -1/256, -3, -27/2, -31/256, 6912/31, Vec
-small([1]), [Vecsmall([128, -1])], [0, 0, 0, 0, 0, 0, 0, [[2, 3]~, [1/2, 0, 
-0, 0], [0, 0, 0, 1, 1, 0, 2, 4, -1, -48, -864, -496, 6912/31, Vecsmall([1]),
- [Vecsmall([128, -1])], [0, 0, 0, 0, 0, 0, 0, [[2, 3]~]]]]]]
-
-0
-20 0 0 -16 0 -4 14 8 0 0 0 26 0 2 0 -28 
-1728
-0 0 -22 0 -14 0 -22 0 0 26 0 18 0 -14 2 0 
--3375
-16 0 -10 0 -22 24 0 -20 0 0 4 0 8 -18 -26 0 
-8000
-0 -18 6 22 0 0 0 2 0 0 18 0 0 22 0 0 
-54000
-20 0 0 16 0 4 -14 -8 0 0 0 26 0 2 0 -28 
--32768
-0 0 3 0 0 0 23 16 0 0 21 25 -15 0 0 -20 
-287496
-0 0 22 0 -14 0 22 0 0 -26 0 -18 0 14 2 0 
--884736
-0 7 23 -9 11 0 18 -24 0 0 0 0 17 0 -22 -25 
--12288000
-20 0 0 -23 0 19 14 25 0 0 0 7 0 23 0 -11 
-16581375
-16 0 10 0 22 24 0 -20 0 0 -4 0 8 -18 -26 0 
--884736000
-11 0 0 -13 0 0 0 0 -25 -2 0 -6 0 -27 -10 0 
--147197952000
--21 -16 0 0 -23 1 5 7 20 -25 0 11 0 13 0 -27 
--262537412640768000
-0 19 0 0 0 -21 0 0 4 -23 8 0 0 0 -25 -12 
-4294985035
-[0, 1, [5, 0, 0, 0], 1]
-1
-0
-[6.2500000000000000000000000000000000000, -140.62500000000000000000000000000
-000000]
-[37247908142/10128208321, 7601802384416381/1019292757217119]
-[0, 0, 0, x^2, x, 0, 2*x^2, 4*x, -x^4, -48*x^2, -864*x, -64*x^6 - 432*x^2, -
-6912*x^4/(-4*x^4 - 27), Vecsmall([0]), [Vecsmall([128, 0])], [0, 0, 0, 0]]
-  ***   at top-level: ellminimalmodel(E)
-  ***                 ^------------------
-  *** ellminimalmodel: incorrect type in checkell over Q (t_VEC).
-  ***   at top-level: ellweilpairing(E,[0]
-  ***                 ^--------------------
-  *** ellweilpairing: incorrect type in checkell over Fq (t_VEC).
-  ***   at top-level: ellinit([1])
-  ***                 ^------------
-  *** ellinit: incorrect type in ellxxx [not an elliptic curve (ell5)] (t_VEC).
-  ***   at top-level: ellinit([1,1],quadge
-  ***                 ^--------------------
-  *** ellinit: incorrect type in elliptic curve base_ring (t_QUAD).
-  ***   at top-level: ellinit([Mod(1,2),1]
-  ***                 ^--------------------
-  *** ellinit: incorrect type in elliptic curve base_ring (t_VEC).
-  ***   at top-level: ellinit([O(2),1],ffg
-  ***                 ^--------------------
-  *** ellinit: incorrect type in elliptic curve base_ring (t_VEC).
-  ***   at top-level: ellinit([O(2),1],1.)
-  ***                 ^--------------------
-  *** ellinit: incorrect type in elliptic curve base_ring (t_VEC).
-[0, 0, 0, 1, 2, 0, 2, 8, -1, -48, -1728, -1792, 432/7, Vecsmall([0]), [Vecsm
-all([128, -1])], [0, 0, 0, 0]]
-[0, 0, 0, 0, 1, 0, 0, 4, 0, 0, 1, 3, 0, Vecsmall([4]), [0, [Vecsmall([0]), V
-ecsmall([0, 1]), [Vecsmall([0, 1]), Vecsmall([0]), Vecsmall([0]), Vecsmall([
-0])]]], [0, 0, 0, 0]]
-  ***   at top-level: ellinit([ffgen(5),1]
-  ***                 ^--------------------
-  *** ellinit: inconsistent moduli in ellinit: 3 != 5
-[0, 0, 0, 1.0000000000000000000000000000000000000, 1, 0, 2.00000000000000000
-00000000000000000000, 4, -1.0000000000000000000000000000000000000, -48.00000
-0000000000000000000000000000000, -864, -496.00000000000000000000000000000000
-000, 222.96774193548387096774193548387096774, Vecsmall([0]), [Vecsmall([128,
- -1])], [0, 0, 0, 0]]
-  ***   at top-level: ellinit([1.,Mod(1,3)
-  ***                 ^--------------------
-  *** ellinit: incorrect type in elliptic curve base_ring (t_VEC).
-1
--1
-1
-x^-2 + Mod(-1/5*x, x^2 + 5)*x^2 + Mod(-1/15, x^2 + 5)*x^6 + Mod(2/975*x, x^2
- + 5)*x^10 + O(x^14)
-x^-1 + Mod(1/15*x, x^2 + 5)*x^3 + Mod(1/105, x^2 + 5)*x^7 + Mod(-2/10725*x, 
-x^2 + 5)*x^11 + O(x^15)
-x + Mod(1/60*x, x^2 + 5)*x^5 + Mod(1/2016, x^2 + 5)*x^9 + Mod(23/51891840*x,
- x^2 + 5)*x^13 + O(x^17)
-Mod(1, 1009)*x^-2 + Mod(807, 1009)*x^2 + Mod(148, 1009)*x^6 + Mod(368, 1009)
-*x^10 + O(x^14)
-Mod(1, 1009)*x^-1 + Mod(740, 1009)*x^3 + Mod(123, 1009)*x^7 + Mod(150, 1009)
-*x^11 + O(x^15)
-Mod(1, 1009)*x + Mod(185, 1009)*x^5 + Mod(101, 1009)*x^9 + Mod(990, 1009)*x^
-13 + O(x^17)
--52760
--52832
-Total time spent: 568
diff --git a/src/test/64/ellanal b/src/test/64/ellanal
deleted file mode 100644
index ec93e18..0000000
--- a/src/test/64/ellanal
+++ /dev/null
@@ -1,14 +0,0 @@
-[0, 0.25384186085591068433775892335090946105]
-[1, 0.30599977383405230182048368332167647444]
-[2, 1.5186330005768535404603852157894440392]
-[3, 10.391099400715804138751850510360917049]
-[5, 9997.0334671722554999496820788093288503]
-[-339/16, 691/64]
-[-3, 12]
-[69648970982596494254458225/166136231668185267540804, 5389624350896046150780
-04307258785218335/67716816556077455999228495435742408]
-[553/17424, 25469/2299968]
-35
-  ***   Warning: new stack size = 30000000 (28.610 Mbytes).
-[1317254400, 19916886528000]
-Total time spent: 10772
diff --git a/src/test/64/ff b/src/test/64/ff
deleted file mode 100644
index 2b163ca..0000000
--- a/src/test/64/ff
+++ /dev/null
@@ -1,283 +0,0 @@
-? test(2,20)
-[a^2 + a + 1, a^19 + a^18 + a^17 + a^15 + a^14 + a^13 + a^12 + a^8 + a^7 + a
-^6 + a^4 + a^2 + 1, 0, a + 1, 0, 0, 0, 0, a^19 + a^16 + a^15 + a^11 + a^8 + 
-a^5 + a^4 + a^3 + a^2 + a, a, a^2, a^12 + a^9 + a^6 + a^4 + a^3 + a^2 + a, a
-^18 + a^17 + a^16 + a^14 + a^13 + a^12 + a^11 + a^10 + a^9 + a^8 + a^7 + a^4
- + a^3 + a^2 + 1, a^18 + a^17 + a^16 + a^14 + a^13 + a^12 + a^11 + a^10 + a^
-9 + a^8 + a^7 + a^4 + a^3 + a^2 + 1, a^16 + a^12 + a^9 + a^6 + a^4 + a^3 + a
-^2 + a + 1, 0, Mod(1, 2), Mod(0, 2), Mod(1, 2)*x^20 + Mod(1, 2)*x^17 + Mod(1
-, 2)*x^16 + Mod(1, 2)*x^12 + Mod(1, 2)*x^9 + Mod(1, 2)*x^6 + Mod(1, 2)*x^5 +
- Mod(1, 2)*x^4 + Mod(1, 2)*x^3 + Mod(1, 2)*x^2 + Mod(1, 2), Mod(1, 2)*x^20 +
- Mod(1, 2)*x^17 + Mod(1, 2)*x^16 + Mod(1, 2)*x^12 + Mod(1, 2)*x^9 + Mod(1, 2
-)*x^6 + Mod(1, 2)*x^5 + Mod(1, 2)*x^4 + Mod(1, 2)*x^3 + Mod(1, 2)*x^2 + Mod(
-1, 2), [a, a^2, a^4, a^8, a^16, a^16 + a^12 + a^9 + a^6 + a^4 + a^3 + a^2, a
-^16 + a^12 + a^9 + a^6 + a^4 + a^3 + a + 1, a^16 + a^12 + a^9 + a^6 + a^3 + 
-a^2 + a, a^16 + a^12 + a^9 + a^8 + a^6 + a^4 + a^3 + a^2 + a + 1, a^12 + a^9
- + a^6 + a^4 + a^3 + a^2 + a, a + 1, a^2 + 1, a^4 + 1, a^8 + 1, a^16 + 1, a^
-16 + a^12 + a^9 + a^6 + a^4 + a^3 + a^2 + 1, a^16 + a^12 + a^9 + a^6 + a^4 +
- a^3 + a, a^16 + a^12 + a^9 + a^6 + a^3 + a^2 + a + 1, a^16 + a^12 + a^9 + a
-^8 + a^6 + a^4 + a^3 + a^2 + a]~, [x^3 + (a^17 + a^16 + a^10 + a^7 + a^3), 1
-; x^3 + (a^17 + a^16 + a^10 + a^7 + a^3 + a), 1], [], a/x, 1, a^18 + a^16 + 
-a^14 + a^13 + a^12 + a^11 + a^9 + a^8 + a^7 + a^3 + a^2 + a + 1, 1048575, a,
- [x + (a^18 + a^16 + a^13 + a^9 + a^8 + a^7 + a^6 + a^4 + a^2 + a), 1; x + (
-a^18 + a^16 + a^13 + a^9 + a^8 + a^7 + a^6 + a^4 + a^2 + a + 1), 1], [a^18 +
- a^16 + a^13 + a^9 + a^8 + a^7 + a^6 + a^4 + a^2 + a, a^18 + a^16 + a^13 + a
-^9 + a^8 + a^7 + a^6 + a^4 + a^2 + a + 1]~]
-? test(7,7)
-[a^2 + 3*a + 1, a^6 + 2*a^4 + 5*a^3 + 2*a^2 + 5*a + 1, 3*a + 3, a + 3, 5*a^6
- + 3*a^4 + 4*a^3 + 3*a^2 + 4*a, 2*a + 2, 2*a + 2, 4*a + 4, 6*a^6 + 6*a^5 + 5
-*a^4 + 2, 6*a, a^2, 3*a^6 + 5*a^5 + 3*a^3 + a^2 + 2*a + 6, 4*a^2 + 4*a + 4, 
-4*a^2 + 4*a + 4, 4, 3*a^6 + 3*a^5 + 5*a^4 + 2*a^3 + 3*a^2 + a + 4, Mod(1, 7)
-, Mod(6, 7), Mod(1, 7)*x^7 + Mod(1, 7)*x^6 + Mod(2, 7)*x^5 + Mod(5, 7)*x + M
-od(1, 7), Mod(1, 7)*x^7 + Mod(1, 7)*x^6 + Mod(2, 7)*x^5 + Mod(5, 7)*x + Mod(
-1, 7), [a, 6*a^6 + 5*a^5 + 2*a + 6, 5*a^6 + 6*a^5 + 2*a^3 + 4*a^2 + 3*a + 5,
- 3*a^6 + 5*a^2 + 5, 6*a^6 + 2*a^5 + 5*a^4 + 5*a^3 + 5*a^2 + a + 5, 2*a^6 + 5
-*a^2 + 6, 6*a^6 + a^5 + 2*a^4 + 2*a^2]~, [x^2 + (a^6 + 6*a^5 + 4*a^4 + 5*a^3
- + 4)*x + 4, 1; x^2 + (2*a^6 + 5*a^5 + a^4 + 3*a^3 + 1)*x + 2, 1; x^2 + (4*a
-^6 + 3*a^5 + 2*a^4 + 6*a^3 + 2)*x + 1, 1], [0, 0, 0, a, 1, 0, 2*a, 4, 6*a^2,
- a, 4, 6*a^3 + 2, a^6 + 4*a^5 + 4*a^4 + 6*a^2 + a + 4, Vecsmall([4]), [a, [V
-ecsmall([140737488355328, 0, 1]), Vecsmall([140737488355328, 1]), [Vecsmall(
-[140737488355328, 6]), Vecsmall([140737488355328]), Vecsmall([14073748835532
-8]), Vecsmall([140737488355328])]]], [0, 0, 0, 0]], a/x, (x + a)/(x + 6*a), 
-4*a^6 + 4*a^5 + 2*a^4 + 3*a^3 + a^2 + a + 6, 274514, a, [x + (2*a^6 + 6*a^5 
-+ 5*a^2 + 2*a + 1), 1; x + (5*a^6 + a^5 + 2*a^2 + 5*a), 1], [2*a^6 + 6*a^5 +
- 5*a^2 + 2*a, 5*a^6 + a^5 + 2*a^2 + 5*a + 6]~]
-? test(precprime(2^32),3)
-[a^2 + 3*a + 1, 3435973833*a^2 + 3435973833, 2863311528*a + 2863311528, a + 
-3435973833, 3579139409*a^2 + 2863311528, 3579139410*a + 3579139410, 1024*a +
- 1024, 859832319*a + 859832319, 4294967290*a^2 + 4294967290*a + 4, 429496729
-0*a, a^2, 3885163399*a^2 + 2553150559*a + 523234686, a^2 + a + 1, a^2 + a + 
-1, 1, 4264202413*a^2 + 356078407*a + 3929909005, Mod(25, 4294967291), Mod(42
-94967290, 4294967291), Mod(1, 4294967291)*x^3 + Mod(1, 4294967291)*x^2 + Mod
-(4294967287, 4294967291)*x + Mod(1, 4294967291), Mod(1, 4294967291)*x^3 + Mo
-d(1, 4294967291)*x^2 + Mod(4294967287, 4294967291)*x + Mod(1, 4294967291), [
-a, a^2 + a + 4294967288, 4294967290*a^2 + 4294967289*a + 2]~, [x + (34444702
-3*a^2 + 1616586690*a + 252460086), 1; x + (3340051543*a^2 + 1627577691*a + 2
-021233148), 1; x^2 + (954915748*a^2 + 2667389600*a + 2273734143)*x + (816322
-992*a^2 + 830924795*a + 1995175223), 1; x^2 + (3950520268*a^2 + 2678380601*a
- + 4042507205)*x + (1642837480*a^2 + 2548350348*a + 1670376662), 1], [0, 0, 
-0, a, 1, 0, 2*a, 4, 4294967290*a^2, 4294967243*a, 4294966427, 64*a^2 + 42949
-67035*a + 4294966923, 3618892287*a^2 + 1482857269*a + 1021597254, Vecsmall([
-4]), [a, [Vecsmall([140737488355328, 0, 1296]), Vecsmall([140737488355328, 4
-6656]), [Vecsmall([140737488355328, 6]), Vecsmall([140737488355328]), Vecsma
-ll([140737488355328]), Vecsmall([140737488355328])]]], [0, 0, 0, 0]], a/x, (
-x + a)/(x + 4294967290*a), 4020082597*a^2 + 70712658*a + 4018965070, 3689348
-8070109691946, a, [x + (1365670490*a^2 + 3373566631*a + 4083593885), 1; x + 
-(2929296801*a^2 + 921400660*a + 211373407), 1], [1365670490*a^2 + 3373566631
-*a + 4083593884, 2929296801*a^2 + 921400660*a + 211373406]~]
-? test(nextprime(2^32),3)
-[a^2 + 3*a + 1, a^2 + 4294967310, 1431655771*a + 1431655771, a + 3435973849,
- 3579139425*a^2 + 1431655772, 715827886*a + 715827886, 1024*a + 1024, 114504
-4996*a + 1145044996, a^2 + a + 4294967309, 4294967310*a, a^2, 264190711*a^2 
-+ 2629464558*a + 2494776416, 2086193154*a^2 + 2086193154*a + 2086193154, 220
-8774156*a^2 + 2208774156*a + 2208774156, 2086193154, 996804783*a^2 + 2908221
-018*a + 1206110100, Mod(13, 4294967311), Mod(4294967310, 4294967311), Mod(1,
- 4294967311)*x^3 + Mod(1, 4294967311)*x^2 + Mod(4294967309, 4294967311)*x + 
-Mod(4294967310, 4294967311), Mod(1, 4294967311)*x^3 + Mod(1, 4294967311)*x^2
- + Mod(4294967309, 4294967311)*x + Mod(4294967310, 4294967311), [a, a^2 + 42
-94967309, 4294967310*a^2 + 4294967310*a + 1]~, [x^2 + (2086193155*a^2 + 1225
-81001)*x + 2086193154, 1; x^2 + (2208774157*a^2 + 4172386308)*x + 2208774156
-, 1; x^2 + (4294967310*a^2 + 2)*x + 1, 1], [0, 0, 0, a, 1, 0, 2*a, 4, 429496
-7310*a^2, 4294967263*a, 4294966447, 64*a^2 + 4294967183*a + 4294966815, 1484
-088443*a^2 + 1141114953*a + 4283364322, Vecsmall([4]), [a, [Vecsmall([140737
-488355328, 0, 1296]), Vecsmall([140737488355328, 46656]), [Vecsmall([1407374
-88355328, 6]), Vecsmall([140737488355328]), Vecsmall([140737488355328]), Vec
-small([140737488355328])]]], [0, 0, 0, 0]], a/x, (x + a)/(x + 4294967310*a),
- 4204026293*a^2 + 2068287144*a + 232863018, 6148914735617846011, a, [x + (26
-8392743*a^2 + 2459390605*a + 1304316255), 1; x + (4026574568*a^2 + 183557670
-6*a + 2990651057), 1], [268392743*a^2 + 2459390605*a + 1304316254, 402657456
-8*a^2 + 1835576706*a + 2990651056]~]
-? test2(p)=ffgen(x*Mod(1,p));g=ffprimroot(ffgen((x+1)*Mod(1,p)),&o);print([g,o]);fflog(g^17,g,o);
-? test2(2)
-[1, [1, matrix(0,2)]]
-0
-? test2(3)
-[2, [2, Mat([2, 1])]]
-1
-? test2(46744073709551653)
-[2, [46744073709551652, [2, 2; 3, 1; 7, 1; 37, 1; 1036513, 1; 14510113, 1]]]
-[]
-? test2(precprime(1<<32))
-[2, [4294967290, [2, 1; 5, 1; 19, 1; 22605091, 1]]]
-17
-? for(i=1,10,print(ffnbirred(11,i)));
-11
-55
-440
-3630
-32208
-295020
-2783880
-26793030
-261994040
-2593726344
-? for(i=1,10,print(ffnbirred(11,i,1)));
-11
-66
-506
-4136
-36344
-331364
-3115244
-29908274
-291902314
-2885628658
-? do(f,p,T)=centerlift(lift(polrootsff(f,p,T)));
-? do(x^3+x^2+x-1,3,t^3+t^2+t-1)
-[t, t^2 + 1, -t^2 - t + 1]~
-? t=ffgen(3^3,'t);do((x^3+x^2+x-1)*t^0,t.p,t.mod)
-[t, t^2 + 1, -t^2 - t + 1]~
-? polrootsff(x^4+1,2,y^2+y+1)
-[Mod(Mod(1, 2), Mod(1, 2)*y^2 + Mod(1, 2)*y + Mod(1, 2))]~
-? t=ffgen(7^4);fflog(t^6,t^2)
-3
-? t=ffgen(2^64)^((2^64-1)\5);1/t
-x^58 + x^57 + x^56 + x^52 + x^51 + x^49 + x^46 + x^45 + x^42 + x^39 + x^36 +
- x^35 + x^32 + x^30 + x^29 + x^25 + x^23 + x^22 + x^21 + x^20 + x^19 + x^12 
-+ x^8 + x^7 + x^6 + x^2
-? t=ffgen(('t^2+'t+1)*Mod(1,2));
-? factorff(x^12+t*x^10+x^6+(t+1)*x^2+1)
-
-[x + 1 6]
-
-[x + t 6]
-
-? polrootsff(x^2-x-ffgen((v^2+1)*Mod(1,3)))
-[]~
-? polrootsff(2*x+1,2,y)
-[]~
-? sqrt(Mod(-1,4296540161))
-Mod(1086811600, 4296540161)
-? sqrt(Mod(-1,18446744073944432641))
-Mod(6687681666819568403, 18446744073944432641)
-? centerlift(factorcantor(prod(i=-10,10,(x^2-i)),2^64+13)[,1])
-[x, x + 1, x + 2, x + 3, x + 248527397336721375, x + 2370518075556110396, x 
-+ 2888582621843189425, x + 4741036151112220792, x + 5193293969518580612, x +
- 6494187761904104278, x + 7111554226668331188, x + 7312212166335540022, x + 
-7562574061564804959, x - 7562574061564804959, x - 7312212166335540022, x - 7
-111554226668331188, x - 6494187761904104278, x - 5193293969518580612, x - 47
-41036151112220792, x - 2888582621843189425, x - 2370518075556110396, x - 248
-527397336721375, x - 3, x - 2, x - 1, x^2 + 2, x^2 + 3, x^2 + 8, x^2 + 10, x
-^2 - 10, x^2 - 8, x^2 - 3, x^2 - 2]~
-? #polrootsff(x^107+2*x^3+1,3,ffinit(3,107,'a))
-107
-? t=ffprimroot(ffgen(2^61));fflog(t^1234567891012345678,t)
-1234567891012345678
-? t=ffprimroot(ffgen(3^23));fflog(t^12345678910,t)
-12345678910
-? t=ffprimroot(ffgen(5^23));fflog(t^1234567891012345,t)
-1234567891012345
-? t=ffprimroot(ffgen(5^17));fflog(t^123456789101,t)
-123456789101
-? ffgen(x^2+x+Mod(1,3))
-  ***   at top-level: ffgen(x^2+x+Mod(1,3)
-  ***                 ^--------------------
-  *** ffgen: not an irreducible polynomial in ffgen: x^2 + x + 1.
-? conjvec(Mod(x,x^2+Mod(1,3)))
-[Mod(Mod(1, 3)*x, Mod(1, 3)*x^2 + Mod(1, 3)), Mod(Mod(2, 3)*x, Mod(1, 3)*x^2
- + Mod(1, 3))]~
-? t=ffgen(5^4,'t);
-? factor((x^24-1)*t^0)
-
-[                x + 1 1]
-
-[                x + 2 1]
-
-[                x + 3 1]
-
-[                x + 4 1]
-
-[      x + (t^3 + 4*t) 1]
-
-[  x + (t^3 + 4*t + 1) 1]
-
-[  x + (t^3 + 4*t + 2) 1]
-
-[  x + (t^3 + 4*t + 3) 1]
-
-[  x + (t^3 + 4*t + 4) 1]
-
-[    x + (2*t^3 + 3*t) 1]
-
-[x + (2*t^3 + 3*t + 1) 1]
-
-[x + (2*t^3 + 3*t + 2) 1]
-
-[x + (2*t^3 + 3*t + 3) 1]
-
-[x + (2*t^3 + 3*t + 4) 1]
-
-[    x + (3*t^3 + 2*t) 1]
-
-[x + (3*t^3 + 2*t + 1) 1]
-
-[x + (3*t^3 + 2*t + 2) 1]
-
-[x + (3*t^3 + 2*t + 3) 1]
-
-[x + (3*t^3 + 2*t + 4) 1]
-
-[      x + (4*t^3 + t) 1]
-
-[  x + (4*t^3 + t + 1) 1]
-
-[  x + (4*t^3 + t + 2) 1]
-
-[  x + (4*t^3 + t + 3) 1]
-
-[  x + (4*t^3 + t + 4) 1]
-
-? factorff(Pol(0),t.p,t.mod)
-
-[0 1]
-
-? factorff(Pol(1),t.p,t.mod)
-[;]
-? factorff(x^4-t,t.p,t.mod)
-
-[Mod(Mod(1, 5), Mod(1, 5)*t^4 + Mod(1, 5)*t^3 + Mod(2, 5)*t^2 + Mod(1, 5)*t 
-+ Mod(3, 5))*x^4 + Mod(Mod(0, 5), Mod(1, 5)*t^4 + Mod(1, 5)*t^3 + Mod(2, 5)*
-t^2 + Mod(1, 5)*t + Mod(3, 5))*x^3 + Mod(Mod(0, 5), Mod(1, 5)*t^4 + Mod(1, 5
-)*t^3 + Mod(2, 5)*t^2 + Mod(1, 5)*t + Mod(3, 5))*x^2 + Mod(Mod(0, 5), Mod(1,
- 5)*t^4 + Mod(1, 5)*t^3 + Mod(2, 5)*t^2 + Mod(1, 5)*t + Mod(3, 5))*x + Mod(M
-od(4, 5)*t, Mod(1, 5)*t^4 + Mod(1, 5)*t^3 + Mod(2, 5)*t^2 + Mod(1, 5)*t + Mo
-d(3, 5)) 1]
-
-? test(q)=my(t=ffgen(q,'t),m=[t,t^2,1+t^3;1+t,1+t^2,1+t^3]);print(matker(m));print(matimage(m));print(matrank(m));my(M=[t,2*t^0,3*t^0;t,t^2,1+t^3;1+t,1+t^2,1+t^3]);print(matdet(M));print(M^(-1)*M);my(v=[t^0,t^1,t^2]~);print(M*v);
-? test(2^5)
-[t^4 + t^3; t^4 + t^3; 1]
-[t, t^2; t + 1, t^2 + 1]
-2
-t^4 + t^2
-[1, 0, 0; 0, 1, 0; 0, 0, 1]
-[t^2 + t, t^4 + t^3 + 1, t^4 + t^3 + t]~
-? test(7^5)
-[3*t^4 + 5*t^3 + 6*t^2 + 2*t; 4*t^4 + 2*t^3 + t^2 + 5*t; 1]
-[t, t^2; t + 1, t^2 + 1]
-2
-6*t^4 + 2*t^3 + 4*t^2 + 2*t + 2
-[1, 0, 0; 0, 1, 0; 0, 0, 1]
-[3*t^2 + 3*t, 6*t^4 + 5*t^3 + 4*t^2 + 5*t + 6, 6*t^4 + 5*t^3 + 4*t^2 + 6*t]~
-? test((2^64+13)^5)
-[3*t^4 + 5*t^3 + 18446744073709551621*t^2 + 18446744073709551617*t; 18446744
-073709551626*t^4 + 18446744073709551624*t^3 + 8*t^2 + 12*t; 1]
-[t, t^2; t + 1, t^2 + 1]
-2
-18446744073709551628*t^4 + 2*t^3 + 18446744073709551626*t^2 + 2*t + 2
-[1, 0, 0; 0, 1, 0; 0, 0, 1]
-[3*t^2 + 3*t, 18446744073709551628*t^4 + 5*t^3 + 4*t^2 + 1844674407370955162
-7*t + 18446744073709551628, 18446744073709551628*t^4 + 5*t^3 + 4*t^2 + 18446
-744073709551628*t]~
-? p=2^64+13;g=ffprimroot(ffgen(p^2),&o);a=2*g^0;
-? v=[I,-1,Mat(1),matid(2)/2];
-? for(i=1,#v,print(iferr(fflog(a,g,v[i]),E,E)));
-error("incorrect type in generic discrete logarithm (order factorization) (t
-_COMPLEX).")
-error("incorrect type in generic discrete logarithm (order factorization) (t
-_INT).")
-error("incorrect type in factorback [not a factorization] (t_MAT).")
-error("incorrect type in factorback [not an exponent vector] (t_COL).")
-? g^fflog(a,g,o)==a
-1
-? print("Total time spent: ",gettime);
-Total time spent: 1536
diff --git a/src/test/64/incgam b/src/test/64/incgam
deleted file mode 100644
index 8e40dcf..0000000
--- a/src/test/64/incgam
+++ /dev/null
@@ -1,73 +0,0 @@
-      1/2,          -100: 5.0 e-18
-   10 - I,    19 + 236*I: 3.4 e-18
-   10 - I,          -100: 3.8 e-18
-1 + 128*I,       -1/10*I: 1.9 e-17
-1 + 128*I, 1/10 - 1/10*I: 6.5 e-18
-      1/2,          -100: 1.0 e-37
-   10 - I,    19 + 236*I: 6.3 e-37
-   10 - I,          -100: 5.8 e-37
-1 + 128*I,       -1/10*I: 8.6 e-37
-1 + 128*I, 1/10 - 1/10*I: 2.1 e-37
-      1/2,          -100: 3.8 e-43
-   10 - I,          -100: 4.1 e-56
-1: -37
-2: -37
-3: -38
-4: -39
-5: -37
-6: -37
-7: oo
-8: -37
-9: oo
-10: -34
-11: oo
-12: -41
-13: -40
-1: -75
-2: -75
-3: -77
-4: -77
-5: -76
-6: -75
-7: -76
-8: -75
-9: -76
-10: -72
-11: -77
-12: -79
-13: -79
-6.4517096605632180286130396475962100207 E-43429453
--0.0096304981549875294045330406967324266004 + 0.0104448408245333075664155335
-90425336552*I
-3.6835977616820321802351926205081189877 E-46
-0.033148544714002591996135923592143390256
-[0.048900510708061119567239835228049522318, 0.003779352409848906478874860132
-4664148561, 0.00036008245216265865929539411577179720024, 3.76656228439249017
-72557995950752726710 E-5, 4.1569689296853242774028598102781906834 E-6]
-   realprecision = 1001 significant digits (1000 digits displayed)
-3.68359776168203218023519262050811898765522013690956761970324308577568037914
-9250955037826947160993268362230577110061496836716989214907855071445311470563
-2214214800120311153618035942174272929063643378947115395627352197174490634249
-2683012033541722036066655328102708417224861577032395241919552543821704857579
-1038133881414147745573634350151991309184589035264539926631750948004685156693
-1899374361029305819637078712617022128735026710549374269865118275697787239064
-9991027682952231969799549304090829468335748935154281470949071433111492071075
-1767849583590888814450823588721920568263412763123076003634199144923928930230
-2664745888505585350305095849977148442159142952183358896948374051498045266578
-8430696482922647521423833733233609936621457658644695029880537347596251466117
-5788754599498196161120801923825870392159899899969875656841020930930028966473
-7128930613953196310035735416832096667412906792274453172606232569623655768685
-0600705332240514673617947823961471228466621963387238011480537605649806838965
-7919746393664 E-46
-   realprecision = 481 significant digits
-4.75192490656016273728795810646514224344948226385534946774854953981091171184
-5548377731754871666027106541752645628899410605265552482172045603954059223044
-9909582386495215175154235730928812285673186372640110666892550763379643115805
-1645655068324986893656866348640914630478382436361571896386505720797343025328
-1801089025819604231751731641093222001525360979162684147070957434471241677012
-3171321323534000876101297696945758112884328591356813522962187412618386959055
-56983544264467232044835371 E-68
-  ***   at top-level: eint1(0)
-  ***                 ^--------
-  *** eint1: domain error in eint1: x = 0
-Total time spent: 84
diff --git a/src/test/64/isprime b/src/test/64/isprime
deleted file mode 100644
index 5cb0414..0000000
--- a/src/test/64/isprime
+++ /dev/null
@@ -1,25 +0,0 @@
-1
-1
-1
-
-[      2 5 1]
-
-[      3 2 1]
-
-[1000003 2 1]
-
-[1000033 2 1]
-
-
-[      2 3 1]
-
-[     29 2 1]
-
-[1000003 2 1]
-
-[1, 1, 0]
-[1, Mat([2, 2, 1]), 0]
-[1, 1, 0]
-[0, 1, 0, 1]
-1
-Total time spent: 3036
diff --git a/src/test/64/kernel b/src/test/64/kernel
deleted file mode 100644
index f28bcc8..0000000
--- a/src/test/64/kernel
+++ /dev/null
@@ -1,23 +0,0 @@
-INT: 187654321
-conv:4000000000000003  000000000b2f60b1  
-+:4000000000000003  000000000a72ff63  
--:4000000000000003  000000000bebc1ff  
-*:c000000000000003  00083b0b5e0e86ee  
-/:c000000000000003  000000000000000f  
-rem:4000000000000003  000000000025ad1f  
-pow:
-4000000000000003  007d1b13db833a61  
-4000000000000004  00003d2374418fff  02bee98cc29618c1  
-4000000000000006  000000000e99ea50  3d586253467c3cea  a7f1a74285bba548  639e3a9d8890c181  
-4000000000000009  00d5322ab115c7b2  9cf0c5711679c253  8cea7ca01cbe7596  78ae7d09c969dc26  cd42e2ad51204d31  635bced866d36dbb  0351ebad5363c301  
-4000000000000010  0000b18c84df6289  66df9491766a39a4  0685a8a3cfc68c74  4d9dcb9102634462  b398839e1a6892ef  5efe0281bcae4afb  eb64fcabf930fa7a  00f013352a5dc7c3  4295b5c3b031c96e  a5c190798e647dac  09e2091e67abbc58  c118d1b776f5e31c  e97a9180140e859c  64a53cad0d508601  
-invmod:4000000000000010  000089fe3c4ba859  b9472dacd0585e64  b5311881edf8024b  aaf6ce9e98d94a2d  b253c748bc185be1  6de1e5f8831bbecd  a3d629dc0fc9440e  b0ab325d53dd21c5  9fb7fc20cc22d98c  e8fe6eca928c7f4f  a3861061a7ab0bdc  71deda2617a28387  774875639f0f88ac  424ca4d53dcae2a5  
-
-REAL: 187654321.000000
-conv1:600000000000001b  b2f60b1000000000  
-conv2:600000000000001b  b2f60b1000000000  
-+:600000000000001b  a72ff63000000000  
--:600000000000001b  bebc1ff000000000  
-*:e000000000000033  83b0b5e0e86ee000  
-/:e000000000000003  f33334820be1df0a  
-gcc bug?:6000000000000000  c000000000000000  
diff --git a/src/test/64/member b/src/test/64/member
deleted file mode 100644
index 50827a1..0000000
--- a/src/test/64/member
+++ /dev/null
@@ -1,319 +0,0 @@
-.pol: x
-.a1: 0
-.a2: 0
-.a3: 0
-.a4: 0
-.a6: 0
-NF
-.codiff: [1, 553/1105; 0, 1/1105]
-.diff: [1105, 553; 0, 1]
-.disc: 1105
-.index: 2
-.nf: [y^2 - 1105, [2, 0], 1105, 2, [[1, -17.12077013859466140231529077105260
-9448; 1, 16.120770138594661402315290771052609448], [1, -17.12077013859466140
-2315290771052609448; 1, 16.120770138594661402315290771052609448], [1, -17; 1
-, 16], [2, -1; -1, 553], [1105, 553; 0, 1], [553, 1; 1, 2], [1105, [553, 276
-; 1, 552]], [5, 13, 17]], [-33.241540277189322804630581542105218897, 33.2415
-40277189322804630581542105218897], [1, 1/2*y - 1/2], [1, 1; 0, 2], [1, 0, 0,
- 276; 0, 1, 1, -1]]
-.pol: y^2 - 1105
-.r1: 2
-.r2: 0
-.roots: [-33.241540277189322804630581542105218897, 33.2415402771893228046305
-81542105218897]
-.sign: [2, 0]
-.t2: [2, -1.0000000000000000000000000000000000000; -1.0000000000000000000000
-000000000000000, 553.00000000000000000000000000000000000]
-.zk: [1, 1/2*y - 1/2]
-NF chvar
-  *** nfinit: Warning: non-monic polynomial. Result of the form [nf,c].
-.codiff: [1/2, 0; 0, 1/4]
-.diff: [4, 0; 0, 2]
-.disc: -8
-.index: 1
-.nf: [y^2 + 2, [0, 1], -8, 1, [Mat([1, 0.E-38 + 1.41421356237309504880168872
-42096980786*I]), [1, 1.4142135623730950488016887242096980786; 1, -1.41421356
-23730950488016887242096980786], [1, 1; 1, -1], [2, 0; 0, -4], [4, 0; 0, 2], 
-[2, 0; 0, -1], [2, [0, -2; 1, 0]], [2]], [0.E-38 + 1.41421356237309504880168
-87242096980786*I], [1, y], [1, 0; 0, 1], [1, 0, 0, -2; 0, 1, 1, 0]]
-.pol: y^2 + 2
-.r1: 0
-.r2: 1
-.roots: [0.E-38 + 1.4142135623730950488016887242096980786*I]
-.sign: [0, 1]
-.t2: [2, 0.E-38; 0.E-38, 4.0000000000000000000000000000000000000]
-.zk: [1, y]
-BNF
-.bnf: [[2, 0; 0, 2], [1, 1, 0; 1, 0, 1], [10.9503854058256053302677508250179
-37393 + 3.1415926535897932384626433832795028842*I; -10.950385405825605330267
-750825017937393 + 6.2831853071795864769252867665590057684*I], [-2.8070134016
-636593080928506577483570863 + 6.2831853071795864769252867665590057684*I, -6.
-4656286076812397829259659980344686073 + 6.2831853071795864769252867665590057
-684*I, 6.3140644011531557847583424971265245465 + 4.701977403289150032 E-38*I
-, 0, 0; 2.8070134016636593080928506577483570863 + 3.141592653589793238462643
-3832795028842*I, 6.4656286076812397829259659980344686073 + 3.141592653589793
-2384626433832795028842*I, -6.3140644011531557847583424971265245465 + 7.05296
-6104933725048 E-38*I, 0, 0], [[2, [-1, 1]~, 1, 1, [0, 276; 1, -1]], [3, [0, 
-2]~, 1, 1, [-1, -276; -1, 0]], [5, [1, 2]~, 2, 1, [1, 552; 2, -1]], [2, [2, 
-1]~, 1, 1, [1, 276; 1, 0]], [3, [2, 2]~, 1, 1, [0, -276; -1, 1]]], 0, [y^2 -
- 1105, [2, 0], 1105, 2, [[1, -17.120770138594661402315290771052609448; 1, 16
-.120770138594661402315290771052609448], [1, -17.1207701385946614023152907710
-52609448; 1, 16.120770138594661402315290771052609448], [1, -17; 1, 16], [2, 
--1; -1, 553], [1105, 553; 0, 1], [553, 1; 1, 2], [1105, [553, 276; 1, 552]],
- [5, 13, 17]], [-33.241540277189322804630581542105218897, 33.241540277189322
-804630581542105218897], [1, 1/2*y - 1/2], [1, 1; 0, 2], [1, 0, 0, 276; 0, 1,
- 1, -1]], [[4, [2, 2], [[2, 0; 0, 1], [3, 1; 0, 1]]], 10.9503854058256053302
-67750825017937393, 1, [2, -1], [857*y - 28488]], [[-1, 0; 0, -1], [[0, 0], [
-0, 0]], [[2.8070134016636593080928506577483570863 - 6.2831853071795864769252
-867665590057684*I, -2.8070134016636593080928506577483570863 - 3.141592653589
-7932384626433832795028842*I], [6.4656286076812397829259659980344686073 - 6.2
-831853071795864769252867665590057684*I, -6.465628607681239782925965998034468
-6073 - 3.1415926535897932384626433832795028842*I]]], [0, 0]]
-.clgp: [4, [2, 2], [[2, 0; 0, 1], [3, 1; 0, 1]]]
-.codiff: [1, 553/1105; 0, 1/1105]
-.cyc: [2, 2]
-.diff: [1105, 553; 0, 1]
-.disc: 1105
-.fu: [Mod(857*y - 28488, y^2 - 1105)]
-.gen: [[2, 0; 0, 1], [3, 1; 0, 1]]
-.index: 2
-.nf: [y^2 - 1105, [2, 0], 1105, 2, [[1, -17.12077013859466140231529077105260
-9448; 1, 16.120770138594661402315290771052609448], [1, -17.12077013859466140
-2315290771052609448; 1, 16.120770138594661402315290771052609448], [1, -17; 1
-, 16], [2, -1; -1, 553], [1105, 553; 0, 1], [553, 1; 1, 2], [1105, [553, 276
-; 1, 552]], [5, 13, 17]], [-33.241540277189322804630581542105218897, 33.2415
-40277189322804630581542105218897], [1, 1/2*y - 1/2], [1, 1; 0, 2], [1, 0, 0,
- 276; 0, 1, 1, -1]]
-.no: 4
-.pol: y^2 - 1105
-.r1: 2
-.r2: 0
-.reg: 10.950385405825605330267750825017937393
-.roots: [-33.241540277189322804630581542105218897, 33.2415402771893228046305
-81542105218897]
-.sign: [2, 0]
-.t2: [2, -1.0000000000000000000000000000000000000; -1.0000000000000000000000
-000000000000000, 553.00000000000000000000000000000000000]
-.tu: [2, Mod(-1, y^2 - 1105)]
-.zk: [1, 1/2*y - 1/2]
-BNR
-.bid: [[[4, 0; 0, 4], [0, 0]], [4, [2, 2], [[1, -2]~, [-1, -2]~]], [[2, [-1,
- 1]~, 1, 1, [0, 276; 1, -1]], 2; [2, [2, 1]~, 1, 1, [1, 276; 1, 0]], 2], [[[
-[1], [1], [[1, 0]~], [Vecsmall([])], 1], [[2], [-1], [[1, -2]~], [Vecsmall([
-])], Mat([1/2, -1/2])]], [[[1], [1], [[1, 0]~], [Vecsmall([])], 1], [[2], [-
-1], [[-1, -2]~], [Vecsmall([])], Mat([1/2, 0])]], [[], [], []]], [0, 1, 0, 0
-; 0, 0, 0, 1]]
-.bnf: [[2, 0; 0, 2], [1, 1, 0; 1, 0, 1], [10.9503854058256053302677508250179
-37393 + 3.1415926535897932384626433832795028842*I; -10.950385405825605330267
-750825017937393 + 6.2831853071795864769252867665590057684*I], [-2.8070134016
-636593080928506577483570863 + 6.2831853071795864769252867665590057684*I, -6.
-4656286076812397829259659980344686073 + 6.2831853071795864769252867665590057
-684*I, 6.3140644011531557847583424971265245465 + 4.701977403289150032 E-38*I
-, 0, 0; 2.8070134016636593080928506577483570863 + 3.141592653589793238462643
-3832795028842*I, 6.4656286076812397829259659980344686073 + 3.141592653589793
-2384626433832795028842*I, -6.3140644011531557847583424971265245465 + 7.05296
-6104933725048 E-38*I, 0, 0], [[2, [-1, 1]~, 1, 1, [0, 276; 1, -1]], [3, [0, 
-2]~, 1, 1, [-1, -276; -1, 0]], [5, [1, 2]~, 2, 1, [1, 552; 2, -1]], [2, [2, 
-1]~, 1, 1, [1, 276; 1, 0]], [3, [2, 2]~, 1, 1, [0, -276; -1, 1]]], 0, [y^2 -
- 1105, [2, 0], 1105, 2, [[1, -17.120770138594661402315290771052609448; 1, 16
-.120770138594661402315290771052609448], [1, -17.1207701385946614023152907710
-52609448; 1, 16.120770138594661402315290771052609448], [1, -17; 1, 16], [2, 
--1; -1, 553], [1105, 553; 0, 1], [553, 1; 1, 2], [1105, [553, 276; 1, 552]],
- [5, 13, 17]], [-33.241540277189322804630581542105218897, 33.241540277189322
-804630581542105218897], [1, 1/2*y - 1/2], [1, 1; 0, 2], [1, 0, 0, 276; 0, 1,
- 1, -1]], [[4, [2, 2], [[2, 0; 0, 1], [3, 1; 0, 1]]], 10.9503854058256053302
-67750825017937393, 1, [2, -1], [857*y - 28488]], [[-1, 0; 0, -1], [[0, 0], [
-0, 0]], [[2.8070134016636593080928506577483570863 - 6.2831853071795864769252
-867665590057684*I, -2.8070134016636593080928506577483570863 - 3.141592653589
-7932384626433832795028842*I], [6.4656286076812397829259659980344686073 - 6.2
-831853071795864769252867665590057684*I, -6.465628607681239782925965998034468
-6073 - 3.1415926535897932384626433832795028842*I]]], [0, [Mat([[16, -1]~, 1]
-), Mat([[-137, -8]~, 1])]]]
-.clgp: [4, [2, 2]]
-.codiff: [1, 553/1105; 0, 1/1105]
-.cyc: [2, 2]
-.diff: [1105, 553; 0, 1]
-.disc: 1105
-.index: 2
-.mod: [[4, 0; 0, 4], [0, 0]]
-.nf: [y^2 - 1105, [2, 0], 1105, 2, [[1, -17.12077013859466140231529077105260
-9448; 1, 16.120770138594661402315290771052609448], [1, -17.12077013859466140
-2315290771052609448; 1, 16.120770138594661402315290771052609448], [1, -17; 1
-, 16], [2, -1; -1, 553], [1105, 553; 0, 1], [553, 1; 1, 2], [1105, [553, 276
-; 1, 552]], [5, 13, 17]], [-33.241540277189322804630581542105218897, 33.2415
-40277189322804630581542105218897], [1, 1/2*y - 1/2], [1, 1; 0, 2], [1, 0, 0,
- 276; 0, 1, 1, -1]]
-.no: 4
-.pol: y^2 - 1105
-.r1: 2
-.r2: 0
-.roots: [-33.241540277189322804630581542105218897, 33.2415402771893228046305
-81542105218897]
-.sign: [2, 0]
-.t2: [2, -1.0000000000000000000000000000000000000; -1.0000000000000000000000
-000000000000000, 553.00000000000000000000000000000000000]
-.zk: [1, 1/2*y - 1/2]
-.zkst: [4, [2, 2], [[1, -2]~, [-1, -2]~]]
-RNF
-.disc: [[4420, 553; 0, 1], [1, 2]~]
-.index: [2, 0; 0, 1]
-.nf: [y^2 - 1105, [2, 0], 1105, 2, [[1, -17.12077013859466140231529077105260
-9448; 1, 16.120770138594661402315290771052609448], [1, -17.12077013859466140
-2315290771052609448; 1, 16.120770138594661402315290771052609448], [1, -17; 1
-, 16], [2, -1; -1, 553], [1105, 553; 0, 1], [553, 1; 1, 2], [1105, [553, 276
-; 1, 552]], [5, 13, 17]], [-33.241540277189322804630581542105218897, 33.2415
-40277189322804630581542105218897], [1, 1/2*y - 1/2], [1, 1; 0, 2], [1, 0, 0,
- 276; 0, 1, 1, -1]]
-.pol: x^2 - y
-.polabs: x^4 - 1105
-.zk: [[1, x - 1], [1, [1, 1/2; 0, 1/2]]]
-QUADCLASSUNIT
-.clgp: [4, [2, 2], [Qfb(2, 31, -18, 0.E-57), Qfb(3, 29, -22, 0.E-57)]]
-.cyc: [2, 2]
-.gen: [Qfb(2, 31, -18, 0.E-57), Qfb(3, 29, -22, 0.E-57)]
-.no: 4
-.reg: 10.950385405825605330267750825017937393
-GAL
-.gen: [Vecsmall([2, 1])]
-.group: [Vecsmall([1, 2]), Vecsmall([2, 1])]
-.mod: 1341068619663964900807
-.orders: Vecsmall([2])
-.p: 7
-.pol: x^2 - 2
-.roots: [1323350126780315668282, 17718492883649232525]~
-ELL
-.a1: 1
-.a2: 2
-.a3: 3
-.a4: 4
-.a6: 5
-.b2: 9
-.b4: 11
-.b6: 29
-.b8: 35
-.c4: -183
-.c6: -3429
-.area: 2.9719152678179096707716479509361896060
-.disc: -10351
-.eta: [3.1096482423243803285501491221965830079, 1.55482412116219016427507456
-10982915039 + 1.0643747452102737569438859937299427442*I]
-.gen: [[1, 2]]
-.j: 6128487/10351
-.omega: [2.7807400137667297710631976271813584994, 1.390370006883364885531598
-8135906792497 - 1.0687497763561930661592635474375038788*I]
-.roots: [-1.6189099322673713423780009396072169751, -0.3155450338663143288109
-9953019639151248 + 2.0925470969119586079816894466366945829*I, -0.31554503386
-631432881099953019639151248 - 2.0925470969119586079816894466366945829*I]~
-ELLFp
-.a1: Mod(1, 13)
-.a2: Mod(2, 13)
-.a3: Mod(3, 13)
-.a4: Mod(4, 13)
-.a6: Mod(5, 13)
-.b2: Mod(9, 13)
-.b4: Mod(11, 13)
-.b6: Mod(3, 13)
-.b8: Mod(9, 13)
-.c4: Mod(12, 13)
-.c6: Mod(3, 13)
-.cyc: [13]
-.disc: Mod(10, 13)
-.gen: [[Mod(6, 13), Mod(12, 13)]]
-.group: [13, [13], [[Mod(6, 13), Mod(12, 13)]]]
-.j: Mod(9, 13)
-.no: 13
-.p: 13
-ELLFq
-.a1: 1
-.a2: 2
-.a3: 3
-.a4: 4
-.a6: 5
-.b2: 9
-.b4: 11
-.b6: 3
-.b8: 9
-.c4: 12
-.c6: 3
-.cyc: [195]
-.disc: 10
-.gen: [[6*x + 1, x + 6]]
-.group: [195, [195], [[6*x + 1, x + 6]]]
-.j: 9
-.no: 195
-.p: 13
-ELLQp
-.a1: 1
-.a2: 2
-.a3: 3
-.a4: 4
-.a6: 5
-.b2: 9
-.b4: 11
-.b6: 29
-.b8: 35
-.c4: -183
-.c6: -3429
-.disc: -10351
-.j: 6128487/10351
-.p: 11
-.roots: [9 + O(11^2)]~
-.tate: [6 + 8*11 + 5*11^2 + O(11^4), Mod(u, u^2 + (5 + 2*11 + 5*11^2 + 10*11
-^3 + O(11^4))), 3*11 + 7*11^2 + O(11^4), [6 + 3*11 + O(11^4), 6 + 11 + 9*11^
-2 + 11^3 + O(11^4)]]
-FFELT
-.f: 3
-.mod: x^3 + x^2 + 1
-.p: 2
-.pol: x
-.f: 3
-.mod: x^3 + x^2 + x + 2
-.p: 3
-.pol: x
-.f: 2
-.mod: x^2 + x + 1
-.p: 18446744073709551629
-.pol: x
-INTMOD
-.mod: 3
-POLMOD
-.mod: x^2 + 1
-.pol: x
-QFB
-QUAD
-.disc: -4
-.fu: []
-.mod: x^2 + 1
-.pol: x^2 + 1
-.tu: [4, w]
-.zk: [1, x]
-PRID
-.e: 1
-.f: 1
-.gen: [2, [-1, 1]~]
-.p: 2
-MODPR
-.e: 1
-.f: 1
-.gen: [2, [-1, 1]~]
-.p: 2
-BID
-.bid: [[[4, 1; 0, 1], [0, 0]], [2, [2], [3]], Mat([[2, [-1, 1]~, 1, 1, [0, 2
-76; 1, -1]], 2]), [[[[1], [1], [1], [Vecsmall([])], 1], [[2], [-1], [-1], [V
-ecsmall([])], Mat([1/2, -1/2])]], [[], [], []]], Mat([0, 1])]
-.clgp: [2, [2], [3]]
-.cyc: [2]
-.gen: [3]
-.mod: [[4, 1; 0, 1], [0, 0]]
-.no: 2
-.zkst: [2, [2], [3]]
-BID (nogen)
-.bid: [[[4, 1; 0, 1], [0, 0]], [2, [2]], Mat([[2, [-1, 1]~, 1, 1, [0, 276; 1
-, -1]], 2]), [[[[1], [1], [1], [Vecsmall([])], 1], [[2], [-1], [-1], [Vecsma
-ll([])], Mat([1/2, -1/2])]], [[], [], []]], Mat([0, 1])]
-.clgp: [2, [2]]
-.cyc: [2]
-.mod: [[4, 1; 0, 1], [0, 0]]
-.no: 2
-.zkst: [2, [2]]
-Total time spent: 48
diff --git a/src/test/64/nf b/src/test/64/nf
deleted file mode 100644
index c3e87e0..0000000
--- a/src/test/64/nf
+++ /dev/null
@@ -1,361 +0,0 @@
-[85997496, [42998748, 2], [[408188227, 99620635; 0, 1], [2, 1; 0, 1]]]
-12.340047278667903334059769086970462250
-4.1894250945222025884896456921310573068
-20915648110955829231381594293324156411897455346679838307589120000
-571459344155975480004612560667633185714077696
-[54898, [54898], [[7, 0; 0, 1]]]
-[26, [26], [[19, 14, 5, 13; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1]]]
-[1, [], []]
-  *** zetakinit: Warning: non-monic polynomial. Result of the form [nf,c].
-  *** zetakinit: Warning: non-monic polynomial. Change of variables discarded.
-20/3
--5
-13
-0
-5/2
--1
-1024/243
--1
-31
--11
-1/32
-15853839
-1736217747
-Mod(4/3, y^5 - 4*y^3 + 2*y + 11)
-Mod(-1, y^5 - 4*y^3 + 2*y + 11)
-Mod(y^2 + y + 1, y^5 - 4*y^3 + 2*y + 11)
-Mod(y, y^5 - 4*y^3 + 2*y + 11)
-Mod(1/2, y^5 - 4*y^3 + 2*y + 11)
-Mod(5*y^4 + 4*y^3 - 12*y^2 - y - 5, y^5 - 4*y^3 + 2*y + 11)
-[4/3, 0, 0, 0, 0]~
-[-1, 0, 0, 0, 0]~
-[3, 1, 1, 0, 0]~
-[0, 1, 0, 0, 0]~
-[1/2, 0, 0, 0, 0]~
-[1, 2, 3, 4, 5]~
-(f)->for(i=1,#v,for(j=1,#v,print(f(nf,v[i],v[j]))))
-[8/3, 0, 0, 0, 0]~
-[1/3, 0, 0, 0, 0]~
-[13/3, 1, 1, 0, 0]~
-[4/3, 1, 0, 0, 0]~
-[11/6, 0, 0, 0, 0]~
-[7/3, 2, 3, 4, 5]~
-[1/3, 0, 0, 0, 0]~
-[-2, 0, 0, 0, 0]~
-[2, 1, 1, 0, 0]~
-[-1, 1, 0, 0, 0]~
-[-1/2, 0, 0, 0, 0]~
-[0, 2, 3, 4, 5]~
-[13/3, 1, 1, 0, 0]~
-[2, 1, 1, 0, 0]~
-[6, 2, 2, 0, 0]~
-[3, 2, 1, 0, 0]~
-[7/2, 1, 1, 0, 0]~
-[4, 3, 4, 4, 5]~
-[4/3, 1, 0, 0, 0]~
-[-1, 1, 0, 0, 0]~
-[3, 2, 1, 0, 0]~
-[0, 2, 0, 0, 0]~
-[1/2, 1, 0, 0, 0]~
-[1, 3, 3, 4, 5]~
-[11/6, 0, 0, 0, 0]~
-[-1/2, 0, 0, 0, 0]~
-[7/2, 1, 1, 0, 0]~
-[1/2, 1, 0, 0, 0]~
-[1, 0, 0, 0, 0]~
-[3/2, 2, 3, 4, 5]~
-[7/3, 2, 3, 4, 5]~
-[0, 2, 3, 4, 5]~
-[4, 3, 4, 4, 5]~
-[1, 3, 3, 4, 5]~
-[3/2, 2, 3, 4, 5]~
-[2, 4, 6, 8, 10]~
-[1, 0, 0, 0, 0]~
-[-4/3, 0, 0, 0, 0]~
-[-64/93, 16/31, 16/93, -8/31, 4/93]~
-[0, 4/33, 4/33, 0, -4/33]~
-[8/3, 0, 0, 0, 0]~
-[1587988/47561517, -165136/5284613, 41300/5284613, -212540/47561517, -78712/
-47561517]~
-[-3/4, 0, 0, 0, 0]~
-[1, 0, 0, 0, 0]~
-[16/31, -12/31, -4/31, 6/31, -1/31]~
-[0, -1/11, -1/11, 0, 1/11]~
-[-2, 0, 0, 0, 0]~
-[-396997/15853839, 123852/5284613, -30975/5284613, 53135/15853839, 19678/158
-53839]~
-[9/4, 3/4, 3/4, 0, 0]~
-[-3, -1, -1, 0, 0]~
-[1, 0, 0, 0, 0]~
-[1, 12/11, 1/11, 0, -1/11]~
-[6, 2, 2, 0, 0]~
-[1249690/15853839, -222317/5284613, 39600/5284613, -477392/15853839, 434/158
-53839]~
-[0, 3/4, 0, 0, 0]~
-[0, -1, 0, 0, 0]~
-[3/31, -10/31, 7/31, 5/31, -6/31]~
-[1, 0, 0, 0, 0]~
-[0, 2, 0, 0, 0]~
-[-672280/15853839, 150044/5284613, -148123/5284613, 73247/15853839, -53135/1
-5853839]~
-[3/8, 0, 0, 0, 0]~
-[-1/2, 0, 0, 0, 0]~
-[-8/31, 6/31, 2/31, -3/31, 1/62]~
-[0, 1/22, 1/22, 0, -1/22]~
-[1, 0, 0, 0, 0]~
-[396997/31707678, -61926/5284613, 30975/10569226, -53135/31707678, -9839/158
-53839]~
-[3/4, 3/2, 9/4, 3, 15/4]~
-[-1, -2, -3, -4, -5]~
-[-314/31, -59/31, 311/31, 14/31, -85/31]~
-[7, -27/11, 39/11, 5, 5/11]~
-[2, 4, 6, 8, 10]~
-[1, 0, 0, 0, 0]~
-[1, 0, 0, 0, 0]~
-[-1, 0, 0, 0, 0]~
-[-1, 1, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[3, 0, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[-1, 0, 0, 0, 0]~
-[1, 0, 0, 0, 0]~
-[1, 0, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[-2, 0, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[2, 1, 1, 0, 0]~
-[-3, -1, -1, 0, 0]~
-[1, 0, 0, 0, 0]~
-[1, 1, 0, 0, 0]~
-[6, 2, 2, 0, 0]~
-[0, 0, 0, 0, 0]~
-[0, 1, 0, 0, 0]~
-[0, -1, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[1, 0, 0, 0, 0]~
-[0, 2, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[1, 0, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[1, 2, 2, 3, 4]~
-[-1, -2, -3, -4, -5]~
-[-10, -2, 10, 0, -3]~
-[7, -2, 4, 5, 0]~
-[2, 4, 6, 8, 10]~
-[1, 0, 0, 0, 0]~
-[[1, 0, 0, 0, 0]~, [0, 0, 0, 0, 0]~]
-[[-1, 0, 0, 0, 0]~, [1/3, 0, 0, 0, 0]~]
-[[-1, 1, 0, 0, 0]~, [7/3, -2, 0, -1, 0]~]
-[[0, 0, 0, 0, 0]~, [4/3, 0, 0, 0, 0]~]
-[[3, 0, 0, 0, 0]~, [-1/6, 0, 0, 0, 0]~]
-[[0, 0, 0, 0, 0]~, [4/3, 0, 0, 0, 0]~]
-[[-1, 0, 0, 0, 0]~, [1/3, 0, 0, 0, 0]~]
-[[1, 0, 0, 0, 0]~, [0, 0, 0, 0, 0]~]
-[[1, 0, 0, 0, 0]~, [-4, -1, -1, 0, 0]~]
-[[0, 0, 0, 0, 0]~, [-1, 0, 0, 0, 0]~]
-[[-2, 0, 0, 0, 0]~, [0, 0, 0, 0, 0]~]
-[[0, 0, 0, 0, 0]~, [-1, 0, 0, 0, 0]~]
-[[2, 1, 1, 0, 0]~, [1/3, -1/3, -1/3, 0, 0]~]
-[[-3, -1, -1, 0, 0]~, [0, 0, 0, 0, 0]~]
-[[1, 0, 0, 0, 0]~, [0, 0, 0, 0, 0]~]
-[[1, 1, 0, 0, 0]~, [1, 0, 0, 0, 0]~]
-[[6, 2, 2, 0, 0]~, [0, 0, 0, 0, 0]~]
-[[0, 0, 0, 0, 0]~, [3, 1, 1, 0, 0]~]
-[[0, 1, 0, 0, 0]~, [0, -1/3, 0, 0, 0]~]
-[[0, -1, 0, 0, 0]~, [0, 0, 0, 0, 0]~]
-[[0, 0, 0, 0, 0]~, [0, 1, 0, 0, 0]~]
-[[1, 0, 0, 0, 0]~, [0, 0, 0, 0, 0]~]
-[[0, 2, 0, 0, 0]~, [0, 0, 0, 0, 0]~]
-[[0, 0, 0, 0, 0]~, [0, 1, 0, 0, 0]~]
-[[0, 0, 0, 0, 0]~, [1/2, 0, 0, 0, 0]~]
-[[0, 0, 0, 0, 0]~, [1/2, 0, 0, 0, 0]~]
-[[0, 0, 0, 0, 0]~, [1/2, 0, 0, 0, 0]~]
-[[0, 0, 0, 0, 0]~, [1/2, 0, 0, 0, 0]~]
-[[1, 0, 0, 0, 0]~, [0, 0, 0, 0, 0]~]
-[[0, 0, 0, 0, 0]~, [1/2, 0, 0, 0, 0]~]
-[[1, 2, 2, 3, 4]~, [-1/3, -2/3, 1/3, 0, -1/3]~]
-[[-1, -2, -3, -4, -5]~, [0, 0, 0, 0, 0]~]
-[[-10, -2, 10, 0, -3]~, [-6, -2, 1, 2, 1]~]
-[[7, -2, 4, 5, 0]~, [-5, 0, 0, 0, 0]~]
-[[2, 4, 6, 8, 10]~, [0, 0, 0, 0, 0]~]
-[[1, 0, 0, 0, 0]~, [0, 0, 0, 0, 0]~]
-[0, 0, 0, 0, 0]~
-[1/3, 0, 0, 0, 0]~
-[7/3, -2, 0, -1, 0]~
-[4/3, 0, 0, 0, 0]~
-[-1/6, 0, 0, 0, 0]~
-[4/3, 0, 0, 0, 0]~
-[1/3, 0, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[-4, -1, -1, 0, 0]~
-[-1, 0, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[-1, 0, 0, 0, 0]~
-[1/3, -1/3, -1/3, 0, 0]~
-[0, 0, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[1, 0, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[3, 1, 1, 0, 0]~
-[0, -1/3, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[0, 1, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[0, 1, 0, 0, 0]~
-[1/2, 0, 0, 0, 0]~
-[1/2, 0, 0, 0, 0]~
-[1/2, 0, 0, 0, 0]~
-[1/2, 0, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[1/2, 0, 0, 0, 0]~
-[-1/3, -2/3, 1/3, 0, -1/3]~
-[0, 0, 0, 0, 0]~
-[-6, -2, 1, 2, 1]~
-[-5, 0, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[0, 0, 0, 0, 0]~
-[16/9, 0, 0, 0, 0]~
-[-4/3, 0, 0, 0, 0]~
-[4, 4/3, 4/3, 0, 0]~
-[0, 4/3, 0, 0, 0]~
-[2/3, 0, 0, 0, 0]~
-[4/3, 8/3, 4, 16/3, 20/3]~
-[-4/3, 0, 0, 0, 0]~
-[1, 0, 0, 0, 0]~
-[-3, -1, -1, 0, 0]~
-[0, -1, 0, 0, 0]~
-[-1/2, 0, 0, 0, 0]~
-[-1, -2, -3, -4, -5]~
-[4, 4/3, 4/3, 0, 0]~
-[-3, -1, -1, 0, 0]~
-[13, 5, 6, 2, 1]~
-[2, 3, 1, 1, 0]~
-[3/2, 1/2, 1/2, 0, 0]~
-[-58, -42, 23, 27, 17]~
-[0, 4/3, 0, 0, 0]~
-[0, -1, 0, 0, 0]~
-[2, 3, 1, 1, 0]~
-[2, 0, 1, 0, 0]~
-[0, 1/2, 0, 0, 0]~
-[-33, -3, 11, 8, 4]~
-[2/3, 0, 0, 0, 0]~
-[-1/2, 0, 0, 0, 0]~
-[3/2, 1/2, 1/2, 0, 0]~
-[0, 1/2, 0, 0, 0]~
-[1/4, 0, 0, 0, 0]~
-[1/2, 1, 3/2, 2, 5/2]~
-[4/3, 8/3, 4, 16/3, 20/3]~
-[-1, -2, -3, -4, -5]~
-[-58, -42, 23, 27, 17]~
-[-33, -3, 11, 8, 4]~
-[1/2, 1, 3/2, 2, 5/2]~
-[-1071, -384, -251, -155, 20]~
-[1]
-[1, 1/2*x - 1/2]
-[2, Mod(0, 2)]~
-[x^2 + x + 1, [0, 1], -3, 1, [Mat([1, -0.50000000000000000000000000000000000
-000 + 0.86602540378443864676372317075293618347*I]), [1, 0.366025403784438646
-76372317075293618347; 1, -1.3660254037844386467637231707529361835], [1, 0; 1
-, -1], [2, -1; -1, -1], [3, 2; 0, 1], [1, -1; -1, -2], [3, [2, -1; 1, 1]], [
-]], [-0.50000000000000000000000000000000000000 + 0.8660254037844386467637231
-7075293618347*I], [1, x], [1, 0; 0, 1], [1, 0, 0, -1; 0, 1, 1, -1]]
-2
-[0, Mod(0, 2), 1, 0, 0, 0, 0]~
-[0, Mod(1, 2), 1, 0, 1, 0, 0]~
-[]~
-[]~
-388
-
-[2 0]
-
-[0 1]
-
-  *** bnfisprincipal: Warning: precision too low for generators, not given.
-[[]~, [-16275043782306513717209797591668600538906793729160424387141562023303
-069241961, -3992515767463859376807521115314587378342597458337773390379448027
-181914746015, 40263088752008514039400780199135662260965092541683607359784818
-2049497266399, 3875196415920480829978279850511752676499384722019721458357455
-29259111353576, 524613164482816169908873750526849574668376660999341089640759
-880949016596504]~]
-[[[[[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], Vecsmall([1])], [2, [2]], matrix(0,2), [[[2], [-1], [Vecsmall([1])]]], 
-Mat(1)]], [[[[2, 0, 0, 0, 0; 0, 1, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0,
- 0, 0, 0, 1], Vecsmall([1])], [2, [2]], Mat([[2, [0, 0, 1, -1, 0]~, 3, 1, [0
-, -80, 60, -10, -60; 0, 0, -100, 0, -20; 0, 0, 0, -10, -100; 0, 2, -2, 0, 2;
- 1, 0, 0, -10, 0]], 1]), [[[[1], [1], [1], [Vecsmall([])], 1]], [[2], [-1], 
-[Vecsmall([1])]]], Mat(1)]], [], [[[[2, 0, 0, 0, 0; 0, 1, 0, 0, 0; 0, 0, 1, 
-0, 0; 0, 0, 0, 2, 0; 0, 0, 0, 0, 1], Vecsmall([1])], [4, [2, 2]], Mat([[2, [
-0, 0, 1, -1, 0]~, 3, 1, [0, -80, 60, -10, -60; 0, 0, -100, 0, -20; 0, 0, 0, 
--10, -100; 0, 2, -2, 0, 2; 1, 0, 0, -10, 0]], 2]), [[[[1], [1], [1], [Vecsma
-ll([])], 1], [[2], [[1, 0, 0, -1, 0]~], [[1, 0, 0, -1, 0]~], [Vecsmall([])],
- Mat([0, 0, 0, 1, 0])]], [[2], [-1], [Vecsmall([1])]]], [1, 0; 0, 1]], [[[2,
- 0, 1, 0, 0; 0, 2, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], Ve
-csmall([1])], [6, [6]], Mat([[2, [1, 2, 1, 0, 0]~, 1, 2, [0, -80, -20, 0, 0;
- 0, -1, -100, -10, -120; 1, 0, -1, -20, -100; 0, 2, 0, 0, 0; 1, 1, -1, -10, 
-0]], 1]), [[[[3], [[1, 1, 0, 0, 0]~], [[1, 1, 0, 0, 0]~], [Vecsmall([])], 1]
-], [[2], [-1], [Vecsmall([1])]]], Mat([-2, -3])]]]
-[[[[[[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], Vecsmall([1])], [2, [2], [[-1, 0, 0, 0, 0]~]], matrix(0,2), [[[2], [-1
-], [Vecsmall([1])]]], Mat(1)], Mat([1, 1, 1])]], [[[[[2, 0, 0, 0, 0; 0, 1, 0
-, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], Vecsmall([1])], [2, [2
-], [[-1, 0, 0, 0, 0]~]], Mat([[2, [0, 0, 1, -1, 0]~, 3, 1, [0, -80, 60, -10,
- -60; 0, 0, -100, 0, -20; 0, 0, 0, -10, -100; 0, 2, -2, 0, 2; 1, 0, 0, -10, 
-0]], 1]), [[[[1], [1], [1], [Vecsmall([])], 1]], [[2], [-1], [Vecsmall([1])]
-]], Mat(1)], Mat([1, 1, 1])]], [], [[[[[2, 0, 0, 0, 0; 0, 1, 0, 0, 0; 0, 0, 
-1, 0, 0; 0, 0, 0, 2, 0; 0, 0, 0, 0, 1], Vecsmall([1])], [4, [2, 2], [[1, 0, 
-0, -1, 0]~, [-1, 0, 0, 0, 0]~]], Mat([[2, [0, 0, 1, -1, 0]~, 3, 1, [0, -80, 
-60, -10, -60; 0, 0, -100, 0, -20; 0, 0, 0, -10, -100; 0, 2, -2, 0, 2; 1, 0, 
-0, -10, 0]], 2]), [[[[1], [1], [1], [Vecsmall([])], 1], [[2], [[1, 0, 0, -1,
- 0]~], [[1, 0, 0, -1, 0]~], [Vecsmall([])], Mat([0, 0, 0, 1, 0])]], [[2], [-
-1], [Vecsmall([1])]]], [1, 0; 0, 1]], [0, 0, 0; 1, 1, 1]], [[[[2, 0, 1, 0, 0
-; 0, 2, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], Vecsmall([1])
-], [6, [6], [[0, -1, 0, 0, 0]~]], Mat([[2, [1, 2, 1, 0, 0]~, 1, 2, [0, -80, 
--20, 0, 0; 0, -1, -100, -10, -120; 1, 0, -1, -20, -100; 0, 2, 0, 0, 0; 1, 1,
- -1, -10, 0]], 1]), [[[[3], [[0, 1, 0, 0, 0]~], [[0, 1, 0, 0, 0]~], [Vecsmal
-l([])], 1]], [[2], [-1], [Vecsmall([1])]]], Mat([-2, -3])], Mat([-3, -1, -3]
-)]]]
-[[[5, 1, [2, 2; 5, 2; 39821, 1; 161141, 1]]], [[]], [], [[10, 2, [2, 6; 5, 4
-; 39821, 2; 161141, 2]], []]]
-[[[5, -1, [-1, 1; 2, 2; 5, 2; 39821, 1; 161141, 1]]], [[]], [], [[10, -2, [2
-, 6; 5, 4; 39821, 2; 161141, 2]], []]]
-[[[[matrix(0,2), 5, -1, [-1, 1; 2, 2; 5, 2; 39821, 1; 161141, 1]]], [[Mat([5
-0, 1]), 0, 0, 0]], [], [[Mat([50, 2]), 10, -2, [2, 6; 5, 4; 39821, 2; 161141
-, 2]], [Mat([56, 1]), 0, 0, 0]]]]
-  ***   at top-level: nfinit([y^3+2,[1,x]]
-  ***                 ^--------------------
-  *** nfinit: incorrect type in nfbasic_init (t_VEC).
-  ***   at top-level: nfinit([y^3+2,[1,x,x
-  ***                 ^--------------------
-  *** nfinit: incorrect type in nfbasic_init (t_VEC).
-  ***   at top-level: nfinit([y^3+2,[1,y^5
-  ***                 ^--------------------
-  *** nfinit: incorrect type in nfbasic_init (t_VEC).
-2
-[6416795761]
-  ***   at top-level: nfnewprec(x)
-  ***                 ^------------
-  *** nfnewprec: incorrect type in nfnewprec (t_POL).
-  ***   at top-level: nfnewprec(quadgen(5)
-  ***                 ^--------------------
-  *** nfnewprec: incorrect type in nfnewprec (t_QUAD).
-  ***   at top-level: nfnewprec(vector(5))
-  ***                 ^--------------------
-  *** nfnewprec: incorrect type in nfnewprec (t_VEC).
-  ***   at top-level: nfnewprec(vector(6))
-  ***                 ^--------------------
-  *** nfnewprec: incorrect type in nfnewprec (t_VEC).
-  ***   at top-level: nfnewprec(vector(8))
-  ***                 ^--------------------
-  *** nfnewprec: incorrect type in nfnewprec (t_VEC).
-  ***   at top-level: nfnewprec(vector(9))
-  ***                 ^--------------------
-  *** nfnewprec: incorrect type in nfnewprec (t_VEC).
-  ***   at top-level: nfnewprec(vector(16)
-  ***                 ^--------------------
-  *** nfnewprec: incorrect type in nfnewprec (t_VEC).
-Total time spent: 1408
diff --git a/src/test/64/nfields b/src/test/64/nfields
deleted file mode 100644
index 3bba1dd..0000000
--- a/src/test/64/nfields
+++ /dev/null
@@ -1,751 +0,0 @@
-   echo = 1 (on)
-? p2=Pol([1,3021,-786303,-6826636057,-546603588746,3853890514072057]);
-? fa=[11699,6;2392997,2;4987333019653,2];
-? setrand(1);N=10^8;a=matrix(3,5,j,k,vectorv(5,l,random\N));
-? nfpol=x^5-5*x^3+5*x+25;nf=nfinit(nfpol)
-[x^5 - 5*x^3 + 5*x + 25, [1, 2], 595125, 45, [[1, -1.08911514572050482502495
-27946671612684, -2.4285174907194186068992069565359418365, 0.7194669112891317
-8943997506477288225737, -2.5558200350691694950646071159426779972; 1, -0.1383
-8372073406036365047976417441696637 - 0.4918163765776864349975328551474152510
-7*I, 1.9647119211288133163138753392090569931 + 0.809714924188978951282940822
-19556466857*I, -0.072312766896812300380582649294307897074 + 2.19808037538462
-76641195195160383234878*I, -0.98796319352507039803950539735452837193 + 1.570
-1452385894131769052374806001981109*I; 1, 1.682941293594312776162956161507997
-6006 + 2.0500351226010726172974286983598602164*I, -0.75045317576910401286427
-186094108607489 + 1.3101462685358123283560773619310445916*I, -0.787420688747
-75359433940488309213323154 + 2.1336633893126618034168454610457936018*I, 1.26
-58732110596551455718089553258673705 - 2.716479010374315056657802803578983483
-5*I], [1, -1.0891151457205048250249527946671612684, -2.428517490719418606899
-2069565359418365, 0.71946691128913178943997506477288225737, -2.5558200350691
-694950646071159426779972; 1, -0.63020009731174679864801261932183221743, 2.77
-44268453177922675968161614046216617, 2.1257676084878153637389368667440155907
-, 0.58218204506434277886573208324566973897; 1, 0.353432655843626071347053090
-97299828470, 1.1549969969398343650309345170134923246, -2.2703931422814399645
-001021653326313849, -2.5581084321144835749447428779547264828; 1, 3.732976416
-1953853934603848598678578170, 0.55969309276670831549180550098995851667, 1.34
-62427005649082090774405779536603703, -1.450605799314659911085993848253116112
-9; 1, -0.36709382900675984113447253685186261580, -2.060599444304916341220349
-2228721306665, -2.9210840780604153977562503441379268334, 3.98235222143397020
-22296117589048508540], [1, -1, -2, 1, -3; 1, -1, 3, 2, 1; 1, 0, 1, -2, -3; 1
-, 4, 1, 1, -1; 1, 0, -2, -3, 4], [5, 2, 0, -1, -2; 2, -2, -5, -10, 20; 0, -5
-, 10, -10, 5; -1, -10, -10, -17, 1; -2, 20, 5, 1, -8], [345, 0, 200, 110, 17
-7; 0, 345, 95, 1, 145; 0, 0, 5, 4, 3; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], [63, 3,
- 0, -6, -9; 3, 8, -5, -1, 16; 0, -5, 22, -10, 0; -6, -1, -10, -14, -9; -9, 1
-6, 0, -9, -2], [345, [138, 117, 330, 288, -636; -172, -88, 65, 118, -116; 53
-, 1, 138, -173, 65; 1, -172, 54, 191, 106; 0, 118, 173, 225, -34]], [3, 5, 2
-3]], [-2.4285174907194186068992069565359418365, 1.96471192112881331631387533
-92090569931 + 0.80971492418897895128294082219556466857*I, -0.750453175769104
-01286427186094108607489 + 1.3101462685358123283560773619310445916*I], [1, 1/
-15*x^4 - 2/3*x^2 + 1/3*x + 4/3, x, 2/15*x^4 - 1/3*x^2 + 2/3*x - 1/3, -1/15*x
-^4 + 1/3*x^3 + 1/3*x^2 - 4/3*x - 2/3], [1, 0, 3, 1, 10; 0, 0, -2, 1, -5; 0, 
-1, 0, 3, -5; 0, 0, 1, 1, 10; 0, 0, 0, 3, 0], [1, 0, 0, 0, 0, 0, -1, -1, -2, 
-4, 0, -1, 3, -1, 1, 0, -2, -1, -3, -1, 0, 4, 1, -1, -1; 0, 1, 0, 0, 0, 1, 1,
- -1, -1, 1, 0, -1, -2, -1, 1, 0, -1, -1, -1, 3, 0, 1, 1, 3, -3; 0, 0, 1, 0, 
-0, 0, 0, 0, 1, -1, 1, 0, 0, 0, -2, 0, 1, 0, -1, -1, 0, -1, -2, -1, -1; 0, 0,
- 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 2, 1, 0, 1, 0, 0, 0, 0, 2, 0, -1; 0, 0,
- 0, 0, 1, 0, -1, -1, -1, 1, 0, -1, 0, 1, 0, 0, -1, 1, 0, 0, 1, 1, 0, 0, -1]]
-? nfinit(nfpol,2)
-[x^5 - 2*x^4 + 3*x^3 + 8*x^2 + 3*x + 2, [1, 2], 595125, 4, [[1, -1.089115145
-7205048250249527946671612684, -2.4285174907194186068992069565359418365, 0.71
-946691128913178943997506477288225735, -2.55582003506916949506460711594267799
-71; 1, -0.13838372073406036365047976417441696637 + 0.49181637657768643499753
-285514741525107*I, 1.9647119211288133163138753392090569931 - 0.8097149241889
-7895128294082219556466857*I, -0.072312766896812300380582649294307897123 - 2.
-1980803753846276641195195160383234878*I, -0.98796319352507039803950539735452
-837195 - 1.5701452385894131769052374806001981109*I; 1, 1.6829412935943127761
-629561615079976006 + 2.0500351226010726172974286983598602164*I, -0.750453175
-76910401286427186094108607490 + 1.3101462685358123283560773619310445915*I, -
-0.78742068874775359433940488309213323160 + 2.1336633893126618034168454610457
-936016*I, 1.2658732110596551455718089553258673704 - 2.7164790103743150566578
-028035789834836*I], [1, -1.0891151457205048250249527946671612684, -2.4285174
-907194186068992069565359418365, 0.71946691128913178943997506477288225735, -2
-.5558200350691694950646071159426779971; 1, 0.3534326558436260713470530909729
-9828470, 1.1549969969398343650309345170134923246, -2.27039314228143996450010
-21653326313849, -2.5581084321144835749447428779547264828; 1, -0.630200097311
-74679864801261932183221744, 2.7744268453177922675968161614046216617, 2.12576
-76084878153637389368667440155906, 0.58218204506434277886573208324566973893; 
-1, 3.7329764161953853934603848598678578170, 0.559693092766708315491805500989
-95851657, 1.3462427005649082090774405779536603700, -1.4506057993146599110859
-938482531161132; 1, -0.36709382900675984113447253685186261580, -2.0605994443
-049163412203492228721306664, -2.9210840780604153977562503441379268332, 3.982
-3522214339702022296117589048508541], [1, -1, -2, 1, -3; 1, 0, 1, -2, -3; 1, 
--1, 3, 2, 1; 1, 4, 1, 1, -1; 1, 0, -2, -3, 4], [5, 2, 0, -1, -2; 2, -2, -5, 
--10, 20; 0, -5, 10, -10, 5; -1, -10, -10, -17, 1; -2, 20, 5, 1, -8], [345, 0
-, 200, 110, 177; 0, 345, 95, 1, 145; 0, 0, 5, 4, 3; 0, 0, 0, 1, 0; 0, 0, 0, 
-0, 1], [63, 3, 0, -6, -9; 3, 8, -5, -1, 16; 0, -5, 22, -10, 0; -6, -1, -10, 
--14, -9; -9, 16, 0, -9, -2], [345, [138, 117, 330, 288, -636; -172, -88, 65,
- 118, -116; 53, 1, 138, -173, 65; 1, -172, 54, 191, 106; 0, 118, 173, 225, -
-34]], [3, 5, 23]], [-1.0891151457205048250249527946671612684, -0.13838372073
-406036365047976417441696637 + 0.49181637657768643499753285514741525107*I, 1.
-6829412935943127761629561615079976006 + 2.0500351226010726172974286983598602
-164*I], [1, x, -1/2*x^4 + 3/2*x^3 - 5/2*x^2 - 2*x + 1, -1/2*x^4 + x^3 - x^2 
-- 9/2*x - 1, -1/2*x^4 + x^3 - 2*x^2 - 7/2*x - 2], [1, 0, -1, -7, -14; 0, 1, 
-1, -2, -15; 0, 0, 0, 2, 4; 0, 0, 1, 1, -2; 0, 0, -1, -3, -4], [1, 0, 0, 0, 0
-, 0, -1, -1, -2, 4, 0, -1, 3, -1, 1, 0, -2, -1, -3, -1, 0, 4, 1, -1, -1; 0, 
-1, 0, 0, 0, 1, 1, -1, -1, 1, 0, -1, -2, -1, 1, 0, -1, -1, -1, 3, 0, 1, 1, 3,
- -3; 0, 0, 1, 0, 0, 0, 0, 0, 1, -1, 1, 0, 0, 0, -2, 0, 1, 0, -1, -1, 0, -1, 
--2, -1, -1; 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 2, 1, 0, 1, 0, 0, 0, 0
-, 2, 0, -1; 0, 0, 0, 0, 1, 0, -1, -1, -1, 1, 0, -1, 0, 1, 0, 0, -1, 1, 0, 0,
- 1, 1, 0, 0, -1]]
-? nfinit(nfpol,3)[2]
-Mod(-1/2*x^4 + 3/2*x^3 - 5/2*x^2 - 2*x + 1, x^5 - 2*x^4 + 3*x^3 + 8*x^2 + 3*
-x + 2)
-? nf3=nfinit(x^6+108);
-? setrand(1);bnf2=bnfinit(y^3-y-1);nf2=bnf2[7];
-? setrand(1);bnf=bnfinit(x^2-x-57,,[0.2,0.2])
-[Mat(3), Mat([1, 1, 2]), [-2.7124653051843439746808795106061300699 + 3.14159
-26535897932384626433832795028842*I; 2.7124653051843439746808795106061300699]
-, [1.7903417566977293763292119206302198761, 1.289761953065273502503008607239
-5031018 + 3.1415926535897932384626433832795028842*I, 0.E-37, 0.5005798036324
-5587382620331339071677436; -1.7903417566977293763292119206302198761, -1.2897
-619530652735025030086072395031018, 0.E-38, -0.500579803632455873826203313390
-71677436 + 3.1415926535897932384626433832795028842*I], [[3, [-1, 1]~, 1, 1, 
-[0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 57; 1, 2]], [3, [0, 1]~, 1, 1, [-1, 
-57; 1, 0]], [5, [1, 1]~, 1, 1, [-2, 57; 1, -1]]], 0, [x^2 - x - 57, [2, 0], 
-229, 1, [[1, -7.0663729752107779635959310246705326059; 1, 8.0663729752107779
-635959310246705326058], [1, -7.0663729752107779635959310246705326059; 1, 8.0
-663729752107779635959310246705326058], [1, -7; 1, 8], [2, 1; 1, 115], [229, 
-114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]], [229]], [-7.06637297
-52107779635959310246705326059, 8.0663729752107779635959310246705326058], [1,
- x], [1, 0; 0, 1], [1, 0, 0, 57; 0, 1, 1, 1]], [[3, [3], [[3, 2; 0, 1]]], 2.
-7124653051843439746808795106061300699, 1, [2, -1], [x + 7]], [Mat(1), [[0, 0
-]], [[1.7903417566977293763292119206302198761, -1.79034175669772937632921192
-06302198761]]], [0, 0]]
-? dobnf(x^2-x-100000,1)
-[[5], [Mod(379554884019013781006303254896369154068336082609238336*x + 119836
-165644250789990462835950022871665178127611316131167, x^2 - x - 100000)]]
-? \p19
-   realprecision = 19 significant digits
-? setrand(1);sbnf=bnfcompress(bnfinit(x^3-x^2-14*x-1))
-[x^3 - x^2 - 14*x - 1, 3, 10889, [1, x, x^2 - x - 9], [-3.233732695981516673
-, -0.07182350902743636345, 4.305556205008953036], 0, Mat(2), Mat([1, 1, 0, 1
-, 0, 1]), [9, 15, 16, 17, 39, 33, 10], [2, -1], [[0, 1, 0]~, [5, 3, 1]~], [[
-[4, -1, 0]~, [-1, 1, 0]~, [2, 1, 0]~, [3, 1, 0]~, [-10, -5, -1]~, [-1, -1, 0
-]~, [-3, 0, 0]~], 0]]
-? bnfinit(sbnf)
-[Mat(2), Mat([1, 1, 0, 1, 0, 1]), [1.173637103435061715 + 3.1415926535897932
-38*I, -4.562279014988837902 + 3.141592653589793238*I; -2.633543432738976050 
-+ 3.141592653589793238*I, 1.420330600779487358 + 3.141592653589793238*I; 1.4
-59906329303914335, 3.141948414209350544], [1.246346989334819161, 0.540400637
-6129469728 + 3.141592653589793238*I, -0.6926391142471042845 + 3.141592653589
-793238*I, -1.990056445584799714 + 3.141592653589793238*I, -0.830562594660718
-8640, 0.004375616572659815402, 0; 0.6716827432867392936, -0.8333219883742404
-172 + 3.141592653589793238*I, -0.2461086674077943078, 0.5379005671092853267,
- -1.552661549868775854 + 3.141592653589793238*I, -0.8738318043071131265 + 3.
-141592653589793238*I, 0; -1.918029732621558455 + 3.141592653589793238*I, 0.2
-929213507612934444, 0.9387477816548985923, 1.452155878475514387, 2.383224144
-529494718 + 3.141592653589793238*I, 0.8694561877344533111 + 3.14159265358979
-3238*I, 0], [[3, [-1, 1, 0]~, 1, 1, [1, 10, 45; 1, 7, 6; 1, 1, -3]], [5, [-1
-, 1, 0]~, 1, 1, [0, 10, 45; 1, 6, 6; 1, 1, -4]], [5, [2, 1, 0]~, 1, 1, [1, -
-17, 42; -2, 4, -9; 1, -2, -3]], [5, [3, 1, 0]~, 1, 1, [2, 19, 46; 2, 9, 11; 
-1, 2, -2]], [13, [19, 1, 0]~, 1, 1, [-2, -53, 38; -6, -3, -29; 1, -6, -6]], 
-[11, [1, 1, 0]~, 1, 1, [-3, -8, 43; -1, 1, -4; 1, -1, -7]], [3, [10, 1, 1]~,
- 1, 2, [-1, 9, 1; 1, 0, 5; 0, 1, -1]]]~, 0, [x^3 - x^2 - 14*x - 1, [3, 0], 1
-0889, 1, [[1, -3.233732695981516673, 4.690759845041404812; 1, -0.07182350902
-743636345, -8.923017874523549404; 1, 4.305556205008953036, 5.232258029482144
-592], [1, -3.233732695981516673, 4.690759845041404812; 1, -0.071823509027436
-36345, -8.923017874523549404; 1, 4.305556205008953036, 5.232258029482144592]
-, [1, -3, 5; 1, 0, -9; 1, 4, 5], [3, 1, 1; 1, 29, 8; 1, 8, 129], [10889, 569
-8, 8994; 0, 1, 0; 0, 0, 1], [3677, -121, -21; -121, 386, -23; -21, -23, 86],
- [10889, [1899, 46720, 5235; 5191, 7095, 25956; 1, 5191, 1895]], []], [-3.23
-3732695981516673, -0.07182350902743636345, 4.305556205008953036], [1, x, x^2
- - x - 9], [1, 0, 9; 0, 1, 1; 0, 0, 1], [1, 0, 0, 0, 9, 1, 0, 1, 44; 0, 1, 0
-, 1, 1, 5, 0, 5, 1; 0, 0, 1, 0, 1, 0, 1, 0, -4]], [[2, [2], [[3, 2, 0; 0, 1,
- 0; 0, 0, 1]]], 10.34800724602767998, 1, [2, -1], [x, x^2 + 2*x - 4]], [Mat(
-1), [[0, 0, 0]], [[1.246346989334819161, 0.6716827432867392936, -1.918029732
-621558455 + 3.141592653589793238*I]]], [[[4, -1, 0]~, [-1, 1, 0]~, [2, 1, 0]
-~, [3, 1, 0]~, [-10, -5, -1]~, [-1, -1, 0]~, [-3, 0, 0]~], 0]]
-? \p38
-   realprecision = 38 significant digits
-? bnr=bnrinit(bnf,[[5,3;0,1],[1,0]],1);bnr.cyc
-[12]
-? bnr2=bnrinit(bnf,[[25,13;0,1],[1,1]],1);bnr2.bid
-[[[25, 13; 0, 1], [1, 1]], [80, [20, 2, 2], [2, [-24, 0]~, [2, 2]~]], Mat([[
-5, [-2, 1]~, 1, 1, [1, 57; 1, 2]], 2]), [[[[4], [2], [2], [Vecsmall([0, 0])]
-, 1], [[5], [6], [6], [Vecsmall([0, 0])], Mat([1/5, -13/5])]], [[2, 2], [-24
-, [2, 2]~], [Vecsmall([0, 1]), Vecsmall([1, 1])]]], [1, -12, 0, 0; 0, 0, 1, 
-0; 0, 0, 0, 1]]
-? rnfinit(nf2,x^5-x-2)
-[x^5 - x - 2, [[83718587879473471, -18162091535584830*x^14 + 659399873895590
-0*x^13 + 89125883511340690*x^12 - 123429972713895380*x^11 - 8618468612826159
-0*x^10 + 508290939376248430*x^9 - 88425050961683595*x^8 - 806556841120532680
-*x^7 - 2575481228604156570*x^6 + 2756771576006241774*x^5 - 28977279276236285
-95*x^4 + 4379071886234238350*x^3 - 4957913590225421420*x^2 - 981408476020699
-484*x + 24006278056864075, 39516536165538345*x^14 - 6500512476832995*x^13 - 
-196215472046117185*x^12 + 229902227480108910*x^11 + 237380704030959181*x^10 
-- 1064931988160773805*x^9 - 20657086671714300*x^8 + 1772885205999206010*x^7 
-+ 5952033217241102348*x^6 - 4838840187320655696*x^5 + 5180390720553188700*x^
-4 - 8374015687535120430*x^3 + 8907744727915040221*x^2 + 4155976664123434381*
-x + 318920215718580450], 1/83718587879473471], [[49744, 0, 0; 0, 49744, 0; 0
-, 0, 49744], 3109], 1, [], [], [[1, x, x^2, x^3, x^4], [1, 1, 1, 1, 1]], [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], []
-, [y^3 - y - 1, [1, 1], -23, 1, [[1, 0.7548776662466927600495088963585286919
-0, 1.3247179572447460259609088544780973407; 1, -0.87743883312334638002475444
-817926434595 - 0.74486176661974423659317042860439236724*I, -0.66235897862237
-301298045442723904867037 + 0.56227951206230124389918214490937306150*I], [1, 
-0.75487766624669276004950889635852869190, 1.32471795724474602596090885447809
-73407; 1, -1.6223005997430906166179248767836567132, -0.100079466560071769081
-27228232967560887; 1, -0.13257706650360214343158401957487197871, -1.22463849
-06846742568796365721484217319], [1, 1, 1; 1, -2, 0; 1, 0, -1], [3, -1, 0; -1
-, 1, 3; 0, 3, 2], [23, 16, 13; 0, 1, 0; 0, 0, 1], [7, -2, 3; -2, -6, 9; 3, 9
-, -2], [23, [10, 1, 8; 7, 3, 1; 1, 7, 10]], [23]], [1.3247179572447460259609
-088544780973407, -0.66235897862237301298045442723904867037 + 0.5622795120623
-0124389918214490937306150*I], [1, y^2 - 1, y], [1, 0, 1; 0, 0, 1; 0, 1, 0], 
-[1, 0, 0, 0, 0, 1, 0, 1, 1; 0, 1, 0, 1, -1, 0, 0, 0, 1; 0, 0, 1, 0, 1, 0, 1,
- 0, 0]], [x^15 - 5*x^13 + 5*x^12 + 7*x^11 - 26*x^10 - 5*x^9 + 45*x^8 + 158*x
-^7 - 98*x^6 + 110*x^5 - 190*x^4 + 189*x^3 + 144*x^2 + 25*x + 1, 395165361655
-38345/83718587879473471*x^14 - 6500512476832995/83718587879473471*x^13 - 196
-215472046117185/83718587879473471*x^12 + 229902227480108910/8371858787947347
-1*x^11 + 237380704030959181/83718587879473471*x^10 - 1064931988160773805/837
-18587879473471*x^9 - 20657086671714300/83718587879473471*x^8 + 1772885205999
-206010/83718587879473471*x^7 + 5952033217241102348/83718587879473471*x^6 - 4
-838840187320655696/83718587879473471*x^5 + 5180390720553188700/8371858787947
-3471*x^4 - 8374015687535120430/83718587879473471*x^3 + 8907744727915040221/8
-3718587879473471*x^2 + 4155976664123434381/83718587879473471*x + 31892021571
-8580450/83718587879473471, -1, y^3 - y - 1, x^5 - x - 2], [0, 0]]
-? bnfcertify(bnf)
-1
-? dobnf(x^4+24*x^2+585*x+1791,,[0.1,0.1])
-[[4], [Mod(1/343*x^3 - 46/1029*x^2 - 122/343*x - 174/343, x^4 + 24*x^2 + 585
-*x + 1791)]]
-? bnrconductor(bnf,[[25,13;0,1],[1,1]])
-[[5, 3; 0, 1], [1, 0]]
-? bnrconductorofchar(bnr,[2])
-[[5, 3; 0, 1], [0, 0]]
-? bnfisprincipal(bnf,[5,1;0,1],0)
-[1]~
-? bnfisprincipal(bnf,[5,1;0,1])
-[[1]~, [-2, -1/3]~]
-? bnfisunit(bnf,Mod(3405*x-27466,x^2-x-57))
-[-4, Mod(1, 2)]~
-? bnfnarrow(bnf)
-[3, [3], [[3, 2; 0, 1]]]
-? bnfsignunit(bnf)
-
-[-1]
-
-[ 1]
-
-? bnrclassno(bnf,[[5,3;0,1],[1,0]])
-12
-? lu=ideallist(bnf,55,3);
-? bnrclassnolist(bnf,lu)
-[[3], [], [3, 3], [3], [6, 6], [], [], [], [3, 3, 3], [], [3, 3], [3, 3], []
-, [], [12, 6, 6, 12], [3], [3, 3], [], [9, 9], [6, 6], [], [], [], [], [6, 1
-2, 6], [], [3, 3, 3, 3], [], [], [], [], [], [3, 6, 6, 3], [], [], [9, 3, 9]
-, [6, 6], [], [], [], [], [], [3, 3], [3, 3], [12, 12, 6, 6, 12, 12], [], []
-, [6, 6], [9], [], [3, 3, 3, 3], [], [3, 3], [], [6, 12, 12, 6]]
-? bnrdisc(bnr,Mat(6))
-[12, 12, 18026977100265125]
-? bnrdisc(bnr)
-[24, 12, 40621487921685401825918161408203125]
-? bnrdisc(bnr2,,,2)
-0
-? bnrdisc(bnr,Mat(6),,1)
-[6, 2, [125, 13; 0, 1]]
-? bnrdisc(bnr,,,1)
-[12, 1, [1953125, 1160888; 0, 1]]
-? bnrdisc(bnr2,,,3)
-0
-? bnrdisclist(bnf,lu)
-[[[6, 6, Mat([229, 3])]], [], [[], []], [[]], [[12, 12, [5, 3; 229, 6]], [12
-, 12, [5, 3; 229, 6]]], [], [], [], [[], [], []], [], [[], []], [[], []], []
-, [], [[24, 24, [3, 6; 5, 9; 229, 12]], [], [], [24, 24, [3, 6; 5, 9; 229, 1
-2]]], [[]], [[], []], [], [[18, 18, [19, 6; 229, 9]], [18, 18, [19, 6; 229, 
-9]]], [[], []], [], [], [], [], [[], [24, 24, [5, 12; 229, 12]], []], [], [[
-], [], [], []], [], [], [], [], [], [[], [12, 12, [3, 3; 11, 3; 229, 6]], [1
-2, 12, [3, 3; 11, 3; 229, 6]], []], [], [], [[18, 18, [2, 12; 3, 12; 229, 9]
-], [], [18, 18, [2, 12; 3, 12; 229, 9]]], [[12, 12, [37, 3; 229, 6]], [12, 1
-2, [37, 3; 229, 6]]], [], [], [], [], [], [[], []], [[], []], [[], [], [], [
-], [], []], [], [], [[12, 12, [2, 12; 3, 3; 229, 6]], [12, 12, [2, 12; 3, 3;
- 229, 6]]], [[18, 18, [7, 12; 229, 9]]], [], [[], [], [], []], [], [[], []],
- [], [[], [24, 24, [5, 9; 11, 6; 229, 12]], [24, 24, [5, 9; 11, 6; 229, 12]]
-, []]]
-? bnrdisclist(bnf,20)
-[[[[matrix(0,2), [[6, 6, Mat([229, 3])], [0, 0, 0], [0, 0, 0], [0, 0, 0]]]],
- [], [[Mat([12, 1]), [[0, 0, 0], [0, 0, 0], [0, 0, 0], [12, 0, [3, 3; 229, 6
-]]]], [Mat([13, 1]), [[0, 0, 0], [12, 6, [-1, 1; 3, 3; 229, 6]], [0, 0, 0], 
-[0, 0, 0]]]], [[Mat([10, 1]), [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]]]
-, [[Mat([20, 1]), [[12, 12, [5, 3; 229, 6]], [0, 0, 0], [0, 0, 0], [24, 0, [
-5, 9; 229, 12]]]], [Mat([21, 1]), [[12, 12, [5, 3; 229, 6]], [24, 12, [5, 9;
- 229, 12]], [0, 0, 0], [0, 0, 0]]]], [], [], [], [[Mat([12, 2]), [[0, 0, 0],
- [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [[12, 1; 13, 1], [[0, 0, 0], [0, 0, 0], 
-[12, 6, [-1, 1; 3, 6; 229, 6]], [24, 0, [3, 12; 229, 12]]]], [Mat([13, 2]), 
-[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]]], [], [[Mat([44, 1]), [[0, 0, 
-0], [12, 6, [-1, 1; 11, 3; 229, 6]], [0, 0, 0], [0, 0, 0]]], [Mat([45, 1]), 
-[[0, 0, 0], [0, 0, 0], [0, 0, 0], [12, 0, [11, 3; 229, 6]]]]], [[[10, 1; 12,
- 1], [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [[10, 1; 13, 1], [[0, 0,
- 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]]], [], [], [[[12, 1; 20, 1], [[24, 24,
- [3, 6; 5, 9; 229, 12]], [0, 0, 0], [0, 0, 0], [48, 0, [3, 12; 5, 18; 229, 2
-4]]]], [[13, 1; 20, 1], [[0, 0, 0], [24, 12, [3, 6; 5, 6; 229, 12]], [24, 12
-, [3, 6; 5, 9; 229, 12]], [48, 0, [3, 12; 5, 18; 229, 24]]]], [[12, 1; 21, 1
-], [[0, 0, 0], [0, 0, 0], [24, 12, [3, 6; 5, 9; 229, 12]], [48, 0, [3, 12; 5
-, 18; 229, 24]]]], [[13, 1; 21, 1], [[24, 24, [3, 6; 5, 9; 229, 12]], [48, 2
-4, [3, 12; 5, 18; 229, 24]], [0, 0, 0], [0, 0, 0]]]], [[Mat([10, 2]), [[0, 0
-, 0], [12, 6, [-1, 1; 2, 12; 229, 6]], [12, 6, [-1, 1; 2, 12; 229, 6]], [24,
- 0, [2, 36; 229, 12]]]]], [[Mat([68, 1]), [[0, 0, 0], [0, 0, 0], [12, 6, [-1
-, 1; 17, 3; 229, 6]], [0, 0, 0]]], [Mat([69, 1]), [[0, 0, 0], [0, 0, 0], [12
-, 6, [-1, 1; 17, 3; 229, 6]], [0, 0, 0]]]], [], [[Mat([76, 1]), [[18, 18, [1
-9, 6; 229, 9]], [0, 0, 0], [0, 0, 0], [36, 0, [19, 15; 229, 18]]]], [Mat([77
-, 1]), [[18, 18, [19, 6; 229, 9]], [36, 18, [-1, 1; 19, 15; 229, 18]], [0, 0
-, 0], [0, 0, 0]]]], [[[10, 1; 20, 1], [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 
-0, 0]]], [[10, 1; 21, 1], [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]]]]]
-? bnrisprincipal(bnr,idealprimedec(bnf,7)[1])
-[[9]~, [32879/6561, 13958/19683]~]
-? dirzetak(nfinit(x^3-10*x+8),30)
-[1, 2, 0, 3, 1, 0, 0, 4, 0, 2, 1, 0, 0, 0, 0, 5, 1, 0, 0, 3, 0, 2, 0, 0, 2, 
-0, 1, 0, 1, 0]
-? factornf(x^3+x^2-2*x-1,t^3+t^2-2*t-1)
-
-[         x + Mod(-t, t^3 + t^2 - 2*t - 1) 1]
-
-[   x + Mod(-t^2 + 2, t^3 + t^2 - 2*t - 1) 1]
-
-[x + Mod(t^2 + t - 1, t^3 + t^2 - 2*t - 1) 1]
-
-? vp=idealprimedec(nf,3)[1]
-[3, [1, 0, 1, 0, 0]~, 1, 1, [1, 4, -1, 6, -4; -1, 2, 4, 3, -5; -1, -1, 1, 0,
- 4; -1, -1, -2, 0, -2; 0, 3, 0, 0, 0]]
-? idx=idealhnf(nf,vp)
-
-[3 2 1 0 1]
-
-[0 1 0 0 0]
-
-[0 0 1 0 0]
-
-[0 0 0 1 0]
-
-[0 0 0 0 1]
-
-? idy=idealred(nf,idx,[1,5,6])
-
-[5 0 0 0 2]
-
-[0 5 0 0 2]
-
-[0 0 5 0 1]
-
-[0 0 0 5 2]
-
-[0 0 0 0 1]
-
-? idx2=idealmul(nf,idx,idx)
-
-[9 5 7 0 4]
-
-[0 1 0 0 0]
-
-[0 0 1 0 0]
-
-[0 0 0 1 0]
-
-[0 0 0 0 1]
-
-? idt=idealmul(nf,idx,idx,1)
-
-[2 0 0 0 0]
-
-[0 2 0 0 0]
-
-[0 0 2 0 0]
-
-[0 0 0 2 1]
-
-[0 0 0 0 1]
-
-? idz=idealintersect(nf,idx,idy)
-
-[15 10 5 0 12]
-
-[ 0  5 0 0  2]
-
-[ 0  0 5 0  1]
-
-[ 0  0 0 5  2]
-
-[ 0  0 0 0  1]
-
-? aid=[idx,idy,idz,1,idx];
-? idealadd(nf,idx,idy)
-
-[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]
-
-? idealaddtoone(nf,idx,idy)
-[[0, -1, -3, -1, 2]~, [1, 1, 3, 1, -2]~]
-? idealaddtoone(nf,[idy,idx])
-[[-5, 0, 0, 0, 0]~, [6, 0, 0, 0, 0]~]
-? idealappr(nf,idy)
-[-1, 4, 2, -1, -3]~
-? idealappr(nf,idealfactor(nf,idy),1)
-[-1, 4, 2, -1, -3]~
-? idealcoprime(nf,idx,idx)
-[-1/3, 1/3, 1/3, 1/3, 0]~
-? idealdiv(nf,idy,idt)
-
-[5   0 5/2   0   1]
-
-[0 5/2   0   0   1]
-
-[0   0 5/2   0 1/2]
-
-[0   0   0 5/2   1]
-
-[0   0   0   0 1/2]
-
-? idealdiv(nf,idx2,idx,1)
-
-[3 2 1 0 1]
-
-[0 1 0 0 0]
-
-[0 0 1 0 0]
-
-[0 0 0 1 0]
-
-[0 0 0 0 1]
-
-? idealfactor(nf,idz)
-
-[[3, [1, 0, 1, 0, 0]~, 1, 1, [1, 4, -1, 6, -4; -1, 2, 4, 3, -5; -1, -1, 1, 0
-, 4; -1, -1, -2, 0, -2; 0, 3, 0, 0, 0]] 1]
-
-[[5, [-1, 0, 0, 0, 2]~, 4, 1, [2, -3, 0, -12, 6; 2, 2, -5, -2, 6; 1, 1, 0, -
-1, -7; 2, 2, 5, 3, 1; 1, -4, 0, -1, 3]] 3]
-
-[[5, [2, 0, 0, 0, -2]~, 1, 1, [2, 1, 10, -4, 2; 0, 0, -5, 0, 0; 3, -1, 0, -1
-, -7; 0, 0, 5, 5, 5; 1, -2, 0, 3, 1]] 1]
-
-? idealhnf(nf,vp[2],3)
-
-[3 2 1 0 1]
-
-[0 1 0 0 0]
-
-[0 0 1 0 0]
-
-[0 0 0 1 0]
-
-[0 0 0 0 1]
-
-? ideallist(bnf,20)
-[[[1, 0; 0, 1]], [], [[3, 2; 0, 1], [3, 0; 0, 1]], [[2, 0; 0, 2]], [[5, 3; 0
-, 1], [5, 1; 0, 1]], [], [], [], [[9, 5; 0, 1], [3, 0; 0, 3], [9, 3; 0, 1]],
- [], [[11, 9; 0, 1], [11, 1; 0, 1]], [[6, 4; 0, 2], [6, 0; 0, 2]], [], [], [
-[15, 8; 0, 1], [15, 3; 0, 1], [15, 11; 0, 1], [15, 6; 0, 1]], [[4, 0; 0, 4]]
-, [[17, 14; 0, 1], [17, 2; 0, 1]], [], [[19, 18; 0, 1], [19, 0; 0, 1]], [[10
-, 6; 0, 2], [10, 2; 0, 2]]]
-? bid=idealstar(nf2,54)
-[[[54, 0, 0; 0, 54, 0; 0, 0, 54], [0]], [132678, [1638, 9, 9]], [[2, [2, 0, 
-0]~, 1, 3, 1], 1; [3, [3, 0, 0]~, 1, 3, 1], 3], [[[[7], [[2, 1, 1]~], [[-26,
- -27, -27]~], [Vecsmall([])], 1]], [[[26], [[4, 2, 1]~], [[-23, 2, -26]~], [
-Vecsmall([])], 1], [[3, 3, 3], [4, [1, 3, 0]~, [1, 0, 3]~], [-77, [1, -24, 0
-]~, [1, 0, -24]~], [Vecsmall([]), Vecsmall([]), Vecsmall([])], [1/3, 0, 0; 0
-, 1/3, 0; 0, 0, 1/3]], [[3, 3, 3], [10, [1, 9, 0]~, [1, 0, 9]~], [-233, [1, 
--18, 0]~, [1, 0, -18]~], [Vecsmall([]), Vecsmall([]), Vecsmall([])], [1/9, 0
-, 0; 0, 1/9, 0; 0, 0, 1/9]]], [[], [], []]], [468, -77, 0, 728, -1456, 0, 54
-6, -1092; 0, 0, 1, 0, -1, -6, 0, -3; 0, 1, 0, -1, 1, 0, -3, 3]]
-? ideallog(nf2,y,bid)
-[284, 1, 1]~
-? idealmin(nf,idx,[1,2,3])
-[1, 0, 1, 0, 0]~
-? idealnorm(nf,idt)
-16
-? idp=idealpow(nf,idx,7)
-
-[2187 1436 1807 630 1822]
-
-[   0    1    0   0    0]
-
-[   0    0    1   0    0]
-
-[   0    0    0   1    0]
-
-[   0    0    0   0    1]
-
-? idealpow(nf,idx,7,1)
-
-[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]
-
-? idealprimedec(nf,2)
-[[2, [3, 0, 1, 0, 0]~, 1, 1, [0, 2, 0, -4, -2; 0, 0, 0, 2, 0; 0, 0, -2, -2, 
--2; 1, 0, 3, 0, -1; 1, 0, 1, 0, -1]], [2, [12, -4, -2, 11, 3]~, 1, 4, [1, -1
-, 3, -1, 1; 0, 0, -2, -1, 1; 1, 0, 1, 0, -2; 0, 0, 1, 2, 2; 0, -1, 0, 1, 1]]
-]
-? idealprimedec(nf,3)
-[[3, [1, 0, 1, 0, 0]~, 1, 1, [1, 4, -1, 6, -4; -1, 2, 4, 3, -5; -1, -1, 1, 0
-, 4; -1, -1, -2, 0, -2; 0, 3, 0, 0, 0]], [3, [1, 1, 1, 0, 0]~, 2, 2, [0, -6,
- 3, -9, 9; 2, -1, -7, -5, 7; 2, 1, 0, 1, -7; 1, 2, 3, 2, 4; 0, -5, -1, 0, 2]
-]]
-? idealprimedec(nf,11)
-[[11, [11, 0, 0, 0, 0]~, 1, 5, 1]]
-? idealtwoelt(nf,idy)
-[5, [2, 2, 1, 2, 1]~]
-? idealtwoelt(nf,idy,10)
-[-1, 4, 2, 4, 2]~
-? idealstar(nf2,54)
-[[[54, 0, 0; 0, 54, 0; 0, 0, 54], [0]], [132678, [1638, 9, 9]], [[2, [2, 0, 
-0]~, 1, 3, 1], 1; [3, [3, 0, 0]~, 1, 3, 1], 3], [[[[7], [[0, 0, 1]~], [[-26,
- 0, -27]~], [Vecsmall([])], 1]], [[[26], [[0, 0, 2]~], [[-27, 0, 2]~], [Vecs
-mall([])], 1], [[3, 3, 3], [4, [1, 3, 0]~, [1, 0, 3]~], [-77, [1, -24, 0]~, 
-[1, 0, -24]~], [Vecsmall([]), Vecsmall([]), Vecsmall([])], [1/3, 0, 0; 0, 1/
-3, 0; 0, 0, 1/3]], [[3, 3, 3], [10, [1, 9, 0]~, [1, 0, 9]~], [-233, [1, -18,
- 0]~, [1, 0, -18]~], [Vecsmall([]), Vecsmall([]), Vecsmall([])], [1/9, 0, 0;
- 0, 1/9, 0; 0, 0, 1/9]]], [[], [], []]], [468, 469, 0, 0, -182, 0, 0, -546; 
-0, 0, 1, 0, -7, -6, 0, -3; 0, 0, 0, 1, -3, 0, -6, 0]]
-? idealval(nf,idp,vp)
-7
-? ba=nfalgtobasis(nf,x^3+5)
-[6, 1, 3, 1, 3]~
-? bb=nfalgtobasis(nf,x^3+x)
-[1, 1, 4, 1, 3]~
-? bc=matalgtobasis(nf,[x^2+x;x^2+1])
-
-[[3, -2, 1, 1, 0]~]
-
-[[4, -2, 0, 1, 0]~]
-
-? matbasistoalg(nf,bc)
-
-[Mod(x^2 + x, x^5 - 5*x^3 + 5*x + 25)]
-
-[Mod(x^2 + 1, x^5 - 5*x^3 + 5*x + 25)]
-
-? nfbasis(x^3+4*x+5)
-[1, x, 1/7*x^2 - 1/7*x - 2/7]
-? nfbasis(x^3+4*x+5,2)
-[1, x, 1/7*x^2 - 1/7*x - 2/7]
-? nfbasis(x^3+4*x+12,1)
-[1, x, 1/2*x^2]
-? nfbasistoalg(nf,ba)
-Mod(x^3 + 5, x^5 - 5*x^3 + 5*x + 25)
-? nfbasis(p2,0,fa)
-[1, x, x^2, 1/11699*x^3 + 1847/11699*x^2 - 132/11699*x - 2641/11699, 1/13962
-3738889203638909659*x^4 - 1552451622081122020/139623738889203638909659*x^3 +
- 418509858130821123141/139623738889203638909659*x^2 - 6810913798507599407313
-4/139623738889203638909659*x - 13185339461968406/58346808996920447]
-? nfdisc(x^3+4*x+12)
--1036
-? nfdisc(x^3+4*x+12,1)
--1036
-? nfdisc(p2,0,fa)
-136866601
-? nfeltdiv(nf,ba,bb)
-[584/373, 66/373, -32/373, -105/373, 120/373]~
-? nfeltdiveuc(nf,ba,bb)
-[2, 0, 0, 0, 0]~
-? nfeltdivrem(nf,ba,bb)
-[[2, 0, 0, 0, 0]~, [4, -1, -5, -1, -3]~]
-? nfeltmod(nf,ba,bb)
-[4, -1, -5, -1, -3]~
-? nfeltmul(nf,ba,bb)
-[50, -15, -35, 60, 15]~
-? nfeltpow(nf,bb,5)
-[-291920, 136855, 230560, -178520, 74190]~
-? nfeltreduce(nf,ba,idx)
-[1, 0, 0, 0, 0]~
-? nfeltval(nf,ba,vp)
-0
-? nffactor(nf2,x^3+x)
-
-[      x 1]
-
-[x^2 + 1 1]
-
-? aut=nfgaloisconj(nf3)
-[-x, x, -1/12*x^4 - 1/2*x, -1/12*x^4 + 1/2*x, 1/12*x^4 - 1/2*x, 1/12*x^4 + 1
-/2*x]~
-? nfgaloisapply(nf3,aut[5],Mod(x^5,x^6+108))
-Mod(-1/2*x^5 + 9*x^2, x^6 + 108)
-? nfhilbert(nf,3,5)
--1
-? nfhilbert(nf,3,5,vp)
--1
-? nfhnf(nf,[a,aid])
-[[1, 1, 4; 0, 1, 0; 0, 0, 1], [[15, 2, 10, 12, 4; 0, 1, 0, 0, 0; 0, 0, 1, 0,
- 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], 1, 1]]
-? da=nfdetint(nf,[a,aid])
-
-[15 10 5 0 12]
-
-[ 0  5 0 0  2]
-
-[ 0  0 5 0  1]
-
-[ 0  0 0 5  2]
-
-[ 0  0 0 0  1]
-
-? nfhnfmod(nf,[a,aid],da)
-[[1, 1, 4; 0, 1, 0; 0, 0, 1], [[15, 2, 10, 12, 4; 0, 1, 0, 0, 0; 0, 0, 1, 0,
- 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], 1, 1]]
-? nfisideal(bnf[7],[5,1;0,1])
-1
-? nfisincl(x^2+1,x^4+1)
-[-x^2, x^2]
-? nfisincl(x^2+1,nfinit(x^4+1))
-[-x^2, x^2]
-? nfisisom(x^3+x^2-2*x-1,x^3+x^2-2*x-1)
-[x, -x^2 - x + 1, x^2 - 2]
-? nfisisom(x^3-2,nfinit(x^3-6*x^2-6*x-30))
-[-1/25*x^2 + 13/25*x - 2/5]
-? nfroots(nf2,x+2)
-[Mod(-2, y^3 - y - 1)]
-? nfrootsof1(nf)
-[2, -1]
-? nfsnf(nf,[a[,1..3],[1,1,1],[idealinv(nf,idx),idealinv(nf,idy),1]])
-[[15706993357777254170417850, 1636878763571210697462070, 1307908830618593502
-9427775, 1815705333955314515809980, 7581330311082212790621785; 0, 5, 0, 0, 0
-; 0, 0, 5, 0, 0; 0, 0, 0, 5, 0; 0, 0, 0, 0, 5], [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], [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]]
-? nfsubfields(nf)
-[[x, 0], [x^5 - 5*x^3 + 5*x + 25, x]]
-? polcompositum(x^4-4*x+2,x^3-x-1)
-[x^12 - 4*x^10 + 8*x^9 + 12*x^8 + 12*x^7 + 138*x^6 + 132*x^5 - 43*x^4 + 58*x
-^2 - 128*x - 5]
-? polcompositum(x^4-4*x+2,x^3-x-1,1)
-[[x^12 - 4*x^10 + 8*x^9 + 12*x^8 + 12*x^7 + 138*x^6 + 132*x^5 - 43*x^4 + 58*
-x^2 - 128*x - 5, Mod(-279140305176/29063006931199*x^11 + 129916611552/290630
-06931199*x^10 + 1272919322296/29063006931199*x^9 - 2813750209005/29063006931
-199*x^8 - 2859411937992/29063006931199*x^7 - 414533880536/29063006931199*x^6
- - 35713977492936/29063006931199*x^5 - 17432607267590/29063006931199*x^4 + 4
-9785595543672/29063006931199*x^3 + 9423768373204/29063006931199*x^2 - 427797
-76146743/29063006931199*x + 37962587857138/29063006931199, x^12 - 4*x^10 + 8
-*x^9 + 12*x^8 + 12*x^7 + 138*x^6 + 132*x^5 - 43*x^4 + 58*x^2 - 128*x - 5), M
-od(-279140305176/29063006931199*x^11 + 129916611552/29063006931199*x^10 + 12
-72919322296/29063006931199*x^9 - 2813750209005/29063006931199*x^8 - 28594119
-37992/29063006931199*x^7 - 414533880536/29063006931199*x^6 - 35713977492936/
-29063006931199*x^5 - 17432607267590/29063006931199*x^4 + 49785595543672/2906
-3006931199*x^3 + 9423768373204/29063006931199*x^2 - 13716769215544/290630069
-31199*x + 37962587857138/29063006931199, x^12 - 4*x^10 + 8*x^9 + 12*x^8 + 12
-*x^7 + 138*x^6 + 132*x^5 - 43*x^4 + 58*x^2 - 128*x - 5), -1]]
-? polgalois(x^6-3*x^2-1)
-[12, 1, 1, "A_4(6) = [2^2]3"]
-? polred(x^5-2*x^4-4*x^3-96*x^2-352*x-568)
-[x - 1, x^5 - x^4 + 2*x^3 - 4*x^2 + x - 1]
-? polred(x^4-28*x^3-458*x^2+9156*x-25321,3)
-
-[                                                1           x - 1]
-
-[                   1/115*x^2 - 14/115*x - 212/115   x^2 - 2*x - 9]
-
-[                  -1/115*x^2 + 14/115*x + 442/115   x^2 - 2*x - 9]
-
-[                   1/115*x^2 - 14/115*x - 327/115        x^2 - 10]
-
-[1/4485*x^3 - 7/1495*x^2 - 1034/4485*x + 7924/4485 x^4 - 8*x^2 + 6]
-
-? polred(x^4+576,1)
-[x - 1, x^2 - 3*x + 3, x^2 - 2*x + 2, x^2 - x + 1, x^2 + 1, x^4 - x^2 + 1]
-? polred(x^4+576,3)
-
-[                           1         x - 1]
-
-[    -1/192*x^3 - 1/8*x + 3/2 x^2 - 3*x + 3]
-
-[                1/24*x^2 + 1 x^2 - 2*x + 2]
-
-[               -1/24*x^2 + 1 x^2 - 2*x + 2]
-
-[    -1/192*x^3 - 1/8*x + 1/2   x^2 - x + 1]
-
-[     1/192*x^3 + 1/8*x + 1/2   x^2 - x + 1]
-
-[                    1/24*x^2       x^2 + 1]
-
-[1/192*x^3 + 1/48*x^2 - 1/8*x x^4 - x^2 + 1]
-
-? polred(p2,0,fa)
-[x - 1, x^5 - 80*x^3 - 223*x^2 + 800*x + 2671]
-? polred(p2,1,fa)
-[x - 1, x^5 - 80*x^3 - 223*x^2 + 800*x + 2671]
-? polredabs(x^5-2*x^4-4*x^3-96*x^2-352*x-568)
-x^5 - x^4 + 2*x^3 - 4*x^2 + x - 1
-? polredabs(x^5-2*x^4-4*x^3-96*x^2-352*x-568,1)
-[x^5 - x^4 + 2*x^3 - 4*x^2 + x - 1, Mod(2*x^4 - x^3 + 3*x^2 - 3*x - 1, x^5 -
- x^4 + 2*x^3 - 4*x^2 + x - 1)]
-? polredord(x^3-12*x+45*x-1)
-[x - 1, x^3 + 33*x - 1]
-? polsubcyclo(31,5)
-x^5 + x^4 - 12*x^3 - 21*x^2 + x + 5
-? setrand(1);poltschirnhaus(x^5-x-1)
-x^5 + 10*x^4 + 32*x^3 - 100*x^2 - 879*x - 1457
-? p=x^5-5*x+y;aa=rnfpseudobasis(nf2,p)
-[[1, 0, 0, -2, [3, 1, 0]~; 0, 1, 0, 2, [0, -1, 0]~; 0, 0, 1, 1, [-5, -2, 0]~
-; 0, 0, 0, 1, -2; 0, 0, 0, 0, 1], [1, 1, 1, [1, 0, 2/5; 0, 1, 3/5; 0, 0, 1/5
-], [1, 0, 22/25; 0, 1, 8/25; 0, 0, 1/25]], [416134375, 202396875, 60056800; 
-0, 3125, 2700; 0, 0, 25], [-1275, 5, 5]~]
-? rnfbasis(bnf2,aa)
-
-[1 0 0  [-26/25, 11/25, -8/25]~         [0, 4, -7]~]
-
-[0 1 0   [53/25, -8/25, -1/25]~ [6/5, -41/5, 53/5]~]
-
-[0 0 1 [-14/25, -21/25, 13/25]~  [-16/5, 1/5, 7/5]~]
-
-[0 0 0     [7/25, -2/25, 6/25]~  [2/5, -2/5, 11/5]~]
-
-[0 0 0     [9/25, 1/25, -3/25]~   [2/5, -7/5, 6/5]~]
-
-? rnfdisc(nf2,p)
-[[416134375, 202396875, 60056800; 0, 3125, 2700; 0, 0, 25], [-1275, 5, 5]~]
-? rnfequation(nf2,p)
-x^15 - 15*x^11 + 75*x^7 - x^5 - 125*x^3 + 5*x + 1
-? rnfequation(nf2,p,1)
-[x^15 - 15*x^11 + 75*x^7 - x^5 - 125*x^3 + 5*x + 1, Mod(-x^5 + 5*x, x^15 - 1
-5*x^11 + 75*x^7 - x^5 - 125*x^3 + 5*x + 1), 0]
-? rnfhnfbasis(bnf2,aa)
-
-[1 0 0 [-6/5, -4/5, 2/5]~   [3/25, -8/25, 24/25]~]
-
-[0 1 0  [6/5, 4/5, -2/5]~   [-9/25, -1/25, 3/25]~]
-
-[0 0 1  [3/5, 2/5, -1/5]~ [-8/25, 13/25, -39/25]~]
-
-[0 0 0  [3/5, 2/5, -1/5]~   [4/25, 6/25, -18/25]~]
-
-[0 0 0                  0   [-2/25, -3/25, 9/25]~]
-
-? rnfisfree(bnf2,aa)
-1
-? rnfsteinitz(nf2,aa)
-[[1, 0, 0, [-26/25, 11/25, -8/25]~, [29/125, -2/25, 8/125]~; 0, 1, 0, [53/25
-, -8/25, -1/25]~, [-53/125, 7/125, 1/125]~; 0, 0, 1, [-14/25, -21/25, 13/25]
-~, [9/125, 19/125, -13/125]~; 0, 0, 0, [7/25, -2/25, 6/25]~, [-9/125, 2/125,
- -6/125]~; 0, 0, 0, [9/25, 1/25, -3/25]~, [-8/125, -1/125, 3/125]~], [1, 1, 
-1, 1, [125, 0, 22; 0, 125, 108; 0, 0, 1]], [416134375, 202396875, 60056800; 
-0, 3125, 2700; 0, 0, 25], [-1275, 5, 5]~]
-? nfz=zetakinit(x^2-2);
-? zetak(nfz,-3)
-0.091666666666666666666666666666666666667
-? zetak(nfz,1.5+3*I)
-0.88324345992059326405525724366416928892 - 0.2067536250233895222724230899142
-7938848*I
-? setrand(1);quadclassunit(1-10^7,,[1,1])
-[2416, [1208, 2], [Qfb(277, 55, 9028), Qfb(1700, 1249, 1700)], 1]
-? setrand(1);quadclassunit(10^9-3,,[0.5,0.5])
-[4, [4], [Qfb(211, 31405, -16263, 0.E-57)], 2800.625251907016076486370621737
-0745514]
-? sizebyte(%)
-288
-? getheap
-[217, 91238]
-? print("Total time spent: ",gettime);
-Total time spent: 64
diff --git a/src/test/64/random b/src/test/64/random
deleted file mode 100644
index 71d38ab..0000000
--- a/src/test/64/random
+++ /dev/null
@@ -1,30 +0,0 @@
-Mod(2, 3)
-a^2
-[[a, a + 1], 1]
-3223690774*a^2 + 2495927739*a + 1543932468
-[[222673296*a^2 + 832141822*a + 1993872865, 3473855231*a^2 + 2165401445*a + 
-1363496513], 1]
-4063307077606482163*a^2 + 2169871353760194456*a + 10598342506117936052
-[[2557945391375694509*a^2 + 5182580949942002905*a + 4115304207846177355, 808
-4599253441901006*a^2 + 17319169765369271807*a + 5394713598728073384], 1]
-0.56071855301363810851584520787407920871
-Mod(5, 7)*x^3 + Mod(2, 7)*x^2 + Mod(1, 7)*x + Mod(6, 7)
-  ***   at top-level: randomprime(2)
-  ***                 ^--------------
-  *** randomprime: domain error in randomprime: N < 2
-  ***   at top-level: randomprime([0,1])
-  ***                 ^------------------
-  *** randomprime: domain error in randomprime: floor(b) - max(ceil(a),2) < 0
-  ***   at top-level: randomprime([2.5,2.4
-  ***                 ^--------------------
-  *** randomprime: domain error in randomprime: b-a < 0
-  ***   at top-level: randomprime([2.4,2.5
-  ***                 ^--------------------
-  *** randomprime: domain error in randomprime: floor(b) - max(ceil(a),2) < 0
-1051006573
-5
-1267650600228229401496703924683
-  ***   at top-level: random("")
-  ***                 ^----------
-  *** random: incorrect type in genrand (t_STR).
-Total time spent: 4
diff --git a/src/test/64/real b/src/test/64/real
deleted file mode 100644
index a67f7f7..0000000
--- a/src/test/64/real
+++ /dev/null
@@ -1,3 +0,0 @@
-5.85492786017126177 E347063955532709820
-1.707962973895205473 E-347063955532709821
-Total time spent: 0
diff --git a/src/test/64/rnfkummer b/src/test/64/rnfkummer
deleted file mode 100644
index 9dc8270..0000000
--- a/src/test/64/rnfkummer
+++ /dev/null
@@ -1,175 +0,0 @@
-  ***   Warning: new stack size = 20000000 (19.073 Mbytes).
-1
-x^3 + (774806212396682040403800911285727580902360710356054423617*y^3 + 97150
-6686017039131003298525517527246921922994336799568156*y^2 + 11821565693684429
-03321920531164159182095127947357116914844*y - 108151434729309365356471406894
-6874997341102881639770950564)*x + (-1101081691006188641718571980971003086516
-33373991261854661897473896921309979584250845786*y^3 - 1380613897447424014891
-54687510692802021389570171865180798324014776069968837855846155006*y^2 - 1679
-9696925608361694809806777136478453179953197918860855068694876240580160263314
-5257038*y + 1536946435524002857971775575314758204502648805624233135296867674
-44129838100365080190135)
-2
-x^3 + (19710886507130683637499481853346220*y^3 - 276380637484283870500207144
-441368652*y^2 + 321806883259334223558938029085301164*y - 2893764851921508720
-91555008989630209)*x + (6234404200069914092635781978921534907087800821965005
-*y^3 - 87417103564909472118499724747251035776212296637996160*y^2 + 101785081
-248253577808797714025930280347744436431138133*y - 91527591822456102976671051
-455070193926146359966708289)
-3
-x^5 + (6496145841479065310793035362475434921070895525/229919*y^3 - 329356645
-026252920894440103714065134919947272250/229919*y^2 - 48247357455860338551230
-0816299651400343793076825/229919*y + 123543801866424262505457797279174925381
-529732076495/229919)*x^3 + (-71021557287220849179024643469344999388010723208
-10325676573265995217846319711524646891132825/229919*y^3 + 312915518730297348
-797926075100976561711702080179753673084705465541436855444615670623948955500/
-229919*y^2 + 373389088629333541906488751920872126291403867985783777391039415
-1262039050473082240798959765475/229919*y - 186975830481723304596917319076060
-227260827340522313433115743539192208330842442737088985645016230/229919)*x + 
-(285331357696034096491305981627897525039281997301328341344454998449876878331
-78806777454970473740731009132513474900/229919*y^3 - 126322042014283687392680
-0705112647035932847475526596784692041313402766945033286681679632475546355981
-254757708245150/229919*y^2 - 14588214877690614738986561739773261402627551978
-016213443426143272871312909382946730136611425023860571069442516995750/229919
-*y + 74449855196093407639269271676900667861540430004636286318089786062493654
-8665702724402264597499043949735472272479146816/229919)
-4
-x^5 + 110*x^3 + 385*x^2 + (-6875*y + 13310)*x + (-20625*y - 32197)
-5
-x^5 + (590954467855790033665410099423754749157030026264928061890504926528336
-7772275490633617637549548608569718527277116446001864709881325798838750905729
-8030795258827639720428023363397609047544665809630635467286642736338355699480
-*y - 12615386542033504303879787410140086547604440260010207180712781991640642
-3422387588267289431462624116310719550083059856489949563282822945905208680310
-3334992487656834725937011490801952876482416400706750342081349443304520100091
-0)*x^3 + (-11644277774384555651776761259407289108977097641980228242435012611
-5006754047681181999487760953138546648235722021492042022118650990530538252856
-6414026821914198835648283336487147011301797121610470649794178541651897633010
-2619047628371992250175584734031123181309438679458163454790544342192453573731
-030635180622494122125396065225820240750*y + 24857594470800734810760217042859
-3197482585473219918102992436513064533871094674977546265869687753336958987424
-4725574396462863038560477800350177318131266777625357152677200654910979563229
-6935482013428626217783946905880811585673853237592381998183469149072919253974
-48956772571251782818646677614091807653908365676310869556566598028662310595)*
-x^2 + (-32086693829588024623316726000100010756361876262137235717978745230159
-7935024332597275728081239325323295559581472435768276459325858446852777406135
-4224237888838586662354341480780448138462095078298855585343788593872628558506
-2232497444401113004177020721408173287480234640696800006558695087522539471918
-8462351882227322473940035609517634436586317985311765355234869522092653871608
-552583923034075591677276229656463785917547906153809856186338690340273770*y +
- 684969938521412010632767736929174913834080110330425498234557819681514228146
-0090549891357621057501917177689832760208273044989366982124463965716426233156
-1527040802440908533713005052405522578751808660353806475066416377243465617273
-3705861162967500113371237563099623430813050413374757885431028358350978378497
-3112848884290316479154536924753537624150534114549576218278910101174064517316
-1007071339740860788236392250237982206266738278196933938408844992180)*x + (-4
-7914883868975351892993788361802360854236346782223242244790627280758059828224
-3706143321286494865672428790243301228341780405161796806191536135406165858060
-3771830086241493044029276729458390644416619292001887065020793855148330934570
-2458067687554516829069745689086923959238429341181386665587548793744841347291
-4498689385652837815737802716011684231376279161897401214472802917672969506723
-1726531825722049891535045895982805077957753979050666046159539157559954608670
-5280609870755665307644950794838520000466297270668595045517853970926619542467
-11193183042460393012*y + 102286185146717051912553759002903739674572708315527
-8177292654318235805156376457250460484024275697120301114067014612617128855593
-1140879004477270052052029080767411295114744444724422974609785562746185135249
-7148990880570567486377403008887101174292961952397946466565017968649906175409
-2628317871187630174976464224281745898238726541254470553169688694375326272602
-0141231081533644354618819738411776242588786830306751837706932242870021408128
-3604919815766725639113030288154884719519014500084386431221130684472131661639
-4338537789242874246402340373262458277723507004179)
-6
-x^5 + 1497313810*x^3 - 153069990594216277067332440*x^2 - 9993317827227414657
-08504771613701347765415*x + 421302153697978557238622899127897637801303537233
-83633556328
-7
-x^3 + (6*y^4 - 18*y^3 + 6*y^2 - 18*y - 12)*x + (-4*y^5 + 30*y^4 + 32*y^2 + 2
-4*y + 4)
-8
-x^5 + (677308732982301944730030845266716201702837696162187325328/5*y^3 + 481
-271319660811460139352501916644558975058261230836596652/5*y^2 - 3487807973304
-8511269299413306183851642254427026365686673888/5*y - 24783137893632185532697
-291886880720222932490781434136563942/5)*x^3 + (31218254245856135648287296707
-04559492032765858876683224121119983801219547643890505070*y^3 + 2218259473949
-490736667831079912338956828105689590705243343986337391928943383709808005*y^2
- - 1607587048361124753491934721194326369713341397761485813643339582894344828
-06877560648970*y - 114229487928172801039731551289054638597376141715926648946
-031483976252167029243247022480)*x^2 + (-166692999053535356002572927874917139
-2118748717302099608304683989705975477021372381764147057643564706588636619348
-44/5*y^3 - 11844618891597190508741280303272659573039434424283175367673479155
-0346393669679117451359918013807557809143042588696/5*y^2 + 858387225015985285
-7479162156889677342550132950704205078118190632176525884150800135006242479797
-595396229858998666474/5*y + 609939805478110246004601234032243326487160080269
-1098946100231203424708988718659688581036467351459717869466864403491/5)*x + (
--376194285951669846001777157888755029972864354842521262364492544230511805129
-9870709569967640457662697840860989973276516003636843449764721490044/5*y^3 - 
-2673104432455463952284352656647109245231103663592899118247897745294025980581
-570350460813923435311458682114748384710825808171997155877533243621/5*y^2 + 1
-9372161459591757660716692723884954611407620247350322071070721355639658608496
-4322202670927424345172110316287310450443586757567876756951302594424/5*y + 13
-7651773558650909762864388498297831958827163349141150095186154867116600261791
-580542516653158613689676015829782898702530873665348851222173825666/5)
-9
-x^3 + (-2138833799099964*y - 77766538091057475)*x + (-2899681696823107245657
-26*y - 10543044869724218021876124)
-10
-[x^3 + (-2138833799099964*y - 77766538091057475)*x + (-271454449233503516412
-931*y - 9869898621944137446807843), x^3 + (-2138833799099964*y - 77766538091
-057475)*x + (18513720448807208152795*y + 673146247780080575068281), x^3 + (-
-2138833799099964*y - 77766538091057475)*x + (-289968169682310724565726*y - 1
-0543044869724218021876124), x^3 - 3*x - 1]
-11
-x^5 - 10*x^3 + 20*x + 10
-12
-x^5 + (14433507922528796322450466885842559554649240/81*y^3 - 206924153900250
-190478940045819169994648120380/81*y^2 + 387221873734866129008668004845146809
-3411480/27*y + 9952907878012919545305461812329973812202320)*x^3 + (151213742
-1515820547988557267937916762553254164737251785897692300/27*y^3 + 18337121232
-6689306422734140437601099700562333545199409203074500/27*y^2 - 11743163565184
-2472537762690188912056014010181849092684109181910170/9*y + 27790231583332542
-847266778828385473838935385907433291290641467310)*x^2 + (-226693826937254370
-3014068118233450711618653187091810917531287989910268281950806313112830/81*y^
-3 + 239315207598088678889180580299531524598499432218877226931937677230073476
-51161135616414460/81*y^2 + 4557474129212450957128695360991332089101354211319
-1870218073887288396098516272850951573480/27*y - 4785071374094015662869316915
-362187463934517274549880463316992141982057530013804207289130)*x + (119270482
-8439928261324666320105890752409692593927875083779153072015384025578913692346
-3989511892271143598294/3*y^3 - 152961475704026365347150203105055935481447020
-419907822345352843160917118838486063790065390094212607259586902/3*y^2 - 9397
-8480302010002477264842168576217064771866107133401243553275407905590291763780
-391464292290112011298779372*y + 40510745442141622784634137179518469588738855
-3485545336064626090438935556037611475681610251702629961491235364)
-13
-x^5 + (332998327585787806210715462400*y - 3088099449668699468241894745310)*x
-^3 + (494543408306584524066234839600325678760597930*y - 45862068980974258959
-41238867752143070004508050)*x^2 + (26417254338273940545860942707750465903049
-7550267984532302200*y - 2449835384316313335292893982961063446219951623920034
-753322415)*x + (476291033688128034677862637907914049204992323838153758931557
-45202346081966*y - 441694133924899145700575613631246753719401915993262186949
-236663342183626850)
-14
-x^2 + (-246740429132141146463522518444668570440348378975804*y^5 + 4703956945
-787111585543964420667028301009723801572487*y^4 + 266190357187628389772307989
-7863774384599266481260032*y^3 - 39177999595004651251370478833094268643601230
-78018159*y^2 + 10590083476362079496920522735326808810513545604444961*y - 584
-8192501453958323706561054990087672915722280908328)
-15
-x^2 + (-920087175408128195117442723568586073341235912833280265/2*y^5 - 37050
-25155369837955703313470274107124929636667858610239*y^4 + 3476715311084623172
-771710772579521132641467422385394005*y^3 + 684153818451910860756827784361755
-8566461173006276695185/2*y^2 - 486305569529989362223536556373888481868397838
-5576079475*y + 292682713400104576552871705948634083358899219106803462)
-16
-x^2 + (7064114974621884209263957684*y^5 - 78597289737331354515763478580*y^4 
-+ 13905399960467092094726011945*y^3 - 27789415584376787513088098359*y^2 + 26
-854231387417039826858692319*y - 60884996981015832433185005956)
-17
-x^2 + (-8*y - 101)
-18
-x^2 - 5
-19
-x^3 + (-3*y^3 - 141/2*y^2 + 921*y - 6963/2)*x + (49621/3*y^3 - 547595/6*y^2 
-- 619772/3*y + 15840415/6)
-20
-[x^3 - 3*x - 1]
-Total time spent: 12057
diff --git a/src/test/in/agm b/src/test/in/agm
index 35c2aa6..5a1c7ac 100644
--- a/src/test/in/agm
+++ b/src/test/in/agm
@@ -16,3 +16,4 @@ testagm(x)= {
 }
 
 for(i=-6,6,for(j=-6,6,testagm(1/6+i/3+j*I/3)));
+agm(1,2+O(5))
diff --git a/src/test/in/algebras b/src/test/in/algebras
new file mode 100644
index 0000000..66653e5
--- /dev/null
+++ b/src/test/in/algebras
@@ -0,0 +1,2090 @@
+J = varhigher("J",y);
+default(realprecision,38);
+default(parisize,100M);
+Q=nfinit(y); T=polcyclo(5, 'x); F=rnfinit(Q, T);
+A = alginit(F, [Mod(x^2,T), 3]);
+print("contains nfabs: ", algsplittingfield(A)[12][1] != 0);
+A[1][12][1] = 0;
+A
+
+
+do(name, test) = {
+ setrand(1);
+ print(name,": ", iferr(test(), E, E));
+}
+gusuite(name, tests) = print("Suite: ", name); tests();
+
+gumaxtime = 3;
+
+searchin(hf,pr,h) =
+{
+  my(i,n);
+  for(i=1,#hf[1],
+    if(hf[1][i]==pr, return(hf[2][i]==h))
+  );
+  return(h==0);
+};
+
+samehasse(hf1,hi1,hf2,hi2) =
+{
+  my(i,n);
+  if(hi1 != hi2, return(0));
+
+  n = #hf1[1];
+  for(i=1,n,
+    if(!searchin(hf2,hf1[1][i],hf1[2][i]), return(0));
+  );
+
+  n = #hf2[1];
+  for(i=1,n,
+    if(!searchin(hf1,hf2[1][i],hf2[2][i]), return(0));
+  );
+
+  return(1);
+};
+
+hassetriv(hf,hi) = samehasse(hf,hi,[[],Vecsmall([])],Vecsmall(vector(#hi,i,0)));
+altriv(al) = hassetriv(alghassef(al),alghassei(al));
+alsame(al,hf,hi) = samehasse(alghassef(al),alghassei(al),hf,hi);
+
+testcharpol(al,a)=
+{ my (T = algcharpoly(al,a));
+  print(T);
+  !algpoleval(al,T,a);
+}
+get() = gusuite("get", ()->{
+  my(s='s,i='i,poli,nf,ii,pols,rnf,ss,al);
+  poli = i^2+1;
+  nf = nfinit(poli);
+  ii = Mod(i,poli);
+  pols = s^2+2;
+  rnf = rnfinit(nf, pols);
+  ss = Mod(s,pols);
+  al = alginit(rnf,[-ss,ii]);
+
+  do("degree", ()->algdegree(al)==2);
+  do("center", ()->algcenter(al)==nf);
+  do("splitting", ()->algsplittingfield(al)==rnf);
+  do("automorphism", ()->algaut(al)==-ss);
+  do("b", ()->algb(al)==ii);
+  do("trivial hasse invariants", ()->altriv(al));
+  do("charac", ()->algchar(al)==0);
+  do("dim", ()->algdim(al)==4);
+  do("absdim", ()->algabsdim(al)==8);
+  do("basis", ()->#algbasis(al)==8);
+  do("invbasis", ()->#alginvbasis(al)==8);
+  do("basis*invbasis", ()->algbasis(al)*alginvbasis(al)==matid(8));
+  do("iscyclic", ()->algtype(al)==3);
+  do("radical", ()->algradical(al)==0); \\cyclic => simple
+});
+
+operations() = gusuite("operations", ()->{
+  my(s='s,i='i,poli,nf,ii,pols,rnf,ss,al,n,un,u,j);
+  poli = i^2+1;
+  nf = nfinit(poli);
+  ii = Mod(i,poli);
+  pols = s^2+2;
+  rnf = rnfinit(nf, pols);
+  ss = Mod(s,pols);
+  ss = ss*Mod(1,poli);
+  al = alginit(rnf,[-ss,ii]);
+
+  do("radical", ()->algradical(al)==0); \\cyclic => simple
+
+  nfii = ii;
+  ii = ii*Mod(1,pols);
+
+  n = [-ss,ii-1]~;
+  un = [1,0]~;
+  u = [1-ss,ii-1]~;
+  j = [0,1]~;
+  do("addition", ()->algadd(al,n,un)==u);
+  do("negation", ()->algneg(al,u)==[ss-1,1-ii]~);
+  do("soustraction", ()->algsub(al,u,n)==un);
+  do("multiplication", ()->algmul(al,n,un)==n);
+  do("non-commutativity", ()->algmul(al,n,j)==algmul(al,j,n));
+  do("left division", ()->algdivl(al,u,n)==n);
+  do("right division", ()->algdivr(al,n,u)==n);
+  do("noncommutative left division", ()->algdivl(al,u,j)==[ii+1,1-ss]~);
+  do("noncommutative right division", ()->algdivr(al,j,u)==[ii+1,1+ss]~);
+  do("division by non-invertible", ()->algdivl(al,n,u));
+  do("nilpotent", ()->algsqr(al,n)==[0,0]~);
+  do("square", ()->algsqr(al,u)==algadd(al,u,n));
+  do("square j", ()->algsqr(al,j)==[ii,0]~);
+  do("inverse", ()->alginv(al,u)==algsub(al,un,n));
+  do("powers", ()->algpow(al,u,124)==algadd(al,un,algmul(al,[124,0]~,n)));
+  do("negative powers", ()->algpow(al,j,-56)==un);
+  do("multiplication table j", ()->algmultable(al,j)==[0,ii;1,0]);
+  do("multiplication table", ()->algmultable(al,u)==[1-ss,-1-ii;ii-1,1+ss]);
+  do("characteristic polynomial", ()->algcharpoly(al,u,'y)==y^2-2*y+1);
+  do("characteristic polynomial j", ()->algcharpoly(al,j,'y)==y^2-nfii);
+  do("trace zero", ()->algtrace(al,n)==0);
+  do("trace commutator", ()->algtrace(al,algsub(al,algmul(al,j,u),algmul(al,u,j)))==0);
+  do("trace", ()->algtrace(al,algmul(al,u,j))==-2-2*nfii);
+  do("norm zero", ()->algnorm(al,n)==0);
+  do("norm one", ()->algnorm(al,u)==1);
+  do("norm j", ()->algnorm(al,j)==-nfii);
+  a = algadd(al,u,j); b = algadd(al, n, [12-4*ii+ss*(4-ii),7+3*ii+ss*(1+7*ii)]~);
+  do("norm is multiplicative a*b", ()->nfalgtobasis(nf,algnorm(al,algmul(al,a,b)))==nfalgtobasis(nf,nfeltmul(nf,algnorm(al,a),algnorm(al,b))));
+  do("norm is multiplicative b*a", ()->nfalgtobasis(nf,algnorm(al,algmul(al,b,a)))==nfalgtobasis(nf,nfeltmul(nf,algnorm(al,b),algnorm(al,a))));
+  do("poleval", ()->algbasistoalg(al,algpoleval(al,x^3-2,u)) ==\
+algsub(al,algpow(al,u,3),[2,0]~));
+  do("poleval b", ()->algbasistoalg(al,algpoleval(al,x^3+i*x-3*i,u)) ==\
+algsub(al,algadd(al,algpow(al,u,3), algmul(al,[i,0]~,u)), [3*i,0]~));
+});
+
+alcheckhasse(al) =
+{
+  my(n,h);
+  n = algdegree(al);
+  h = Mod(0,n);
+  for(i=1, #alghassef(al)[1],
+      h += alghassef(al)[2][i]);
+  for(i=1, #alghassei(al),
+      h += (n/2)*alghassei(al)[i]);
+  return(h == Mod(0,n));
+};
+
+al_cyclotomic(p,b,mo=1) =
+{
+  my(Q,F,pc,r);
+  Q = nfinit(y);
+  pc = polcyclo(p,x);
+  F = rnfinit(Q,pc);
+  r = lift(znprimroot(p));
+  return(alginit(F, [Mod(Mod(1,y)*x^r,pc), b], 'x, mo));
+};
+
+hasse0() = gusuite("hasse sum to 0", ()->{
+  do("cyclo construction", ()->al_cyclotomic(3,-175624635));
+  do("cyclo ramified at infinity", ()->alcheckhasse(al_cyclotomic(3,-175624635)));
+  do("cyclo unramified at infinity", ()->alcheckhasse(al_cyclotomic(3,2763764)));
+  do("cyclo 5", ()->alcheckhasse(al_cyclotomic(5,7861623)));
+  do("cyclo 5 bis", ()->alcheckhasse(al_cyclotomic(5,6569846846546548798*25)));
+  do("cyclo 7 bis no mo", ()->alcheckhasse(al_cyclotomic(7,168656465154165487*7^3,0)));
+  do("cyclo 11 no mo", ()->alcheckhasse(al_cyclotomic(11,87165765,0)));
+  do("quat -1,-1 over Q", ()->alcheckhasse(alginit(nfinit(y),[-1,-1])));
+  do("quat -1,-1 over Q(sqrt(2))", ()->alcheckhasse(alginit(nfinit(y^2-2),[-1,-1],x)));
+  do("quat -1,-1 over Q(sqrt(60))", ()->alcheckhasse(alginit(nfinit(y^2-60),[-1,-1],x)));
+});
+
+nfcompo() = gusuite("compositum of relative extensions", ()->{
+  my(nf, pol, ii);
+  pol = y^2+1;
+  nf = nfinit(pol);
+  ii = Mod(y,pol);
+
+  do("compositum of degrees 2 and 3 over quadratic field", (()->my(L=nfcompositum(nf,x^2-ii,x^3-5,3), a=Mod(L[2],L[1]), b=Mod(L[3],L[1])); polisirreducible(L[1]) && a^2-ii==0 && b^3-5==0 && b+L[4]*a==Mod(x,L[1])));
+  do("compositum of degrees 2 and 4 over quadratic field", (()->my(L=nfcompositum(nf,x^2-ii,x^4-5,3), a=Mod(L[2],L[1]), b=Mod(L[3],L[1])); polisirreducible(L[1]) && a^2-ii==0 && b^4-5==0 && b+L[4]*a==Mod(x,L[1])));
+  do("compositum of degrees 5 and 7 over quadratic field", (()->my(L=nfcompositum(nf,x^5+ii*x+1,x^7-5*x+ii,3), a=Mod(L[2],L[1]), b=Mod(L[3],L[1])); polisirreducible(L[1]) && a^5+ii*a+1==0 && b^7-5*b+ii==0 && b+L[4]*a==Mod(x,L[1])));
+
+  pol = y^5-2;
+  nf = nfinit(pol);
+  ii = Mod(y,pol);
+
+  do("compositum of degrees 2 and 3 over degree 5 field", (()->my(L=nfcompositum(nf,x^2-ii,x^3-5,3), a=Mod(L[2],L[1]), b=Mod(L[3],L[1])); polisirreducible(L[1]) && a^2-ii==0 && b^3-5==0 && b+L[4]*a==Mod(x,L[1])));
+  do("compositum of degrees 2 and 4 over degree 5 field", (()->my(L=nfcompositum(nf,x^2-ii,x^4-5,3), a=Mod(L[2],L[1]), b=Mod(L[3],L[1])); polisirreducible(L[1]) && a^2-ii==0 && b^4-5==0 && b+L[4]*a==Mod(x,L[1])));
+  do("compositum of degrees 5 and 4 over degree 5 field", (()->my(L=nfcompositum(nf,x^5+ii*x+1,x^4-5*x+ii,3), a=Mod(L[2],L[1]), b=Mod(L[3],L[1])); polisirreducible(L[1]) && a^5+ii*a+1==0 && b^4-5*b+ii==0 && b+L[4]*a==Mod(x,L[1])));
+});
+
+tensor() = gusuite("tensor product of cyclic algebras", ()->{
+  my(nf,pol,jj,al1,al2,al3,hf12,hf23,p7,p7b,p3,p5);
+  pol = y^2+y+1;
+  nf = nfinit(pol);
+  jj = Mod(y,pol);
+  al1 = alginit(rnfinit(nf,x^2-(1+jj)), [-x, 4*jj+5]);
+  al2 = alginit(rnfinit(nf,x^3-2), [jj*x, 7]);
+  al3 = alginit(rnfinit(nf,x^4+x^3+x^2+x+1), [x^2, 7]);
+  do("radical 1", ()->algradical(al1)==0); \\cyclic => simple
+  do("radical 2", ()->algradical(al2)==0); \\cyclic => simple
+  do("radical 3", ()->algradical(al3)==0); \\cyclic => simple
+  p3 = idealprimedec(nf,3)[1];
+  p5 = idealprimedec(nf,5)[1];
+  p7 = idealprimedec(nf,7)[1];
+  p7b = idealprimedec(nf,7)[2];
+
+  hf12 = [[p3,p7,p7b],Vecsmall([3,4,5])];
+  hf23 = [[p5,p7,p7b],Vecsmall([6,11,7])];
+
+  do("tensor of degree 2 and 3 no mo", ()->alsame(algtensor(al1,al2,0),hf12,Vecsmall([])));
+});
+
+rnfprimedec2(rnf,pp,nf2) = {
+  my(nf = rnf.nf,pp2,pp3);
+  pp2 = rnfidealup(rnf,pp);
+  pp3 = idealadd(nf2,pp2[1],pp2[2]);
+  for(i=3, #pp2,
+    pp3 = idealadd(nf2,pp3,pp2[i]));
+  return(idealfactor(nf2,pp3));
+};
+
+rnfprimedec(rnf,pp) = rnfprimedec2(rnf,pp,nfinit(rnf.polabs));
+
+testgwa(nf,Lpr,Ld,pl) = ()->{
+  my(rnf, d, n, nf2);
+  rnf = rnfinit(nf,nfgrunwaldwang(nf,Lpr,Ld,pl,x));
+  d = rnf.disc[1];
+  n = poldegree(rnf.pol);
+  return(1);
+  nf2 = nfinit(rnf.polabs);
+  for(i=1,#Lpr,
+    if(#mattranspose(rnfprimedec2(rnf,Lpr[i],nf2))*Ld[i] != n, return(0)));
+  return(1);
+};
+
+gw() = gusuite("Grunwald-Wang", ()->{
+  my(p2,p3,p5,p7,p11,p13,p17,pp,ppp,nf);
+  nf = nfinit(y);
+  p2 = idealprimedec(nf,2)[1];
+  p3 = idealprimedec(nf,3)[1];
+  p5 = idealprimedec(nf,5)[1];
+  pp = idealprimedec(nf,nextprime(1234))[1];
+  ppp = idealprimedec(nf,nextprime(4321))[1];
+
+  do("A quadratic over Q, 2 large inert, imaginary", testgwa(nf,[pp,ppp],Vecsmall([2,2]),Vecsmall([-1])));
+  do("A quartic over Q, 2 large inert, imaginary", testgwa(bnfinit(nf),[pp,ppp],Vecsmall([4,4]),Vecsmall([-1])));
+
+  nf = nfinit(y^2+1);
+  p2 = idealprimedec(nf,2)[1];
+  p3 = idealprimedec(nf,3)[1];
+  p5 = idealprimedec(nf,5)[1];
+  do("A : degree 4 over Q(i), local degrees [4,1,1]", testgwa(nf,[p2,p3,p5],Vecsmall([4,1,1]),Vecsmall([])));
+
+  nf = nfinit(y^2+y+1);
+  p2 = idealprimedec(nf,2)[1];
+  p3 = idealprimedec(nf,3)[1];
+  p5 = idealprimedec(nf,5)[1];
+  p7 = idealprimedec(nf,7)[1];
+  pp = idealprimedec(nf,nextprime(1248))[1];
+  ppp = idealprimedec(nf,nextprime(7531))[1];
+
+  do("A degree 3 over Q(j), local degrees [3,3] larger primes", testgwa(nf,[pp,ppp],[3,3],[]));
+
+  nf = nfinit(y^2-5);
+  p2 = idealprimedec(nf,2)[1];
+  p3 = idealprimedec(nf,3)[1];
+  p5 = idealprimedec(nf,5)[1];
+  p7 = idealprimedec(nf,7)[1];
+  p11 = idealprimedec(nf,11)[1];
+  p13 = idealprimedec(nf,13)[1];
+  p17 = idealprimedec(nf,17)[1];
+  pp = idealprimedec(nf,nextprime(1248))[1];
+  ppp = idealprimedec(nf,nextprime(4897))[1];
+
+  do("A : degree 3 over Q(sqrt(5)), local degrees [3,3] [0,0], larger primes",
+testgwa(nf,[pp,ppp],[3,3],[0,0]));
+  /* TODO check what happens with [-1,-1] */
+
+  nf = nfinit(y^2-7);
+  p2 = idealprimedec(nf,2)[1];
+  p3 = idealprimedec(nf,3)[1];
+  p5 = idealprimedec(nf,5)[1];
+  p7 = idealprimedec(nf,7)[1];
+  p11 = idealprimedec(nf,11)[1];
+  p13 = idealprimedec(nf,13)[1];
+  p17 = idealprimedec(nf,17)[1];
+
+  do("A : degree 5 over Q(sqrt(7)), local degrees [5,5,5,5,5,5,5] [0,0]",
+testgwa(nf,[p2,p3,p5,p7,p11,p13,p17],Vecsmall([5,5,5,5,5,5,5]),Vecsmall([0,0])));
+  /* TODO check what happens with [-1,-1] */
+
+  nf = nfinit(polcyclo(9,y));
+  p2 = idealprimedec(nf,2)[1];
+  p3 = idealprimedec(nf,3)[1];
+  p5 = idealprimedec(nf,5)[1];
+  p7 = idealprimedec(nf,7)[1];
+  do("A : degree 9 over Q(zeta_9), local degrees [9,9,9,9]", testgwa(nf,[p2,p3,p5,p7],Vecsmall([9,9,9,9]),Vecsmall([])));
+
+  nf = nfinit(y^6 -y^5 -7*y^4 +2*y^3 +7*y^2 -2*y -1);
+  p2 = idealprimedec(nf,2)[1];
+  p3 = idealprimedec(nf,3)[1];
+  p5 = idealprimedec(nf,5)[1];
+  p7 = idealprimedec(nf,7)[1];
+  p11 = idealprimedec(nf,11)[1];
+  p13 = idealprimedec(nf,13)[1];
+  p17 = idealprimedec(nf,17)[1];
+  pp = idealprimedec(nf,nextprime(1357))[1];
+  ppp = idealprimedec(nf,nextprime(853))[1];
+
+  do("A degree 2 over totally real sextic, local degrees [2,2] [2,2,2,2,2,2], larger primes", testgwa(nf,[pp,ppp],Vecsmall([2,2]),Vecsmall([-1,-1,-1,-1,-1,-1])));
+
+  do("A degree 2 over totally real sextic, local degrees [] [2,2,2,2,2,2]", testgwa(nf,[],Vecsmall([]),Vecsmall([-1,-1,-1,-1,-1,-1])));
+});
+
+alfromhasse() = gusuite("algebra from Hasse invariants", ()->{
+  my(nf, pr7, pr13, finvm, finv, finv1, finv2, iinvm, iinv, iinv1, iinv2, d1, d2, d, dm, mai, al);
+  nf = nfinit(y^3+y^2-2*y-1);
+  pr7 = idealprimedec(nf,7);
+  pr13 = idealprimedec(nf,13);
+
+  al = alginit(nf,3,J);
+  do("matrix algebra invariants", ()->altriv(al));
+
+  d1 = 3;
+  finv1 = [pr13,Vecsmall([1,1,1])];
+  iinv1 = Vecsmall([0,0,0]);
+  al = alginit(nf,[d1,finv1,iinv1],J);
+  do("algebra 1 invariants", ()->alsame(al,finv1,iinv1));
+
+  d2 = 2;
+  finv2 = [pr7,Vecsmall([1])];
+  iinv2 = Vecsmall([1,0,0]);
+  al = alginit(nf,[d2,finv2,iinv2],J);
+  do("algebra 2 invariants", ()->alsame(al,finv2,iinv2));
+
+  nf = nfinit(y);
+  p13 = idealprimedec(nf,13)[1];
+  finv1 = [[p13],[Mod(1,2)]];
+  iinv1 = Vecsmall([1]);
+  do("test", ()->alginit(nf,[2,finv1,iinv1],J));
+
+  d = 6;
+  p3 = idealprimedec(nf,3)[1];
+  p5 = idealprimedec(nf,5)[1];
+  p7 = idealprimedec(nf,7)[1];
+  p11 = idealprimedec(nf,11)[1];
+  finv = [[p3,p5,p7,p11], Vecsmall([3,2,2,2])];
+  iinv = Vecsmall([3]);
+  al = alginit(nf,[d,finv,iinv],J,0);
+  do("degree 6 algebra over Q", ()->alsame(al,finv,iinv));
+
+  nf = nfinit(y^2-5);
+  finv1 = [[],[]];
+  iinv1 = Vecsmall([1,1]);
+  do("trivial finite conditions", ()->my(al=alginit(nf,[2,finv1,iinv1]));
+    [alghassei(al),alghassef(al)]);
+
+});
+
+moreoperations() = gusuite("more operations", ()->{
+  my(x='x, y='y, nf, p1, p2, iinv, finv, al, u, t, b, w, un, pol1, pol2, cp, mul, rnf, aut, ww, tt, ord, invord);
+
+  pol1 = y;
+  nf = nfinit(pol1);
+  p1 = idealprimedec(nf,2)[1];
+  p2 = idealprimedec(nf,3)[1];
+  iinv = [0];
+  finv = [[p1,p2],[-2/3,-1/3]];
+  al = alginit(nf,[3,finv,iinv],x);
+
+  do("construct algebra", ()->al);
+
+  pol2 = algsplittingfield(al).pol;
+  mul = Mod(1,pol1)*Mod(1,pol2);
+  u = [0,1,0]~*mul;
+  t = [x,0,0]~*mul;
+  b = [algb(al),0,0]~*mul;
+  w = [x+x^2-7,1/2+x-3/7*x^2,12*x-1]~*mul;
+  un = [1,0,0]~*mul;
+
+  do("norm(u)", ()->lift(algnorm(al,u))==lift(algb(al)));
+  do("norm(t)", ()->algnorm(al,t)==rnfeltnorm(algsplittingfield(al),x));
+  do("trace(u)", ()->algtrace(al,u)==0);
+  do("trace(t)", ()->algtrace(al,t)==rnfelttrace(algsplittingfield(al),x));
+  do("u+t", ()->algadd(al,u,t)==algadd(al,t,u));
+  do("u*t", ()->algmul(al,u,t)!=algmul(al,t,u));
+  do("u^3", ()->algpow(al,u,3)==b);
+  do("w^-1 L", ()->algmul(al,w,alginv(al,w))==un);
+  do("w^-1 R", ()->algmul(al,alginv(al,w),w)==un);
+  do("w^-1*u", ()->algmul(al,w,algdivl(al,w,u)));
+  do("u*w^-1", ()->algmul(al,algdivr(al,u,w),w));
+  cp = algcharpoly(al,w,'Y);
+  do("charpol(w)", ()->cp);
+  do("eval charpol", ()->algadd(al,algadd(al,algpow(al,w,3),algmul(al,[polcoeff(cp,2),0,0]~*mul,algsqr(al,w))),algadd(al,algmul(al,[polcoeff(cp,1),0,0]~*mul,w),[polcoeff(cp,0),0,0]~*mul))==0);
+  do("trace(w)", ()->algtrace(al,w)==-polcoeff(cp,2));
+  do("norm(w)", ()->algnorm(al,w)==-polcoeff(cp,0));
+  do("dim", ()->algdim(al)==9);
+  do("absdim", ()->algabsdim(al)==9);
+  do("iscommutative", ()->algiscommutative(al)==0);
+  do("issemisimple", ()->algissemisimple(al)==1);
+  do("issimple", ()->algissimple(al)==1);
+
+  pol1 = y^2+1;
+  nf = nfinit(pol1);
+  pol2 = x^3 + x^2 - 2*x - 1;
+  rnf = rnfinit(nf,pol2);
+  aut = x^2-2;
+  al = alginit(rnf,[aut,Mod(2,pol1)]);
+  mul = Mod(1,pol1)*Mod(1,pol2);
+  u = [0,1,0]~*mul;
+  t = [x,0,0]~*mul;
+  tt = [y*x,0,0]~*mul;
+  b = [2,0,0]~*mul;
+  un = [1,0,0]~*mul;
+  w = [y*x-1/3*x^2, 2+y/7-x, -12*x-3*y*x^2]~*mul;
+  ww = [-x^2*y, 1/13+y+x+4*x^2, (-2+y)*x^2+(y/3+1/5)*x]~*mul;
+  ord = algbasis(al);
+  invord = alginvbasis(al);
+  do("algmultable w+ww", ()->algmultable(al,algadd(al,w,ww))==(algmultable(al,w)+algmultable(al,ww)));
+  do("algmultable w*ww", ()->algmultable(al,algmul(al,w,ww))==(algmultable(al,w)*algmultable(al,ww)));
+  do("alg(basis(w))", ()->algbasistoalg(al,algalgtobasis(al,w))==w);
+  do("alg(basis(ww))", ()->algbasistoalg(al,algalgtobasis(al,ww))==ww);
+  do("basis(w)+ww", ()->algadd(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algadd(al,w,ww)));
+  do("basis(w)-ww", ()->algsub(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algsub(al,w,ww)));
+  do("w+basis(ww)", ()->algadd(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algadd(al,w,ww)));
+  do("w-basis(ww)", ()->algsub(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algsub(al,w,ww)));
+  do("basis(w)*ww", ()->algmul(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algmul(al,w,ww)));
+  do("w*basis(ww)", ()->algmul(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algmul(al,w,ww)));
+  do("basis(w)^2", ()->algsqr(al,algalgtobasis(al,w))==algalgtobasis(al,algsqr(al,w)));
+  do("basis(ww)^2", ()->algsqr(al,algalgtobasis(al,ww))==algalgtobasis(al,algsqr(al,ww)));
+  do("basis(w)\ww", ()->algdivl(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivl(al,w,ww)));
+  do("w\basis(ww)", ()->algdivl(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivl(al,w,ww)));
+  do("basis(ww)\w", ()->algdivl(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivl(al,ww,w)));
+  do("ww\basis(w)", ()->algdivl(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivl(al,ww,w)));
+  do("basis(w)^-1", ()->alginv(al,algalgtobasis(al,w))==algalgtobasis(al,alginv(al,w)));
+  do("basis(ww)^-1", ()->alginv(al,algalgtobasis(al,ww))==algalgtobasis(al,alginv(al,ww)));
+  do("basis(w)/ww", ()->algdivr(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivr(al,w,ww)));
+  do("w/basis(ww)", ()->algdivr(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivr(al,w,ww)));
+  do("basis(ww)/w", ()->algdivr(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivr(al,ww,w)));
+  do("ww/basis(w)", ()->algdivr(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivr(al,ww,w)));
+  do("trace(basis(w))", ()->algtrace(al,w)==algtrace(al,algalgtobasis(al,w)));
+  do("trace(basis(ww))", ()->algtrace(al,ww)==algtrace(al,algalgtobasis(al,ww)));
+  w = [0,0,x*y]~*mul;
+  ww = [1+y,1+x,1+x^2]~*mul;
+  do("alg(basis(w)) 2", ()->algbasistoalg(al,algalgtobasis(al,w))==w);
+  do("alg(basis(ww)) 2", ()->algbasistoalg(al,algalgtobasis(al,ww))==ww);
+  do("basis(w)+ww 2", ()->algadd(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algadd(al,w,ww)));
+  do("basis(w)-ww 2", ()->algsub(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algsub(al,w,ww)));
+  do("w+basis(ww) 2", ()->algadd(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algadd(al,w,ww)));
+  do("w-basis(ww) 2", ()->algsub(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algsub(al,w,ww)));
+  do("basis(w)*ww 2", ()->algmul(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algmul(al,w,ww)));
+  do("w*basis(ww) 2", ()->algmul(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algmul(al,w,ww)));
+  do("basis(w)^2 2", ()->algsqr(al,algalgtobasis(al,w))==algalgtobasis(al,algsqr(al,w)));
+  do("basis(ww)^2 2", ()->algsqr(al,algalgtobasis(al,ww))==algalgtobasis(al,algsqr(al,ww)));
+  do("basis(w)\ww 2", ()->algdivl(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivl(al,w,ww)));
+  do("w\basis(ww) 2", ()->algdivl(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivl(al,w,ww)));
+  do("basis(ww)\w 2", ()->algdivl(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivl(al,ww,w)));
+  do("ww\basis(w) 2", ()->algdivl(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivl(al,ww,w)));
+  do("basis(w)^-1 2", ()->alginv(al,algalgtobasis(al,w))==algalgtobasis(al,alginv(al,w)));
+  do("basis(ww)^-1 2", ()->alginv(al,algalgtobasis(al,ww))==algalgtobasis(al,alginv(al,ww)));
+  do("basis(w)/ww 2", ()->algdivr(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivr(al,w,ww)));
+  do("w/basis(ww) 2", ()->algdivr(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivr(al,w,ww)));
+  do("basis(ww)/w 2", ()->algdivr(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivr(al,ww,w)));
+  do("ww/basis(w) 2", ()->algdivr(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivr(al,ww,w)));
+  do("trace(basis(w)) 2", ()->algtrace(al,w)==algtrace(al,algalgtobasis(al,w)));
+  do("trace(basis(ww)) 2", ()->algtrace(al,ww)==algtrace(al,algalgtobasis(al,ww)));
+  w = [1/2,1/3*x,1/5]~*mul;
+  ww = [1+y,1+x,1+x^2]~*mul;
+  do("alg(basis(w)) 3", ()->algbasistoalg(al,algalgtobasis(al,w))==w);
+  do("alg(basis(ww)) 3", ()->algbasistoalg(al,algalgtobasis(al,ww))==ww);
+  do("basis(w)+ww 3", ()->algadd(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algadd(al,w,ww)));
+  do("basis(w)-ww 3", ()->algsub(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algsub(al,w,ww)));
+  do("w+basis(ww) 3", ()->algadd(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algadd(al,w,ww)));
+  do("w-basis(ww) 3", ()->algsub(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algsub(al,w,ww)));
+  do("basis(w)*ww 3", ()->algmul(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algmul(al,w,ww)));
+  do("w*basis(ww) 3", ()->algmul(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algmul(al,w,ww)));
+  do("basis(w)^2 3", ()->algsqr(al,algalgtobasis(al,w))==algalgtobasis(al,algsqr(al,w)));
+  do("basis(ww)^2 3", ()->algsqr(al,algalgtobasis(al,ww))==algalgtobasis(al,algsqr(al,ww)));
+  do("basis(w)\ww 3", ()->algdivl(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivl(al,w,ww)));
+  do("w\basis(ww) 3", ()->algdivl(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivl(al,w,ww)));
+  do("basis(ww)\w 3", ()->algdivl(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivl(al,ww,w)));
+  do("ww\basis(w) 3", ()->algdivl(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivl(al,ww,w)));
+  do("basis(w)^-1 3", ()->alginv(al,algalgtobasis(al,w))==algalgtobasis(al,alginv(al,w)));
+  do("basis(ww)^-1 3", ()->alginv(al,algalgtobasis(al,ww))==algalgtobasis(al,alginv(al,ww)));
+  do("basis(w)/ww 3", ()->algdivr(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivr(al,w,ww)));
+  do("w/basis(ww) 3", ()->algdivr(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivr(al,w,ww)));
+  do("basis(ww)/w 3", ()->algdivr(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivr(al,ww,w)));
+  do("ww/basis(w) 3", ()->algdivr(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivr(al,ww,w)));
+  do("trace(basis(w)) 3", ()->algtrace(al,w)==algtrace(al,algalgtobasis(al,w)));
+  do("trace(basis(ww)) 3", ()->algtrace(al,ww)==algtrace(al,algalgtobasis(al,ww)));
+  do("radical", ()->algradical(al)==0); \\cyclic => simple
+  do("iscommutative cyc 3", ()->algiscommutative(al)==0);
+  do("issemisimple cyc 3", ()->algissemisimple(al)==1);
+  do("issimple cyc 3", ()->algissimple(al)==1);
+
+  pol1 = y;
+  nf = nfinit(pol1);
+  pol2 = x^2-2;
+  rnf = rnfinit(nf,pol2);
+  aut = -x;
+  al = alginit(rnf,[aut,Mod(5,pol1)]);
+  mul = Mod(1,pol1)*Mod(1,pol2);
+  u = [0,1]~*mul;
+  t = [x,0]~*mul;
+  b = [5,0]~*mul;
+  un = [1,0]~*mul;
+  w = [-1/3*x^2, 2/7-x]~*mul;
+  ww = [-x^2*4, 1/13+x+4*x^2]~*mul;
+  ord = algbasis(al);
+  invord = alginvbasis(al);
+  do("algmultable/Q w+ww", ()->algmultable(al,algadd(al,w,ww))==(algmultable(al,w)+algmultable(al,ww)));
+  do("algmultable/Q w*ww", ()->algmultable(al,algmul(al,w,ww))==(algmultable(al,w)*algmultable(al,ww)));
+  do("alg(basis(w))/Q", ()->algbasistoalg(al,algalgtobasis(al,w))==w);
+  do("alg(basis(ww))/Q", ()->algbasistoalg(al,algalgtobasis(al,ww))==ww);
+  do("basis(w)+ww/Q", ()->algadd(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algadd(al,w,ww)));
+  do("basis(w)-ww/Q", ()->algsub(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algsub(al,w,ww)));
+  do("w+basis(ww)/Q", ()->algadd(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algadd(al,w,ww)));
+  do("w-basis(ww)/Q", ()->algsub(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algsub(al,w,ww)));
+  do("basis(w)*ww/Q", ()->algmul(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algmul(al,w,ww)));
+  do("w*basis(ww)/Q", ()->algmul(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algmul(al,w,ww)));
+  do("basis(w)^2/Q", ()->algsqr(al,algalgtobasis(al,w))==algalgtobasis(al,algsqr(al,w)));
+  do("basis(ww)^2/Q", ()->algsqr(al,algalgtobasis(al,ww))==algalgtobasis(al,algsqr(al,ww)));
+  do("basis(w)\ww/Q", ()->algdivl(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivl(al,w,ww)));
+  do("w\basis(ww)/Q", ()->algdivl(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivl(al,w,ww)));
+  do("basis(ww)\w/Q", ()->algdivl(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivl(al,ww,w)));
+  do("ww\basis(w)/Q", ()->algdivl(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivl(al,ww,w)));
+  do("basis(w)^-1/Q", ()->alginv(al,algalgtobasis(al,w))==algalgtobasis(al,alginv(al,w)));
+  do("basis(ww)^-1/Q", ()->alginv(al,algalgtobasis(al,ww))==algalgtobasis(al,alginv(al,ww)));
+  do("basis(w)/ww/Q", ()->algdivr(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivr(al,w,ww)));
+  do("w/basis(ww)/Q", ()->algdivr(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivr(al,w,ww)));
+  do("basis(ww)/w/Q", ()->algdivr(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivr(al,ww,w)));
+  do("ww/basis(w)/Q", ()->algdivr(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivr(al,ww,w)));
+  do("trace(basis(w))/Q", ()->algtrace(al,w)==algtrace(al,algalgtobasis(al,w)));
+  do("trace(basis(ww))/Q", ()->algtrace(al,ww)==algtrace(al,algalgtobasis(al,ww)));
+  do("radical/Q", ()->algradical(al)==0); \\cyclic => simple
+  do("iscommutative /Q", ()->algiscommutative(al)==0);
+  do("issemisimple /Q", ()->algissemisimple(al)==1);
+  do("issimple /Q", ()->algissimple(al)==1);
+});
+
+tablealg() = gusuite("table algebra", ()->{
+  my(x='x, al, mt, p, un, a, b, c, d, e, ss, projm, liftm, pa, sc);
+  mt = [[1,0,0;0,1,0;0,0,1],[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]]; \\Matrices [*,*;0,*]
+  un = [1,0,0]~;
+  a = [1,0,-1]~;
+  b = [0,-1,1]~;
+  do("algisassociative 0.0", ()->algisassociative(mt));
+  do("algisassociative 0.1", ()->algisassociative(mt[2..3]));
+  my (mt0 = mt);
+  mt0[3][3,1] = 1;
+  do("algisassociative 0.2", ()->algisassociative(mt0));
+  do("algisassociative 0.3", ()->algisassociative('x));
+  al = algtableinit(mt,0);
+  do("construction 0", ()->al);
+  do("iscyclic 0", ()->algtype(al)==1);
+  do("dim 0", ()->algabsdim(al)==3);
+  do("dim 0b", ()->algdim(al)==3);
+  do("char 0", ()->algchar(al)==0);
+  do("a+b 0", ()->algadd(al,a,b)==[1,-1,0]~);
+  do("a-b 0", ()->algsub(al,a,b)==[1,1,-2]~);
+  do("a*b 0", ()->algmul(al,a,b)==[0,-1,0]~);
+  do("b*a 0", ()->algmul(al,b,a)==[0,0,0]~);
+  do("a^2 0", ()->algsqr(al,a)==a);
+  do("b^2 0", ()->algsqr(al,b)==b);
+  e = [1,1,0]~;
+  do("e^691691 0", ()->algpow(al,e,691691)==[1,691691,0]~);
+  d = [1,0,1]~;
+  do("d^101 0", ()->algpow(al,d,101)==[1,0,2^101-1]~);
+  do("multable(a) 0", ()->algmultable(al,a)==[1,0,0;0,1,0;-1,0,0]);
+  do("multable(b) 0", ()->algmultable(al,b)==[0,0,0;-1,0,-1;1,0,1]);
+  do("divl(d,a) 0", ()->algdivl(al,d,a)==a);
+  do("divl(d,b) 0", ()->algdivl(al,d,b)==[0,-1,1/2]~);
+  do("d^-1 0", ()->alginv(al,d)==[1,0,-1/2]~);
+  do("divr(a,d) 0", ()->algdivr(al,a,d)==a);
+  do("divr(b,d) 0", ()->algdivr(al,b,d)==[0,-1/2,1/2]~);
+  c = [0,7,0]~;
+  do("rad(al) 0", ()->#algradical(al)==1); \\matrices [0,*;0,0]
+  do("ss(al) 0", ()->#algradical(algquotient(al,algradical(al)))==0);
+  [ss,projm,liftm] = algquotient(al,algradical(al),1);
+  pa = projm*a;
+  do("proj(a) idem 0", ()->algsqr(ss,pa)==pa);
+  do("idemproj 0", ()->algcentralproj(ss,[pa,algsub(ss,projm*un,pa)]));
+  sc = algcentralproj(ss,[pa,algsub(ss,projm*un,pa)]);
+  do("simple components 0", ()->algmultable(sc[1])==[Mat(1)] && algmultable(sc[2])==[Mat(1)]);
+  do("center al 0", ()->#algcenter(al)==1);
+  do("center ss 0", ()->#algcenter(ss)==2);
+  do("primesubalg ss 0", ()->#algprimesubalg(ss)==-1);
+  do("charpol annihil(a) 0", ()->testcharpol(al,a));
+  do("charpol annihil(b) 0", ()->testcharpol(al,b));
+  do("charpol annihil(c) 0", ()->testcharpol(al,c));
+  do("charpol annihil(d) 0", ()->testcharpol(al,d));
+  do("charpol annihil(e) 0", ()->testcharpol(al,e));
+  do("random 0", ()->algrandom(al,1));
+  do("algsimpledec 0", ()->#algsimpledec(ss)==2);
+  do("alg_decomposition 0", ()->dec=algdecomposition(al); #dec[1]==1 && #dec[2]==2);
+  do("iscommutative 0", ()->algiscommutative(al)==0);
+  do("issemisimple 0", ()->algissemisimple(al)==0);
+  do("issimple 0", ()->algissimple(al)==0);
+  do("issimple ss 0", ()->algissimple(ss)==0);
+  do("isdivision 0", ()->algisdivision(al)==0);
+
+  p = 2;
+  al = algtableinit(mt,p);
+  do("algisassociative 2", ()->algisassociative(mt,p));
+  do("construction 2", ()->al);
+  do("iscyclic 2", ()->algtype(al)==1);
+  do("dim 2", ()->algabsdim(al)==3);
+  do("char 2", ()->algchar(al)==p);
+  do("a+b 2", ()->algadd(al,a,b)==[1,1,0]~);
+  do("a-b 2", ()->algsub(al,a,b)==algadd(al,a,b));
+  do("a*b 2", ()->algmul(al,a,b)==[0,p-1,0]~);
+  do("b*a 2", ()->algmul(al,b,a)==[0,0,0]~);
+  do("a^2 2", ()->algsqr(al,a)==a*Mod(1,p));
+  do("b^2 2", ()->algsqr(al,b)==b*Mod(1,p));
+  do("multable(a) 2", ()->algmultable(al,a)==[1,0,0;0,1,0;-1,0,0]*Mod(1,p));
+  do("multable(b) 2", ()->algmultable(al,b)==[0,0,0;-1,0,-1;1,0,1]*Mod(1,p));
+  do("divl(un,a) 2", ()->algdivl(al,un,a)==a*Mod(1,p));
+  do("divl(un,b) 2", ()->algdivl(al,un,b)==b*Mod(1,p));
+  do("un^-1 2", ()->alginv(al,un)==un);
+  do("divr(a,un) 2", ()->algdivr(al,a,un)==a*Mod(1,p));
+  do("divr(b,un) 2", ()->algdivr(al,b,un)==b*Mod(1,p));
+  do("rad(al) 2", ()->#algradical(al)==1); \\matrices [0,*;0,0]
+  do("ss(al) 2", ()->#algradical(algquotient(al,algradical(al)))==0);
+  [ss,projm,liftm] = algquotient(al,algradical(al),1);
+  pa = projm*a;
+  do("proj(a) idem 2", ()->algsqr(ss,pa)==pa*Mod(1,p));
+  do("idemproj 2", ()->algcentralproj(ss,[pa,algsub(ss,projm*un,pa)]));
+  sc = algcentralproj(ss,[pa,algsub(ss,projm*un,pa)]);
+  do("simple components 2", ()->algmultable(sc[1])==[Mat(Mod(1,p))] && algmultable(sc[2])==[Mat(Mod(1,p))]);
+  do("center al 2", ()->#algcenter(al)==1);
+  do("center ss 2", ()->#algcenter(ss)==2);
+  do("primesubalg ss 2", ()->#algprimesubalg(ss)==2);
+  do("charpol annihil(a) 2", ()->testcharpol(al,a));
+  do("charpol annihil(b) 2", ()->testcharpol(al,b));
+  do("charpol annihil(c) 2", ()->testcharpol(al,c));
+  do("random 2", ()->algrandom(al,1));
+  do("algsimpledec 2", ()->#algsimpledec(ss)==2);
+  do("alg_decomposition 2", ()->dec=algdecomposition(al); #dec[1]==1 && #dec[2]==2);
+  do("iscommutative 2", ()->algiscommutative(al)==0);
+  do("issemisimple 2", ()->algissemisimple(al)==0);
+  do("issimple 2", ()->algissimple(al)==0);
+  do("issimple ss 2", ()->algissimple(ss)==0);
+  do("matrix trace 2", ()->algtrace(al,[un,vector(3)~;vector(3)~,un])==0);
+  do("matrix norm 2", ()->algnorm(al,[un,vector(3)~;vector(3)~,un])==1);
+  do("norm 2", ()->algnorm(al,un)==1);
+
+  p = 3;
+  mt = [[1,0;0,1],[0,0;1,0]];\\F3[x]/(x^2)
+  un = [1,0]~;
+  a = [1,-1]~;
+  b = [0,1]~;
+  al = algtableinit(mt,p);
+  do("construction 3", ()->al);
+  do("iscyclic 3", ()->algtype(al)==1);
+  do("dim 3", ()->algabsdim(al)==2);
+  do("char 3", ()->algchar(al)==p);
+  do("a+b 3", ()->algadd(al,a,b)==un);
+  do("a-b 3", ()->algsub(al,a,b)==[1,1]~);
+  do("a*b 3", ()->algmul(al,a,b)==[0,1]~);
+  do("b*a 3", ()->algmul(al,b,a)==[0,1]~);
+  do("a^2 3", ()->algsqr(al,a)==[1,1]~);
+  do("b^2 3", ()->algsqr(al,b)==[0,0]~);
+  do("a^691691 3", ()->algpow(al,a,691691)==[1,-691691]~*Mod(1,p));
+  do("multable(a) 3", ()->algmultable(al,a)==[1,0;-1,1]*Mod(1,p));
+  do("multable(b) 3", ()->algmultable(al,b)==[0,0;1,0]);
+  do("algdivl(a,b) 3", ()->algdivl(al,a,b)==b);
+  do("a^-1 3", ()->alginv(al,a)==[1,1]~);
+  do("algdivr(b,a) 3", ()->algdivr(al,b,a)==b);
+  do("rad(al) 3", ()->#algradical(al)==1); \\ideal (x)
+  do("ss(al) 3", ()->#algradical(algquotient(al,algradical(al)))==0);
+  [ss,projm,liftm] = algquotient(al,algradical(al),1);
+  do("center al 3", ()->#algcenter(al)==2);
+  do("center ss 3", ()->#algcenter(ss)==1);
+  do("primesubalg ss 3", ()->#algprimesubalg(ss)==1);
+  do("charpol annihil(a) 3", ()->testcharpol(al,a));
+  do("charpol annihil(b) 3", ()->testcharpol(al,b));
+  do("random 3", ()->algrandom(al,1));
+  do("algsimpledec 3", ()->#algsimpledec(ss)==1);
+  do("alg_decomposition 3", ()->dec=algdecomposition(al); #dec[1]==1 && #dec[2]==1);
+  do("iscommutative 3", ()->algiscommutative(al)==1);
+  do("issemisimple 3", ()->algissemisimple(al)==0);
+  do("issemisimple ss 3", ()->algissemisimple(ss)==1);
+  do("issimple 3", ()->algissimple(al)==0);
+  do("issimple ss 3", ()->algissimple(ss)==1);
+
+  p = 3;
+  mt = [[1,0,0;0,1,0;0,0,1],[0,0,0;1,0,0;0,1,0],[0,0,0;0,0,0;1,0,0]];\\F3[x]/(x^3)
+  un = [1,0,0]~;
+  a = [1,-1,0]~;
+  b = [0,1,0]~;
+  al = algtableinit(mt,p);
+  do("construction 3c", ()->al);
+  do("iscyclic 3c", ()->algtype(al)==1);
+  do("dim 3c", ()->algabsdim(al)==3);
+  do("char 3c", ()->algchar(al)==p);
+  do("a+b 3c", ()->algadd(al,a,b)==un);
+  do("a-b 3c", ()->algsub(al,a,b)==[1,1,0]~);
+  do("a*b 3c", ()->algmul(al,a,b)==[0,1,p-1]~);
+  do("b*a 3c", ()->algmul(al,b,a)==[0,1,p-1]~);
+  do("a^2 3c", ()->algsqr(al,a)==[1,1,1]~);
+  do("b^2 3c", ()->algsqr(al,b)==[0,0,1]~);
+  do("a^691691 3c", ()->algpow(al,a,691691)==[1,-691691,(691691*691690)\2]~*Mod(1,p));
+  do("multable(a) 3c", ()->algmultable(al,a)==[1,0,0;-1,1,0;0,-1,1]*Mod(1,p));
+  do("multable(b) 3c", ()->algmultable(al,b)==[0,0,0;1,0,0;0,1,0]);
+  do("algdivl(a,b) 3c", ()->algdivl(al,a,b)==[0,1,1]~);
+  do("a^-1 3c", ()->alginv(al,a)==[1,1,1]~);
+  do("algdivr(b,a) 3c", ()->algdivr(al,b,a)==[0,1,1]~);
+  do("rad(al) 3c", ()->#algradical(al)==2); \\ideal (x), basis (x,x^2)
+  do("ss(al) 3c", ()->#algradical(algquotient(al,algradical(al)))==0);
+  [ss,projm,liftm] = algquotient(al,algradical(al),1);
+  do("center al 3c", ()->#algcenter(al)==3);
+  do("center ss 3c", ()->#algcenter(ss)==1);
+  do("primesubalg ss 3c", ()->#algprimesubalg(ss)==1);
+  do("charpol annihil(a) 3c", ()->testcharpol(al,a));
+  do("charpol annihil(b) 3c", ()->testcharpol(al,b));
+  do("random 3c", ()->algrandom(al,1));
+  do("algsimpledec 3c", ()->#algsimpledec(ss)==1);
+  do("alg_decomposition 3c", ()->dec=algdecomposition(al); #dec[1]==2 && #dec[2]==1);
+  do("iscommutative 3c", ()->algiscommutative(al)==1);
+  do("issemisimple 3c", ()->algissemisimple(al)==0);
+  do("issemisimple ss 3c", ()->algissemisimple(ss)==1);
+  do("issimple 3c", ()->algissimple(al)==0);
+  do("issimple ss 3c", ()->algissimple(ss)==1);
+
+  p = 2;
+  mt = [[1,0;0,1],[0,1;1,1]]; \\F2[x]/(x^2+x+1)
+  un = [1,0]~;
+  a = [0,1]~;
+  b = [1,1]~;
+  al = algtableinit(mt,p);
+  do("construction 2b", ()->al);
+  do("iscyclic 2b", ()->algtype(al)==1);
+  do("dim 2b", ()->algabsdim(al)==2);
+  do("char 2b", ()->algchar(al)==p);
+  do("a+b 2b", ()->algadd(al,a,b)==un);
+  do("a-b 2b", ()->algsub(al,a,b)==un);
+  do("a*b 2b", ()->algmul(al,a,b)==un);
+  do("b*a 2b", ()->algmul(al,b,a)==un);
+  do("a^2 2b", ()->algsqr(al,a)==b);
+  do("b^2 2b", ()->algsqr(al,b)==a);
+  do("a^691691 2b", ()->algpow(al,a,691691)==b);
+  do("multable(a) 2b", ()->algmultable(al,a)==[0,1;1,1]);
+  do("multable(b) 2b", ()->algmultable(al,b)==[1,1;1,0]);
+  do("divl(a,b) 2b", ()->algdivl(al,a,b)==a);
+  do("a^-1 2b", ()->alginv(al,a)==b);
+  do("divr(b,a) 2b", ()->algdivr(al,b,a)==a);
+  do("rad(al) 2b", ()->#algradical(al)==0); \\separable extension of F2
+  do("center al 2b", ()->#algcenter(al)==2);
+  do("primesubalg al 2b", ()->#algprimesubalg(al)==1);
+  do("charpol annihil(a) 2b", ()->testcharpol(al,a));
+  do("charpol annihil(b) 2b", ()->testcharpol(al,b));
+  do("random 2b", ()->algrandom(al,1));
+  do("algsimpledec 2b", ()->#algsimpledec(al)==1);
+  do("alg_decomposition 2b", ()->dec=algdecomposition(al); dec[1]==0 && #dec[2]==1 && algabsdim(dec[2][1])==2);
+  do("iscommutative 2b", ()->algiscommutative(al)==1);
+  do("issemisimple 2b", ()->algissemisimple(al)==1);
+  do("issimple 2b", ()->algissimple(al)==1);
+  do("issimple,1 2b", ()->algissimple(al,1)==1);
+
+
+  p = 3;
+  mt = [matid(4),
+
+         [0,1,0,0;
+          1,0,0,0;
+          0,0,1,0;
+          0,0,0,-1],
+
+         [0,0,0,1/2;
+          0,0,0,1/2;
+          1,-1,0,0;
+          0,0,0,0],
+
+         [0,0,1/2,0;
+          0,0,-1/2,0;
+          0,0,0,0;
+          1,1,0,0]]*Mod(1,p); \\M_2(F3)
+  un = [1,0,0,0]~;
+  a = [0,1,-1,0]~;
+  b = [1,1,0,1]~;
+  al = algtableinit(mt,p);
+  do("construction 3b", ()->al);
+  do("iscyclic 3b", ()->algtype(al)==1);
+  do("dim 3b", ()->algabsdim(al)==4);
+  do("char 3b", ()->algchar(al)==p);
+  do("a+b 3b", ()->algadd(al,a,b)==[1,-1,2,1]~*Mod(1,p));
+  do("a-b 3b", ()->algsub(al,a,b)==[2,0,2,2]~);
+  do("a*b 3b", ()->algmul(al,a,b)==[2,2,0,2]~);
+  do("b*a 3b", ()->algmul(al,b,a)==[2,0,1,1]~);
+  do("a^2 3b", ()->algsqr(al,a)==un);
+  do("b^2 3b", ()->algsqr(al,b)==-b*Mod(1,p));
+  do("a^691691 3b", ()->algpow(al,a,691691)==a*Mod(1,p));
+  do("b^691691 3b", ()->algpow(al,b,691691)==b);
+  do("multable(a) 3b", ()->algmultable(al,a)==[0,1,0,1;1,0,0,1;2,1,1,0;0,0,0,2]);
+  do("multable(b) 3b", ()->algmultable(al,b)==[1,1,2,0;1,1,1,0;0,0,2,0;1,1,0,0]);
+  do("divl(a,b) 3b", ()->algdivl(al,a,b)==[2,2,0,2]~);
+  do("a^-1 3b", ()->alginv(al,a)==[0,1,2,0]~);
+  do("divr(b,a) 3b", ()->algdivr(al,b,a)==[2,0,1,1]~);
+  c = [0,0,1,0]~;
+  do("rad(al) 3b", ()->#algradical(al)==0); \\matrix ring is semisimple
+  do("center al 3b", ()->#algcenter(al)==1);
+  do("primesubalg al 3b", ()->#algprimesubalg(al)==1);
+  do("charpol annihil(a) 3b", ()->testcharpol(al,a));
+  do("charpol annihil(b) 3b", ()->testcharpol(al,b));
+  do("charpol annihil(c) 3b", ()->testcharpol(al,c));
+  do("random 3b", ()->algrandom(al,1));
+  do("algsimpledec 3b", ()->#algsimpledec(al)==1);
+  do("alg_decomposition 3b", ()->dec=algdecomposition(al); dec[1]==0 && #dec[2]==1 && #algcenter(dec[2][1])==1);
+  do("iscommutative 3b", ()->algiscommutative(al)==0);
+  do("issemisimple 3b", ()->algissemisimple(al)==1);
+  do("issimple 3b", ()->algissimple(al)==1);
+
+  p = 2;
+  mt = [matid(4),
+
+     [0,0,1,0;
+      1,0,0,1;
+      0,0,0,0;
+      0,0,-1,0],
+
+     [0,0,0,0;
+      0,0,0,0;
+      1,0,0,0;
+      0,1,0,0],
+
+     [0,0,0,0;
+      0,0,0,0;
+      0,0,1,0;
+      1,0,0,1]]*Mod(1,p); \\M_2(F2)
+  un = [1,0,0,0]~;
+  a = [0,1,0,0]~;
+  b = [1,0,0,1]~;
+  al = algtableinit(mt,p);
+  do("construction 2c", ()->al);
+  do("iscyclic 2c", ()->algtype(al)==1);
+  do("dim 2c", ()->algabsdim(al)==4);
+  do("char 2c", ()->algchar(al)==p);
+  do("a+b 2c", ()->algadd(al,a,b)==[1,1,0,1]~);
+  do("a-b 2c", ()->algsub(al,a,b)==[1,1,0,1]~);
+  do("a*b 2c", ()->algmul(al,a,b)==[0,0,0,0]~);
+  do("b*a 2c", ()->algmul(al,b,a)==a);
+  do("a^2 2c", ()->algsqr(al,a)==[0,0,0,0]~);
+  do("b^2 2c", ()->algsqr(al,b)==b);
+  c = [1,1,1,1]~;
+  do("a^691691 2c", ()->algpow(al,a,691691)==[0,0,0,0]~);
+  do("b^691691 2c", ()->algpow(al,b,691691)==b);
+  do("c^691691 2c", ()->algpow(al,c,691691)==[0,1,1,1]~);
+  do("multable(a) 2c", ()->algmultable(al,a)==[0,0,1,0;1,0,0,1;0,0,0,0;0,0,1,0]);
+  do("multable(b) 2c", ()->algmultable(al,b)==[1,0,0,0;0,1,0,0;0,0,0,0;1,0,0,0]);
+  do("divl(c,a) 2c", ()->algdivl(al,c,a)==[0,0,0,1]~);
+  do("divl(c,b) 2c", ()->algdivl(al,c,b)==[0,0,1,0]~);
+  do("c^-1 2c", ()->alginv(al,c)==[0,1,1,1]~);
+  do("divr(a,c) 2c", ()->algdivr(al,a,c)==[1,1,0,1]~);
+  do("divr(b,c) 2c", ()->algdivr(al,b,c)==[0,1,0,0]~);
+  do("rad(al) 2c", ()->#algradical(al)==0); \\matrix ring is semisimple
+  do("center al 2c", ()->#algcenter(al)==1);
+  do("primesubalg al 2c", ()->#algprimesubalg(al)==1);
+  do("charpol annihil(a) 2c", ()->testcharpol(al,a));
+  do("charpol annihil(b) 2c", ()->testcharpol(al,b));
+  do("charpol annihil(c) 2c", ()->testcharpol(al,c));
+  do("random 2c", ()->algrandom(al,1));
+  do("algsimpledec 2c", ()->#algsimpledec(al)==1);
+  do("alg_decomposition 2c", ()->dec=algdecomposition(al); dec[1]==0 && #dec[2]==1 && #algcenter(dec[2][1])==1);
+  do("iscommutative 2c", ()->algiscommutative(al)==0);
+  do("issemisimple 2c", ()->algissemisimple(al)==1);
+  do("issimple 2c", ()->algissimple(al)==1);
+
+  p = 5;
+  mt = [Mat(Mod(1,p))];
+  un = [1]~;
+  a = [2]~;
+  b = [3]~;
+  al = algtableinit(mt,p);
+  do("construction 5", ()->al);
+  do("iscyclic 5", ()->algtype(al)==1);
+  do("dim 5", ()->algabsdim(al)==1);
+  do("char 5", ()->algchar(al)==p);
+  do("a+b 5", ()->algadd(al,a,b)==[Mod(0,p)]~);
+  do("a-b 5", ()->algsub(al,a,b)==[Mod(4,p)]~);
+  do("a*b 5", ()->algmul(al,a,b)==[Mod(1,p)]~);
+  do("b*a 5", ()->algmul(al,b,a)==[Mod(1,p)]~);
+  do("a^2 5", ()->algsqr(al,a)==[Mod(4,p)]~);
+  do("b^2 5", ()->algsqr(al,b)==[Mod(-1,p)]~);
+  do("a^691691 5", ()->algpow(al,a,691691)==b);
+  do("multable(a) 5", ()->algmultable(al,a)==Mat(Mod(2,p)));
+  do("multable(b) 5", ()->algmultable(al,b)==Mat(Mod(3,p)));
+  do("divl(a,b) 5", ()->algdivl(al,a,b)==[Mod(4,p)]~);
+  do("a^-1 5", ()->alginv(al,a)==[Mod(3,p)]~);
+  do("divr(a,b) 5", ()->algdivr(al,a,b)==[Mod(4,p)]~);
+  do("rad(al) 5", ()->#algradical(al)==0); \\F5, dim 1
+  do("center al 5", ()->#algcenter(al)==1);
+  do("primesubalg al 5", ()->#algprimesubalg(al)==1);
+  do("charpol annihil(a) 5", ()->testcharpol(al,a));
+  do("charpol annihil(b) 5", ()->testcharpol(al,b));
+  do("random 5", ()->algrandom(al,1));
+  do("algsimpledec 5", ()->#algsimpledec(al)==1);
+  do("alg_decomposition 5", ()->dec=algdecomposition(al); dec[1]==0 && #dec[2]==1 && algabsdim(dec[2][1])==1);
+  do("iscommutative 5", ()->algiscommutative(al)==1);
+  do("issemisimple 5", ()->algissemisimple(al)==1);
+  do("issimple 5", ()->algissimple(al)==1);
+
+  p = 0; \\M_2(Q)+Q
+  mt = [matid(5),
+
+     [0,0,1,0,0;
+      1,0,0,1,0;
+      0,0,0,0,0;
+      0,0,-1,0,0;
+      0,1,-1,-1,1],
+
+     [0,0,0,0,0;
+      0,0,0,0,0;
+      1,0,0,0,0;
+      0,1,0,0,0;
+      0,0,0,0,0],
+
+     [0,0,0,0,0;
+      0,0,0,0,0;
+      0,0,1,0,0;
+      1,0,0,1,0;
+      0,0,0,0,0],
+
+     [0,0,0,0,0;
+      0,0,0,0,0;
+      0,0,0,0,0;
+      0,0,0,0,0;
+      1,1,0,0,1]
+  ];
+  un = [1,0,0,0,0]~;
+  a = [1,0,0,0,-1]~;
+  b = [1,1,0,0,0]~;
+  al = algtableinit(mt,p);
+  do("construction 0b", ()->al);
+  do("iscyclic 0b", ()->algtype(al)==1);
+  do("dim 0b", ()->algabsdim(al)==5);
+  do("char 0b", ()->algchar(al)==p);
+  do("a+b 0b", ()->algadd(al,a,b)==[2,1,0,0,-1]~);
+  do("a-b 0b", ()->algsub(al,a,b)==[0,-1,0,0,-1]~);
+  do("a*b 0b", ()->algmul(al,a,b)==[1,1,0,0,-2]~);
+  do("b*a 0b", ()->algmul(al,b,a)==algmul(al,a,b));\\a central
+  do("a^2 0b", ()->algsqr(al,a)==a);
+  do("b^2 0b", ()->algsqr(al,b)==[1,2,0,0,1]~);
+  do("a^691691 0b", ()->algpow(al,a,691691)==a);
+  do("b^691 0b", ()->algpow(al,b,691)==[1,691,0,0,2^691-1-691]~);
+  do("multable(a) 0b", ()->algmultable(al,a)==
+      [1,0,0,0,0;
+       0,1,0,0,0;
+       0,0,1,0,0;
+       0,0,0,1,0;
+       -1,-1,0,0,0]);
+  do("multable(b) 0b", ()->algmultable(al,b)==
+      [1,0,1,0,0;
+       1,1,0,1,0;
+       0,0,1,0,0;
+       0,0,-1,1,0;
+       0,1,-1,-1,2]);
+  do("divl(b,a) 0b", ()->algdivl(al,b,a)==[1,-1,0,0,0]~);
+  do("b^-1 0b", ()->alginv(al,b)==[1,-1,0,0,1/2]~);
+  do("divr(a,b) 0b", ()->algdivr(al,a,b)==algdivl(al,b,a));
+  do("rad(al) 0b", ()->#algradical(al)==0);
+  do("idemproj 0b", ()->algcentralproj(al,[a,algsub(al,un,a)]));
+  sc = algcentralproj(al,[a,algsub(al,un,a)]);
+  do("simple components 0b", ()->algabsdim(sc[1])==4 && algabsdim(sc[2])==1);
+  do("mt M2 component 0b", ()->algmultable(sc[1])[1]==matid(4));
+  do("center al 0b", ()->#algcenter(al)==2);
+  do("primesubalg al 0b", ()->#algprimesubalg(al)==-1);
+  do("charpol annihil(a) 0b", ()->testcharpol(al,a));
+  do("charpol annihil(b) 0b", ()->testcharpol(al,b));
+  do("random 0b", ()->algrandom(al,1));
+  do("algsimpledec 0b", ()->#algsimpledec(al)==2);
+  do("alg_decomposition 0b", ()->dec=algdecomposition(al); dec[1]==0 && #dec[2]==2 && #algcenter(dec[2][1])==1 && #algcenter(dec[2][2])==1 && (algabsdim(dec[2][1])==4 || algabsdim(dec[2][2])==4));
+  do("subalg M2(Q)", ()->sal=algsubalg(al,[1,0,0,0; 0,1,0,0; 0,0,1,0; 0,0,0,1; 0,0,0,0]); algisassociative(sal) && algradical(sal)==0 && #algsimpledec(sal)==1);
+  do("iscommutative 0b", ()->algiscommutative(al)==0);
+  do("issemisimple 0b", ()->algissemisimple(al)==1);
+  do("issimple 0b", ()->algissimple(al)==0);
+
+  p = 3;
+  al = algtableinit(mt,p);
+  do("construction 3d", ()->al);
+  do("iscyclic 3d", ()->algtype(al)==1);
+  do("dim 3d", ()->algabsdim(al)==5);
+  do("char 3d", ()->algchar(al)==p);
+  do("a+b 3d", ()->algadd(al,a,b)==[2,1,0,0,-1]~*Mod(1,p));
+  do("a-b 3d", ()->algsub(al,a,b)==[0,-1,0,0,-1]~*Mod(1,p));
+  do("a*b 3d", ()->algmul(al,a,b)==[1,1,0,0,-2]~*Mod(1,p));
+  do("b*a 3d", ()->algmul(al,b,a)==algmul(al,a,b));\\a central
+  do("a^2 3d", ()->algsqr(al,a)==a*Mod(1,p));
+  do("b^2 3d", ()->algsqr(al,b)==[1,2,0,0,1]~);
+  do("a^691691 3d", ()->algpow(al,a,691691)==a*Mod(1,p));
+  do("b^691 3d", ()->algpow(al,b,691)==[1,691,0,0,2^691-1-691]~*Mod(1,p));
+  do("multable(a) 3d", ()->algmultable(al,a)==
+      [1,0,0,0,0;
+       0,1,0,0,0;
+       0,0,1,0,0;
+       0,0,0,1,0;
+       -1,-1,0,0,0]*Mod(1,p));
+  do("multable(b) 3d", ()->algmultable(al,b)==
+      [1,0,1,0,0;
+       1,1,0,1,0;
+       0,0,1,0,0;
+       0,0,-1,1,0;
+       0,1,-1,-1,2]*Mod(1,p));
+  do("divl(b,a) 3d", ()->algdivl(al,b,a)==[1,-1,0,0,0]~*Mod(1,p));
+  do("b^-1 3d", ()->alginv(al,b)==[1,-1,0,0,1/2]~*Mod(1,p));
+  do("divr(a,b) 3d", ()->algdivr(al,a,b)==algdivl(al,b,a));
+  do("rad(al) 3d", ()->#algradical(al)==0);
+  do("idemproj 3d", ()->algcentralproj(al,[a,algsub(al,un,a)]));
+  sc = algcentralproj(al,[a,algsub(al,un,a)]);
+  do("simple components 3d", ()->algabsdim(sc[1])==4 && algabsdim(sc[2])==1);
+  do("mt M2 component 3d", ()->algmultable(sc[1])[1]==matid(4));
+  do("center al 3d", ()->#algcenter(al)==2);
+  do("primesubalg al 3d", ()->#algprimesubalg(al)==2);
+  do("charpol annihil(a) 3d", ()->testcharpol(al,a));
+  do("charpol annihil(b) 3d", ()->testcharpol(al,b));
+  do("random 3d", ()->algrandom(al,1));
+  do("algsimpledec 3d", ()->#algsimpledec(al)==2);
+  do("alg_decomposition 3d", ()->dec=algdecomposition(al); dec[1]==0 && #dec[2]==2 && #algcenter(dec[2][1])==1 && #algcenter(dec[2][2])==1 && (algabsdim(dec[2][1])==4 || algabsdim(dec[2][2])==4));
+  do("subalg M2(F3)", ()->sal=algsubalg(al,[1,0,0,0; 0,1,0,0; 0,0,1,0; 0,0,0,1; 0,0,0,0]); algisassociative(sal) && algradical(sal)==0 && #algsimpledec(sal)==1);
+  do("iscommutative 3d", ()->algiscommutative(al)==0);
+  do("issemisimple 3d", ()->algissemisimple(al)==1);
+  do("issimple 3d", ()->algissimple(al)==0);
+  do("issimple,1 3d", ()->algissimple(al,1)==0);
+});
+
+all() = gusuite("all", ()->{
+  get();
+  operations();
+  hasse0();
+  nfcompo();
+  tensor();
+  gw();
+  alfromhasse();
+  moreoperations();
+  tablealg();
+});
+
+all();
+
+nf = nfinit(y^2-2);
+al = alginit(nf, [-3,-5], x,1);
+print("maxorder assoc: ", algisassociative(al[9]));
+al0 = alginit(nf, [-3,-5], x,0);
+print("natorder assoc: ", algisassociative(al0[9]));
+un = [1,0]~;
+ii = [x,0]~;
+jj = [0,1]~;
+kk = algmul(al,ii,jj);
+print("spl(1): ", algsplittingmatrix(al,un)==matid(2));
+print("spl(i): ", algsplittingmatrix(al,ii)==[x,0;0,-x]);
+print("spl(j): ", algsplittingmatrix(al,jj)==[0,-5;1,0]);
+print("spl(k): ", algsplittingmatrix(al,kk)==[0,-5*x;-x,0]);
+print("spl(basis(1)): ", algsplittingmatrix(al,algalgtobasis(al,un))==matid(2));
+print("spl(basis(i)): ", algsplittingmatrix(al,algalgtobasis(al,ii))==[x,0;0,-x]);
+print("spl(basis(j)): ", algsplittingmatrix(al,algalgtobasis(al,jj))==[0,-5;1,0]);
+print("spl(basis(k)): ", algsplittingmatrix(al,algalgtobasis(al,kk))==[0,-5*x;-x,0]);
+a = y+1;
+b = 1/3;
+c = -y/5+1/2;
+print("spl(a*1): ", algsplittingmatrix(al,a*un)==a*matid(2));
+print("spl(a*i): ", algsplittingmatrix(al,a*ii)==a*[x,0;0,-x]);
+print("spl(a*j): ", algsplittingmatrix(al,a*jj)==a*[0,-5;1,0]);
+print("spl(a*k): ", algsplittingmatrix(al,a*kk)==a*[0,-5*x;-x,0]);
+print("spl(b*1): ", algsplittingmatrix(al,b*un)==b*matid(2));
+print("spl(b*i): ", algsplittingmatrix(al,b*ii)==b*[x,0;0,-x]);
+print("spl(b*j): ", algsplittingmatrix(al,b*jj)==b*[0,-5;1,0]);
+print("spl(b*k): ", algsplittingmatrix(al,b*kk)==b*[0,-5*x;-x,0]);
+
+
+ord = algbasis(al);
+invord = alginvbasis(al);
+x1 = algrandom(al,1);
+ax1 = algbasistoalg(al,x1);
+nx1 = algalgtobasis(al0,ax1);
+print("nattomax 1: ", nx1==ord*x1);
+x2 = algrandom(al,1);
+ax2 = algbasistoalg(al,x2);
+nx2 = algalgtobasis(al0,ax2);
+print("nattomax 2: ", nx2==ord*x2);
+print("ord*invord=id: ", ord*invord == matid(8));
+print("spl additive: ", algsplittingmatrix(al,x1) + algsplittingmatrix(al,x2) == algsplittingmatrix(al, algadd(al,x1,x2)));
+print("spl multiplicative: ", algsplittingmatrix(al,x1) * algsplittingmatrix(al,x2) == algsplittingmatrix(al, algmul(al,x1,x2)));
+print("changebasis bug 1: ", algalgtobasis(al,algbasistoalg(al,algmul(al,x1,x2)))==algmul(al,x1,x2));
+print("changebasis bug 2: ", algalgtobasis(al0,algmul(al0,ax1,ax2)) == algmul(al0,nx1,nx2));
+print("changebasis bug 3: ", invord*algmul(al0,nx1,nx2) == algmul(al,x1,x2));
+print("changebasis bug 4: ", algmultable(al,x1) == invord*algmultable(al0,nx1)*ord);
+
+print("algtableinit segfault bug: ");
+alt = algtableinit(al[9]);
+print(alt != 'alt);
+print("center of CSA: ", #algcenter(alt)==2);
+print("radical of CSA: ", algradical(alt)==0);
+print("decomposition of CSA: ", #algsimpledec(alt)==1);
+dec = algdecomposition(alt);
+print("alg_decomposition of CSA: ", #dec==2 && dec[1]==0 && #dec[2]==1 && #algcenter(dec[2][1])==2 && algabsdim(dec[2][1])==8);
+
+print("alsimple bug");
+mt = [matid(3), [0,0,0;1,1,0;0,0,0], [0,0,0;0,0,0;1,0,1]];
+A = algtableinit(mt);
+algissimple(A)
+
+print("tests for al_CSA: ");
+T = y^3-y+1;
+nf = nfinit(T);
+   m_i = [0,-1,0, 0;\
+          1, 0,0, 0;\
+          0, 0,0,-1;\
+          0, 0,1, 0];
+   m_j = [0, 0,-1,0;\
+          0, 0, 0,1;\
+          1, 0, 0,0;\
+          0,-1, 0,0];
+   m_k = [0, 0, 0, -1;\
+          0, 0,-1, 0;\
+          0, 1, 0, 0;\
+          1, 0, 0, 0];
+mt = [matid(4), m_i, m_j, m_k];
+print(algisassociative(mt));
+al = alginit(nf, mt, 'x);
+print(al != 0);
+print("should fail:");
+alfail = alginit(nf, [0,0], 'x);
+algb(al);
+algaut(al);
+print("algebra:");
+print("csa getcenter: ", algcenter(al) == nf);
+print("csa getsplitting: ", algsplittingfield(al) != 0);
+print("getrelmultable: ", algrelmultable(al) == mt);
+print("getsplittingdata:");
+print(#algsplittingdata(al) == 3);
+print(#algsplittingdata(al)[1] == 12);
+print(#algsplittingdata(al)[2] == 2);
+print(#algsplittingdata(al)[3][1,] == 12);
+print(#algsplittingdata(al)[3][,1] == 2);
+print(al[3][3]*al[3][2][,1] == [1,0]~);
+print(al[3][3]*al[3][2][,2] == [0,1]~);
+polabs = al[1][12][1].pol;
+for(i=1,10,\
+print(al[3][3]*algmul(al, al[3][2][,1], algpow(al,al[3][1],i)) == [Mod(x^i,polabs),0]~);\
+print(al[3][3]*algmul(al, al[3][2][,2], algpow(al,al[3][1],i)) == [0,Mod(x,polabs)^i]~)\
+);
+print("hasse invariants:");
+print(alghassei(al) == 0);
+print(alghassef(al) == 0);
+print(alghasse(al,1) == 0);
+print("csa splitting pol: ", poldegree(al[1][12][1].pol) == 6);
+print("csa basis: ", matsize(algbasis(al)) == [12,12]);
+print("csa invbasis: ", matsize(alginvbasis(al)) == [12,12]);
+print("csa absdim: ", #algmultable(al) == algabsdim(al));
+print("csa char: ", algchar(al) == 0);
+print("csa deg: ", algdegree(al) == 2);
+print("csa dim: ", algdim(al) == 4);
+print("csa absdim: ", algabsdim(al) == 12);
+print("csa type: ", algtype(al) == 2); \\2==al_CSA
+print("csa iscommutative: ", algiscommutative(al)==0);
+print("csa issemisimple: ", algissemisimple(al)==1);
+
+print("elements:");
+a = [0, Mod(y,T), 0, 0]~;
+b = [0, -1, Mod(2*y^2,T), 0]~;
+c = [Mod(1-y+2*y^2,T), 3, 0, Mod(-3*y,T)]~;
+mynorm(aa) = sum(i=1,4,aa[i]^2);
+algbasistoalg(al,a)
+algalgtobasis(al,[1,2,3,4,5,6,7,8,9,10,11,12]~)
+
+print("csa add: ", algadd(al,a,b) == a+b);
+print("csa neg: ", algneg(al,a) == -a);
+print("csa neg 2: ", algneg(al,b) == -b);
+print("csa sub: ", algsub(al,a,b) == a-b);
+print("csa mul: ", algmul(al,a,b) == [Mod(y,T), 0, 0, Mod(2*y-2,T)]~);
+print("csa mul 2: ", algmul(al,b,a) == [Mod(y,T), 0, 0, Mod(2-2*y,T)]~);
+print("csa sqr: ", algsqr(al,a) == [Mod(-y^2,T),0,0,0]~);
+print("csa sqr 2: ", algsqr(al,b) == [Mod(-1-4*y^4,T),0,0,0]~);
+print("csa mt: ", algmultable(al,b) == -m_i + Mod(2*y^2,T)*m_j);
+print("csa inv: ", alginv(al,a) == -1/y^2*a);
+print("csa inv 2: ", alginv(al,b) == -1/Mod(1+4*y^4,T)*b);
+print("csa divl: ", algdivl(al,1+a+b,b) == algmul(al, alginv(al, 1+a+b), b));
+print("csa pow: ", algpow(al, a, 5) == Mod(y^4,T)*a);
+aa = algalgtobasis(al, a);
+bb = algalgtobasis(al, b);
+cc = algalgtobasis(al, c);
+print("csa mul 3: ", algmul(al,aa,b) == algalgtobasis(al,algmul(al,a,b)));
+print("csa mul 4: ", algmul(al,a,bb) == algalgtobasis(al,algmul(al,a,b)));
+print("csa pow 2: ", algpow(al,aa,13) == algalgtobasis(al,algpow(al,a,13)));
+print("csa sub 2: ", algsub(al,aa,b) == algalgtobasis(al,algsub(al,a,b)));
+print("csa sub 3: ", algsub(al,bb,a) == algalgtobasis(al,algsub(al,b,a)));
+print("csa inv 3: ", alginv(al,aa) == algalgtobasis(al,alginv(al,a)));
+print("csa inv 4: ", alginv(al,bb) == algalgtobasis(al,alginv(al,b)));
+print("csa inv 5: ", alginv(al,algadd(al,a,bb)) == algalgtobasis(al,alginv(al,algadd(al,a,b))));
+print("csa trace: ", algtrace(al,cc) == 2*c[1]);
+print("csa trace 2: ", algtrace(al,c) == 2*c[1]);
+
+D = 12;
+flag = 1;
+for(i=1, D,\
+  for(j=i, D,\
+    ei = matid(D)[,i];\
+    ej = matid(D)[,j];\
+    flag = flag && (algsplittingmatrix(al,ei)*algsplittingmatrix(al,ej) == algsplittingmatrix(al, algmul(al, ei, ej)));\
+    flag = flag && (algsplittingmatrix(al,ei)+algsplittingmatrix(al,ej) == algsplittingmatrix(al, algadd(al, ei, ej)))\
+    ));
+print(flag);
+
+print("testcharpol");
+testcharpol(al,elt) = print(algcharpoly(al,elt)==x^2-algtrace(al,elt)*x+mynorm(elt));
+testcharpol(al,a);
+testcharpol(al,b);
+testcharpol(al,c);
+
+print("testcharpol2");
+testcharpol2(al,elt) = print(algcharpoly(al,elt)==x^2-algtrace(al,elt)*x+mynorm(algbasistoalg(al,elt)));
+testcharpol2(al,aa);
+testcharpol2(al,bb);
+testcharpol2(al,cc);
+
+print("testnorm");
+testnorm(al,elt) = print(algnorm(al,elt) == mynorm(elt));
+testnorm(al,a);
+testnorm(al,b);
+testnorm(al,c);
+
+print("testnorm2");
+testnorm2(al,elt) = print(algnorm(al,elt) == mynorm(algbasistoalg(al,elt)));
+testnorm2(al,aa);
+testnorm2(al,bb);
+testnorm2(al,cc);
+
+doubleindex(N,i,j) = (i-1)*N+j;
+matrixringmt(N) =
+{
+  my(mt = [Mat([Col(0,N^2) | i<-[1..N^2]]) | j<-[1..N^2]], B, Bi, mt2=Vec(0,N^2));
+  for(i=1,N,
+    for(j=1,N,
+      for(k=1,N,
+        mt[doubleindex(N,i,j)][doubleindex(N,i,k),doubleindex(N,j,k)] = 1
+      )
+    )
+  );
+  B = matid(N^2);
+  for(i=1, N, B[doubleindex(N,i,i),1]=1);
+  Bi = B^(-1);
+  mt2[1] = matid(N^2);
+  for(i=2,N^2, mt2[i] = Bi*mt[i]*B);
+  mt2;
+}
+
+print("examples from docu");
+setrand(1);
+algtype([])
+A = alginit(nfinit(y),[-1,1]);
+algadd(A,[1,0]~,[1,2]~)
+algisinv(A,[-1,1]~)
+algisinv(A,[1,2]~,&ix)
+ix
+algisdivl(A,[x+2,-x-2]~,[x,1]~)
+algisdivl(A,[x+2,-x-2]~,[-x,x]~)
+algisdivl(A,[x+2,-x-2]~,[-x,x]~,&z)
+z
+
+A = alginit(nfinit(y^2-5),[2,y]);
+algalgtobasis(A,[y,1]~)
+algbasistoalg(A,algalgtobasis(A,[y,1]~))
+
+algbasistoalg(A,[0,1,0,0,2,-3,0,0]~)
+algalgtobasis(A,algbasistoalg(A,[0,1,0,0,2,-3,0,0]~))
+
+mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+A = algtableinit(mt,2);
+e = [0,1,0]~;
+one = [1,0,0]~;
+e2 = algsub(A,one,e);
+algcentralproj(A,[e,e2])
+algprimesubalg(A)
+algquotient(A,[0;1;0])
+algsubalg(A,[1,0; 0,0; 0,1])
+algiscommutative(A)
+algissimple(A)
+
+mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
+A = algtableinit(mt);
+algiscommutative(A)
+algissemisimple(A)
+algissimple(A)
+algissimple(A,1)
+
+nf = nfinit(y^2-5);
+A = alginit(nf, [-3,1-y]);
+alghassef(A)
+algdegree(A)^algabsdim(A)*nf.disc^algdim(A)*idealnorm(nf,alghassef(A)[1][2])^algdegree(A)
+algdisc(A)
+
+nf = nfinit(y^3-y+1);
+A = alginit(nf, [-1,-1]);
+algabsdim(A)
+algcenter(A).pol
+algdegree(A)
+algdim(A)
+
+nf = nfinit(y);
+p = idealprimedec(nf,7)[1];
+p2 = idealprimedec(nf,11)[1];
+A = alginit(nf,[3,[[p,p2],[1/3,2/3]],[0]]);
+algaut(A)
+algb(A)
+
+mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+A = algtableinit(mt,13);
+algchar(A)
+algtype(A)
+
+nf = nfinit(y^2-5);
+A = alginit(nf, [-1,2*y-1]);
+alghassef(A)
+A = alginit(nf, [-1,y]);
+alghassei(A)
+alghasse(A, 1)
+alghasse(A, 2)
+alghasse(A, idealprimedec(nf,2)[1])
+alghasse(A, idealprimedec(nf,5)[1])
+algindex(1, 1)
+algindex(A, 1)
+algindex(A, 2)
+algindex(A, idealprimedec(nf,2)[1])
+algindex(A, idealprimedec(nf,5)[1])
+algindex(A)
+algisdivision(A, 1)
+algisdivision(A, 2)
+algisdivision(A, idealprimedec(nf,2)[1])
+algisdivision(A, idealprimedec(nf,5)[1])
+algisdivision(A)
+algissplit(A, 1)
+algissplit(A, 2)
+algissplit(A, idealprimedec(nf,2)[1])
+algissplit(A, idealprimedec(nf,5)[1])
+algissplit(A)
+algisramified(A, 1)
+algisramified(A, 2)
+algisramified(A, idealprimedec(nf,2)[1])
+algisramified(A, idealprimedec(nf,5)[1])
+algisramified(A)
+algramifiedplaces(A)
+
+nf = nfinit(y^2-5);
+pr = idealprimedec(nf,13)[1];
+pol = nfgrunwaldwang(nf, [pr], [2], [0,-1], 'x)
+
+
+
+A = alginit(nfinit(y), [-1,-1]);
+alginvbasis(A)
+algbasis(A)
+algmultable(A)
+alginv(A,[1,1,0,0]~)
+algmul(A,[1,1,0,0]~,[0,0,2,1]~)
+algmultable(A,[0,1,0,0]~)
+algneg(A,[1,1,0,0]~)
+algsplittingmatrix(A,[0,0,0,2]~)
+algpow(A,[1,1,0,0]~,7)
+algsub(A,[1,1,0,0]~,[1,0,1,0]~)
+algtrace(A,[5,0,0,1]~)
+algtype(A)
+
+nf = nfinit(y^3-5);
+a = y; b = y^2;
+{m_i = [0,a,0,0;
+       1,0,0,0;
+       0,0,0,a;
+       0,0,1,0];}
+{m_j = [0, 0,b, 0;
+       0, 0,0,-b;
+       1, 0,0, 0;
+       0,-1,0, 0];}
+{m_k = [0, 0,0,-a*b;
+       0, 0,b,   0;
+       0,-a,0,   0;
+       1, 0,0,   0];}
+mt = [matid(4), m_i, m_j, m_k];
+A = alginit(nf,mt,'x);
+algrelmultable(A)
+algsplittingfield(A).pol
+algsplittingdata(A)
+algtype(A)
+
+mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+A = algtableinit(mt,19);
+algnorm(A,[0,-2,3]~)
+A = algtableinit(mt);
+algnorm(A,[0,-2,3]~)
+
+m_i=[0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0];
+m_j=[0,0,-1,0;0,0,0,1;1,0,0,0;0,-1,0,0];
+m_k=[0,0,0,-1;0,0,-1,0;0,1,0,0;1,0,0,0];
+mt = [matid(4), m_i, m_j, m_k];
+A = algtableinit(mt);
+algissemisimple(A)
+algissimple(A)
+algissimple(A,1)
+
+nf = nfinit(y^2+1);
+PR = idealprimedec(nf,5); #PR
+hi = [];
+hf = [PR, [1/3,-1/3]];
+A = alginit(nf, [3,hf,hi]);
+algsplittingfield(A).pol
+
+
+
+print("matrices over algebras");
+scal8(a) = vector(8,i,if(i==1,a,0))~;
+setrand(1);
+nf = nfinit(y^2-5);
+al = alginit(nf, [-1,-7]);
+M1 = [algrandom(al,2),algrandom(al,2);algrandom(al,2),algrandom(al,2)]
+M2 = [algrandom(al,2),algrandom(al,2);algrandom(al,2),algrandom(al,2)]
+print("mul alM: ", algmul(al,M1,M2));
+a = [1,2,3,4,5,6,7,8]~; M = Mat([0,0]); M[1,1] = a; M[1,2] = a;
+algmul(al, M, [a,a,a;a,a,a]);
+print("sqr alM: ", algsqr(al,M1) == algmul(al,M1,M1));
+print("divl alM: ", algmul(al,M1,algdivl(al,M1,M2)) == M2);
+print("divr alM: ", algmul(al,algdivr(al,M1,M2),M2) == M1);
+print("isinv alM: ", algisinv(al, M1));
+print("isinv alM 2: ", algisinv(al, M2));
+un = [1,0,0,0,0,0,0,0]~; zero = [0,0,0,0,0,0,0,0]~; id = [un,zero;zero,un];
+{print("inv alM: ", algmul(al,M1,alginv(al,M1)) == id &&
+ algmul(al,alginv(al,M1),M1) == id);}
+{print("inv alM 2: ", algmul(al,M2,alginv(al,M2)) == id &&
+ algmul(al,alginv(al,M2),M2) == id);}
+print("neg alM: ", algneg(al,M1) == -M1);
+print("sub alM: ", algsub(al,M1,M2) == M1-M2);
+print("add alM: ", algadd(al,M1,M2) == M1+M2);
+print("algtobasis basistoalg alM 1: ", algalgtobasis(al, algbasistoalg(al, M1)) ==
+ M1);
+print("algtobasis basistoalg alM 2: ", algalgtobasis(al, algbasistoalg(al, M2)) ==
+ M2);
+print("algmultable add alM: ", algmultable(al, M1)+algmultable(al,M2) ==
+ algmultable(al, algadd(al, M1, M2)));
+print("algmultable mul alM: ", algmultable(al, M1)*algmultable(al,M2) ==
+ algmultable(al, algmul(al, M1, M2)));
+{print("algmultable sqr alM: ", algmultable(al, M1)^2 == algmultable(al,
+ algsqr(al, M1)));}
+print("algsplitm add alM: ", algsplittingmatrix(al, M1)+algsplittingmatrix(al,M2) ==
+ algsplittingmatrix(al, algadd(al, M1, M2)));
+print("algsplitm mul alM: ", algsplittingmatrix(al, M1)*algsplittingmatrix(al,M2) ==
+ algsplittingmatrix(al, algmul(al, M1, M2)));
+print("algsplitm sqr alM: ", algsplittingmatrix(al, M1)^2 ==
+ algsplittingmatrix(al, algsqr(al, M1)));
+print("algsplitm sqr alM 2: ", algsplittingmatrix(al, M2)^2 ==
+ algsplittingmatrix(al, algsqr(al, M2)));
+{print("algtrace alM: ", algtrace(al,M1) == algtrace(al,M1[1,1]) +
+ algtrace(al,M1[2,2]));}
+{print("algtrace alM 2: ", algtrace(al,M2) == algtrace(al,M2[1,1]) +
+ algtrace(al,M2[2,2]));}
+{print("algtrace prod alM: ", algtrace(al, algmul(al,M1,M2)) == algtrace(al,
+algmul(al,M2,M1)));}
+{print("algnorm alM: ", algnorm(al,algmul(al,M1,M2)) == algnorm(al,M1) *
+ algnorm(al,M2));}
+{print("algnorm alM 2: ", algnorm(al,algmul(al,M2,M1)) == algnorm(al,M1) *
+ algnorm(al,M2));}
+{print("algcharpoly alM: ", poldegree(algcharpoly(al,M1))==4 &&
+ polcoeff(algcharpoly(al,M1),3) == -algtrace(al,M1) &&
+ polcoeff(algcharpoly(al,M1),0) == algnorm(al,M1));}
+{print("algcharpoly alM 2: ", poldegree(algcharpoly(al,M2))==4 &&
+ polcoeff(algcharpoly(al,M2),3) == -algtrace(al,M2) &&
+ polcoeff(algcharpoly(al,M2),0) == algnorm(al,M2));}
+m = 15; n = -8;
+{print("pow alM: ", algmul(al, algpow(al,M1,m), algpow(al,M1,n)) ==
+ algpow(al,M1,m+n));}
+{print("pow alM 2: ", algmul(al, algpow(al,M2,m), algpow(al,M2,n)) ==
+ algpow(al,M2,m+n));}
+print("pow 0 alM: ", algpow(al,M1,0) == id);
+algbasistoalg(al,M1)
+algbasistoalg(al,M2)
+m1 = [1,2;3,4];
+m2 = [5,6;7,8];
+M1 = apply(scal8,m1);
+M2 = apply(scal8,m2);
+print("mul scalar alM: ", algmul(al,M1,M2) == apply(scal8,m1*m2));
+
+m_i=[0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0];
+m_j=[0,0,-1,0;0,0,0,1;1,0,0,0;0,-1,0,0];
+m_k=[0,0,0,-1;0,0,-1,0;0,1,0,0;1,0,0,0];
+mt = [matid(4), m_i, m_j, m_k];
+al = algtableinit(mt);
+M1 = [algrandom(al,2),algrandom(al,2);algrandom(al,2),algrandom(al,2)]
+M2 = [algrandom(al,2),algrandom(al,2);algrandom(al,2),algrandom(al,2)]
+print("mul alM t: ", algmul(al,M1,M2));
+print("sqr alM t: ", algsqr(al,M1) == algmul(al,M1,M1));
+print("divl alM t: ", algmul(al,M1,algdivl(al,M1,M2)) == M2);
+print("divr alM t: ", algmul(al,algdivr(al,M1,M2),M2) == M1);
+print("isinv alM t: ", algisinv(al, M1));
+print("isinv alM t 2: ", algisinv(al, M2));
+un = [1,0,0,0]~; zero = [0,0,0,0]~; id = [un,zero;zero,un];
+{print("inv alM t: ", algmul(al,M1,alginv(al,M1)) == id &&
+ algmul(al,alginv(al,M1),M1) == id);}
+{print("inv alM t 2: ", algmul(al,M2,alginv(al,M2)) == id &&
+ algmul(al,alginv(al,M2),M2) == id);}
+print("neg alM t: ", algneg(al,M1) == -M1);
+print("sub alM t: ", algsub(al,M1,M2) == M1-M2);
+print("add alM t: ", algadd(al,M1,M2) == M1+M2);
+print("algmultable add alM t: ", algmultable(al,M1) + algmultable(al,M2) ==
+ algmultable(al, algadd(al,M1,M2)));
+print("algmultable mul alM t: ", algmultable(al,M1) * algmultable(al,M2) ==
+ algmultable(al, algmul(al,M1,M2)));
+{print("algmultable sqr alM t: ", algmultable(al, M1)^2 == algmultable(al,
+ algsqr(al, M1)));}
+{print("algtrace alM t: ", algtrace(al,M1) == 2*(algtrace(al,M1[1,1]) +
+ algtrace(al,M1[2,2])));}
+{print("algtrace alM t 2: ", algtrace(al,M2) == 2*(algtrace(al,M2[1,1]) +
+ algtrace(al,M2[2,2])));}
+{print("algtrace prod alM t: ", algtrace(al, algmul(al,M1,M2)) == algtrace(al,
+algmul(al,M2,M1)));}
+{print("algnorm alM t: ", algnorm(al,algmul(al,M1,M2)) == algnorm(al,M1) *
+ algnorm(al,M2));}
+{print("algnorm alM t 2: ", algnorm(al,algmul(al,M2,M1)) == algnorm(al,M1) *
+ algnorm(al,M2));}
+{print("algcharpoly alM t: ", poldegree(algcharpoly(al,M1))==16 &&
+ polcoeff(algcharpoly(al,M1),15) == -algtrace(al,M1) &&
+ polcoeff(algcharpoly(al,M1),0) == algnorm(al,M1));}
+{print("algcharpoly alM t 2: ", poldegree(algcharpoly(al,M2))==16 &&
+ polcoeff(algcharpoly(al,M2),15) == -algtrace(al,M2) &&
+ polcoeff(algcharpoly(al,M2),0) == algnorm(al,M2));}
+m = 32; n = -63;
+{print("pow alM t: ", algmul(al, algpow(al,M1,m), algpow(al,M1,n)) ==
+ algpow(al,M1,m+n));}
+{print("pow alM 2 t: ", algmul(al, algpow(al,M2,m), algpow(al,M2,n)) ==
+ algpow(al,M2,m+n));}
+print("pow 0 alM t: ", algpow(al,M2,0) == id);
+
+
+
+T = y^3-y+1;
+nf = nfinit(T);
+print("csa al2");
+setrand(1);
+al2 = alginit(nf, matrixringmt(2), 'x);
+print("al2 contains nfabs: ", algsplittingfield(al2)[12][1] != 0);
+al2b = al2; al2b[1][12][1] = 0; \\ depends on 32/64bit
+print(al2b);
+print("csa al3");
+al3 = alginit(nf, matrixringmt(3), 'x);
+print("al3 contains nfabs: ", algsplittingfield(al3)[12][1] != 0);
+al3b = al3; al3b[1][12][1] = 0; \\ depends on 32/64bit
+print(al3b);
+
+\\limit cases
+print("trivial algebra over a quadratic field");
+al = alginit(rnfinit(nfinit(y^2+1),x),[y,1])
+a = [y]~
+b = [1-2*y]~
+c = algrandom(al,3)
+algadd(al,a,b)
+algsub(al,c,a)
+algmul(al,a,b)
+algdivl(al,b,c)
+algdivr(al,c,b)
+alginv(al,a)
+algalgtobasis(al,b)
+algmultable(al,a)
+algcharpoly(al,b)
+algtrace(al,c)
+algnorm(al,c)
+algiscommutative(al)
+algissemisimple(al)
+algissimple(al)
+alghasse(al,1)
+alghasse(al,idealprimedec(nfinit(y^2+1),2)[1])
+algindex(al)
+algisdivision(al)
+algissplit(al)
+algisramified(al)
+algramifiedplaces(al)
+
+
+print("trivial algebra over Q");
+al = alginit(rnfinit(nfinit(y),x),[y,1])
+a = [-2]~
+b = [1/3]~
+c = algrandom(al,3)
+algadd(al,a,b)
+algsub(al,c,a)
+algmul(al,a,b)
+algdivl(al,b,c)
+algdivr(al,c,b)
+alginv(al,a)
+algalgtobasis(al,b)
+algmultable(al,a)
+algcharpoly(al,b)
+algtrace(al,c)
+algnorm(al,c)
+algiscommutative(al)
+algissemisimple(al)
+algissimple(al)
+alghasse(al,1)
+alghasse(al,idealprimedec(nfinit(y),2)[1])
+algindex(al)
+algisdivision(al)
+algissplit(al)
+algisramified(al)
+algramifiedplaces(al)
+
+print("trivial CSA over Q");
+al = alginit(nfinit(y), [Mat(1)]);
+algsqr(al,[Mod(3,y)]~)
+algsqr(al,[2]~)
+algsqr(al,[Mod(1,y),Mod(2,y)]~) \\should fail
+print("nontrivial CSA over Q");
+{m_i = [0,-1,0, 0;
+       1, 0,0, 0;
+       0, 0,0,-1;
+       0, 0,1, 0];
+m_j = [0, 0,-1,0;
+       0, 0, 0,1;
+       1, 0, 0,0;
+       0,-1, 0,0];
+m_k = [0, 0, 0, -1;
+       0, 0,-1, 0;
+       0, 1, 0, 0;
+       1, 0, 0, 0];
+mt = [matid(4), m_i, m_j, m_k];}
+al = alginit(nfinit(y), mt);
+algsqr(al,[Mod(3,y),Mod(2,y),Mod(1,y),Mod(2,y)]~)
+algsqr(al,[2,3,4,5]~)
+algsqr(al,[Mod(1,y),Mod(2,y)]~) \\should fail
+
+print("empty matrices");
+al = alginit(nfinit(y), [-1,-1]);
+print("-v: ", algneg(al,[;]) == [;]);
+print("v^(-1): ", alginv(al,[;]) == [;]);
+print("v^n: ", algpow(al, [;], 13) == [;]);
+print("v^0: ", algpow(al, [;], 0) == [;]);
+print("mt(v)", algmultable(al, [;]) == [;]);
+print("spl(v)", algsplittingmatrix(al, [;]) == [;]);
+print("trace(v): ", algtrace(al, [;]) == 0);
+print("norm(v): ", algnorm(al, [;]) == 1);
+print("charpoly(v): ", algcharpoly(al, [;]) == 1 && type(algcharpoly(al,[;])) == "t_POL");
+print("v+v: ", algadd(al,[;],[;]) == [;]);
+print("v-v: ", algsub(al,[;],[;]) == [;]);
+print("v*v: ", algmul(al,[;],[;]) == [;]);
+print("v/v: ", algdivr(al,[;],[;]) == [;]);
+print("v\\v: ", algdivl(al,[;],[;]) == [;]);
+v1 = matrix(0,1);
+print("v*nv: ", algmul(al,v1,matid(1))==v1);
+print("v*v 2: ", algmul(al,[;],matrix(0,1))==matrix(0,1));
+print("trace(v) char 2: ", algtrace(algtableinit([matid(1)],2), [;]) == 0);
+
+mt0 = [Mat([1])];
+almt0 = algtableinit(mt0,0)
+a = [12]~
+b = [-1/7]~
+algadd(almt0,a,b)
+algsub(almt0,a,b)
+algmul(almt0,a,b)
+algneg(almt0,a)
+alginv(almt0,a)
+algsqr(almt0,b)
+algdivl(almt0,a,b)
+algtrace(almt0,a)
+algnorm(almt0,b)
+algcharpoly(almt0,a)
+algmultable(almt0,b)
+algpow(almt0,a,0)
+algiscommutative(almt0)
+algissemisimple(almt0)
+algissimple(almt0)
+algisdivision(almt0)
+
+m_i = [0,-1,0, 0;\
+       1, 0,0, 0;\
+       0, 0,0,-1;\
+       0, 0,1, 0];
+m_j = [0, 0,-1,0;\
+       0, 0, 0,1;\
+       1, 0, 0,0;\
+       0,-1, 0,0];
+m_k = [0, 0, 0, -1;\
+       0, 0,-1, 0;\
+       0, 1, 0, 0;\
+       1, 0, 0, 0];
+mt = [matid(4), m_i, m_j, m_k];
+\\ bad inputs
+almt = algtableinit(mt,0);
+algsplittingfield(almt);
+algdegree(almt);
+alghassei(almt);
+alghassef(almt);
+algrandom(1,1)
+algrandom(1,I)
+algtype(1)
+algdim([1,[1],0,0,0,0,0,0,0,0])
+algabsdim([1,[1],0,0,0,0,0,0,0,0])
+algtensor(al,al2)
+algtensor(al2,al)
+algtensor(1,z,1)
+algisassociative([1],0)
+algisassociative([[1,0;0,2],[0,0;0,0]])
+algmul(almt,a,b)
+algmultable(almt,a)
+alginv(almt,a)
+algsplittingmatrix(almt,[0,0,0,0]~)
+algalgtobasis(almt,a)
+algbasistoalg(almt,[0,0,0,0]~)
+algpoleval(almt,1,a)
+zero = [0,0,0,0]~; m = Mat([1,1]); m[1,1]=zero; m[1,2]=zero;
+algadd(almt, [zero;zero], m)
+algadd(almt, [zero;zero;zero], [zero;zero]);
+algsub(almt, [zero;zero], m)
+algsub(almt, [zero;zero;zero], [zero;zero]);
+algmul(almt, m, [zero;zero;zero]);
+algsqr(almt, [zero;zero]);
+algdivl(almt, m, zero);
+algdivl(almt, m, [zero,zero;zero,zero]);
+algdivl(almt, m, m);
+alginv(almt, m);
+algmultable(almt, m);
+algpow(almt, m, 3);
+algtrace(almt, m);
+algcharpoly(almt, m);
+algcharpoly(alginit(nfinit(y),[-1,-1]), m);
+algnorm(almt, m);
+algnorm(alginit(nfinit(y),[-1,-1]), m);
+alginit(nfinit(y),[2,[[],[]],[x]])
+alginit(nfinit(y),[2,[],[1,1]])
+alginit(nfinit(y),[2,[[],[]],Vecsmall([1])])
+alginit(y,[2,[[],[]],[1]])
+alginit(nfinit(y), y)
+alginit(nfinit(y), [1,2,3,4])
+algtableinit(mt,y);
+alginit(nfinit(x^2+1),-3);
+al = alginit(nfinit(y^2-2),[-1,-1]); algrandom(al,-10)
+al = alginit(nfinit(y^2-2),[-1,-1]);
+algrelmultable(al);
+algsplittingdata(al);
+alghasse(almt, 1);
+algindex(almt, 1);
+algisdivision(almt);
+algissplit(almt);
+algisramified(almt);
+algramifiedplaces(almt);
+alghasse(al, -1);
+alghasse(al, 3);
+alghasse(al, 2^100);
+alghasse(al, []);
+alghasse(al, 1/3);
+algtableinit([matid(2), [0,1/2;1,0]]);
+Q = nfinit(y);
+alginit(Q, [matid(2), [0,1/2;1,0]]);
+alginit(Q, [-1/2, -1]);
+alginit(Q, [-1, -1/2]);
+alginit(rnfinit(Q, x^2+1), [-x,-1/2]);
+algsqr([0,0,0,0,0,0,0,0,0,0,0],[]~);
+algsqr([0,0,0,0,0,0,0,0,[],0,0],[]~);
+algsqr([0,0,0,0,0,0,0,0,[0],0,0],[]~);
+algsqr([0,0,0,0,0,0,0,0,[[;]],0,0],[]~);
+algsqr([[],0,0,0,0,0,0,0,[[;]],0,0],[]~);
+algsqr([[],[0],0,0,0,0,0,0,[[;]],0,0],[]~);
+algdim([[],[0],0,0,0,0,0,0,[[;]],0,0]);
+algdegree([[],[0],0,0,0,0,0,0,[[;]],0,0]);
+algdegree([rnfinit(nfinit(y),x),[[]],0,0,0,0,0,0,[[;]],0,0]);
+algcenter([rnfinit(nfinit(y),x),[[]],0,0,0,0,0,0,[[;]],0,0]);
+algcentralproj(almt,0);
+algcentralproj(almt,[zero,zero]);
+algsubalg(almt,0);
+algisassociative([]);
+algisassociative([matid(2),Mat([1,1])]);
+algisassociative([[1,2;3,4],matid(2)]);
+algisassociative([matid(1)],[]);
+algsqr(algtableinit([matid(1)]),[1,2]~);
+algsqr(al,vector(691)~);
+algsqr(al,[1,2,3,4,5,6,7,f^2]~);
+algsqr(al,[f^3,[]]~);
+algmul(al,[;],[1,2]~);
+algdivl(al,[;],matid(1));
+algdivl(al,matid(1),matrix(1,2));
+alginv(al,[0,0]~);
+al0mt = algtableinit([matid(1)]);
+algalgtobasis(al0mt,[1]~);
+algbasistoalg(al0mt,[1]~);
+nfgrunwaldwang(nfinit(y),0,[],[],'x);
+alginit(rnfinit(nfinit(y),x),0);
+alginit(rnfinit(nfinit(y),x),[1,2,3,4]);
+alginit(nfinit(y), [matid(2),matid(2)]);
+alginit(nfinit(y), [matid(2),[0,1;1,0]]);
+
+nfgrunwaldwang(nfinit(y), 0, [], [0]);
+nfgrunwaldwang(nfinit(y), [2], [], [0]);
+nfgrunwaldwang(nfinit(y), [2], [2], []);
+nfgrunwaldwang(nfinit(y), [2], [6], [0]);
+nfgrunwaldwang(nfinit(y), [2,3], [2,3], [0]);
+nfgrunwaldwang(nfinit(y), [2], [3], [-1]);
+nfgrunwaldwang(nfinit(y), [[]~], [3], [-1]);
+nfgrunwaldwang(nfinit(y), [2], [9], [0]);
+
+mt=[matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
+A=algtableinit(mt,2);
+algdegree(A)
+algsub(A,1,1)
+algadd(A,1,1)
+algneg(A,1)
+algmul(A,1,1)
+algsqr(A,1)
+algdivl(A,1,1)
+algdivr(A,1,1)
+alginv(A,1)
+a='a;
+K=nfinit(a);PR=idealprimedec(K,2);A=alginit(K,[3,[PR,[1]],[-1]]);
+K=nfinit(a);P2=idealprimedec(K,2);P3=idealprimedec(K,3);A=alginit(K,[3,[concat(P2,P3),[1/3,-2/3]],[1/3]]);
+algtensor(alginit(nfinit(y),2),alginit(nfinit(y^2+1),3));
+algtensor(alginit(nfinit(y),2),alginit(nfinit(y),2));
+nf = nfinit(y); p2 = idealprimedec(nf,2)[1]; p3 = idealprimedec(nf,3)[1];
+\\alginit(nf, [2, [[p2,p3],[1/2,1/2]], [0]]);
+alginit(nf, [2, [[p2,p2],[1/2,1/2]], [0]]);
+alginit(nf, [2, [[p2,p3],[1/2,1/2]], [0,0]]);
+alginit(nf, [2, [[p2,p3],[1/2,1/2],0], [0]]);
+alginit(nf, [2, [0,[1/2,1/2]], [0]]);
+alginit(nf, [2, [[p2,p3],0], [0]]);
+alginit(nf, [2, [[p2,p3],[1/2,1/2,0]], [0]]);
+alginit(nf, [2, [[p2,p3],[1/2,1/2]], [1/3]]);
+
+\\better accessors for hasse invariants
+setrand(1);
+x='x;
+nf = nfinit(y^3-y+1);
+rnf = rnfinit(nf, polcyclo(5,x));
+al = alginit(rnf, [x^2,-2]);
+alghasse(al,1)
+alghasse(al,2)
+alghasse(al,idealprimedec(nf,2)[1])
+alghasse(al,idealprimedec(nf,3)[1])
+alghasse(al,idealprimedec(nf,5)[1])
+alghasse(al,idealprimedec(nf,5)[2])
+algindex(al,1)
+algindex(al,2)
+algindex(al,idealprimedec(nf,2)[1])
+algindex(al,idealprimedec(nf,3)[1])
+algindex(al,idealprimedec(nf,5)[1])
+algindex(al,idealprimedec(nf,5)[2])
+algindex(al)
+algisdivision(al,1)
+algisdivision(al,2)
+algisdivision(al,idealprimedec(nf,2)[1])
+algisdivision(al,idealprimedec(nf,3)[1])
+algisdivision(al,idealprimedec(nf,5)[1])
+algisdivision(al,idealprimedec(nf,5)[2])
+algisdivision(al)
+algissplit(al,1)
+algissplit(al,2)
+algissplit(al,idealprimedec(nf,2)[1])
+algissplit(al,idealprimedec(nf,3)[1])
+algissplit(al,idealprimedec(nf,5)[1])
+algissplit(al,idealprimedec(nf,5)[2])
+algissplit(al)
+algisramified(al,1)
+algisramified(al,2)
+algisramified(al,idealprimedec(nf,2)[1])
+algisramified(al,idealprimedec(nf,3)[1])
+algisramified(al,idealprimedec(nf,5)[1])
+algisramified(al,idealprimedec(nf,5)[2])
+algisramified(al)
+algramifiedplaces(al)
+
+print(" ");
+al = 0;
+al = alginit(rnf, [x^2,-1]);
+alghasse(al,1)
+alghasse(al,2)
+alghasse(al,idealprimedec(nf,2)[1])
+alghasse(al,idealprimedec(nf,5)[1])
+alghasse(al,idealprimedec(nf,5)[2])
+algindex(al,1)
+algindex(al,2)
+algindex(al,idealprimedec(nf,2)[1])
+algindex(al,idealprimedec(nf,5)[1])
+algindex(al,idealprimedec(nf,5)[2])
+algindex(al)
+algisdivision(al,1)
+algisdivision(al,2)
+algisdivision(al,idealprimedec(nf,2)[1])
+algisdivision(al,idealprimedec(nf,5)[1])
+algisdivision(al,idealprimedec(nf,5)[2])
+algisdivision(al)
+algissplit(al,1)
+algissplit(al,2)
+algissplit(al,idealprimedec(nf,2)[1])
+algissplit(al,idealprimedec(nf,5)[1])
+algissplit(al,idealprimedec(nf,5)[2])
+algissplit(al)
+algisramified(al,1)
+algisramified(al,2)
+algisramified(al,idealprimedec(nf,2)[1])
+algisramified(al,idealprimedec(nf,5)[1])
+algisramified(al,idealprimedec(nf,5)[2])
+algisramified(al)
+algramifiedplaces(al)
+
+print(" ");
+al = 0;
+al = alginit(rnf, [x^2, 1]);
+alghasse(al,1)
+alghasse(al,2)
+alghasse(al,idealprimedec(nf,2)[1])
+alghasse(al,idealprimedec(nf,5)[2])
+algindex(al,1)
+algindex(al,2)
+algindex(al,idealprimedec(nf,2)[1])
+algindex(al,idealprimedec(nf,5)[2])
+algindex(al)
+algisdivision(al,1)
+algisdivision(al,2)
+algisdivision(al,idealprimedec(nf,2)[1])
+algisdivision(al,idealprimedec(nf,5)[2])
+algisdivision(al)
+algissplit(al,1)
+algissplit(al,2)
+algissplit(al,idealprimedec(nf,2)[1])
+algissplit(al,idealprimedec(nf,5)[2])
+algissplit(al)
+algisramified(al,1)
+algisramified(al,2)
+algisramified(al,idealprimedec(nf,2)[1])
+algisramified(al,idealprimedec(nf,5)[2])
+algisramified(al)
+algramifiedplaces(al)
+
+print("Hasse inv 0 bug");
+setrand(1); a='a;
+K=nfinit(a);PR=idealprimedec(K,2);A=alginit(K,[3,[PR,[0]],[0]]);
+algdegree(A)
+algdim(A)
+algindex(A)
+algisdivision(A)
+algadd(A,[1,0,0,0,0,0,0,0,0]~,[1,2,3]~)
+algsub(A,[1,0,0,0,0,0,0,0,0]~,[1,2,3]~)
+algmul(A,[0,0,0,0,0,0,0,0,0]~,[1,2,3]~)
+
+print("trivial tensor product");
+al1 = alginit(nfinit(y),1);
+al2 = alginit(nfinit(y),2);
+print(algtensor(al1,al2)==al2);
+print(algtensor(al2,al1)==al2);
+
+print("splitting a nasty commutative algebra");
+{mt = [matid(8),
+[0,2,0,0,0,0,0,0;
+ 1,0,0,0,0,0,0,0;
+ 0,0,0,2,0,0,0,0;
+ 0,0,1,0,0,0,0,0;
+ 0,0,0,0,0,2,0,0;
+ 0,0,0,0,1,0,0,0;
+ 0,0,0,0,0,0,0,2;
+ 0,0,0,0,0,0,1,0],
+
+[0,0,3,0,0,0,0,0;
+ 0,0,0,3,0,0,0,0;
+ 1,0,0,0,0,0,0,0;
+ 0,1,0,0,0,0,0,0;
+ 0,0,0,0,0,0,3,0;
+ 0,0,0,0,0,0,0,3;
+ 0,0,0,0,1,0,0,0;
+ 0,0,0,0,0,1,0,0],
+
+[0,0,0,6,0,0,0,0;
+ 0,0,3,0,0,0,0,0;
+ 0,2,0,0,0,0,0,0;
+ 1,0,0,0,0,0,0,0;
+ 0,0,0,0,0,0,0,6;
+ 0,0,0,0,0,0,3,0;
+ 0,0,0,0,0,2,0,0;
+ 0,0,0,0,1,0,0,0],
+
+[0,0,0,0,5,0,0,0;
+ 0,0,0,0,0,5,0,0;
+ 0,0,0,0,0,0,5,0;
+ 0,0,0,0,0,0,0,5;
+ 1,0,0,0,0,0,0,0;
+ 0,1,0,0,0,0,0,0;
+ 0,0,1,0,0,0,0,0;
+ 0,0,0,1,0,0,0,0],
+
+[0,0,0,0,0,10,0, 0;
+ 0,0,0,0,5, 0,0, 0;
+ 0,0,0,0,0, 0,0,10;
+ 0,0,0,0,0, 0,5, 0;
+ 0,2,0,0,0, 0,0, 0;
+ 1,0,0,0,0, 0,0, 0;
+ 0,0,0,2,0, 0,0, 0;
+ 0,0,1,0,0, 0,0, 0],
+
+[0,0,0,0,0,0,15, 0;
+ 0,0,0,0,0,0, 0,15;
+ 0,0,0,0,5,0, 0, 0;
+ 0,0,0,0,0,5, 0, 0;
+ 0,0,3,0,0,0, 0, 0;
+ 0,0,0,3,0,0, 0, 0;
+ 1,0,0,0,0,0, 0, 0;
+ 0,1,0,0,0,0, 0, 0],
+
+[0,0,0,0,0, 0, 0,30;
+ 0,0,0,0,0, 0,15, 0;
+ 0,0,0,0,0,10, 0, 0;
+ 0,0,0,0,5, 0, 0, 0;
+ 0,0,0,6,0, 0, 0, 0;
+ 0,0,3,0,0, 0, 0, 0;
+ 0,2,0,0,0, 0, 0, 0;
+ 1,0,0,0,0, 0, 0, 0]
+];}
+{chg =
+[1, 0,0,0,0,0, 0, 0;
+ 0, 1,0,0,0,0, 0, 0;
+ 0,-2,1,1,0,0, 0, 0;
+ 0,-1,0,1,0,0, 0, 0;
+ 0, 0,0,0,1,1,-2, 0;
+ 0, 0,0,0,0,1, 0,-1;
+ 0, 0,0,0,0,0, 1, 0;
+ 0, 0,0,0,0,0, 0, 1];}
+chgi = chg^(-1);
+mt2 = vector(8,j,chgi*sum(i=1,8,chg[i,j]*mt[i])*chg);
+algisassociative(mt2)
+al = algtableinit(mt2);
+algiscommutative(al)
+algissemisimple(al)
+setrand(9991);
+algissimple(al,1)
+
+print("non associative algebra");
+mt = [matid(3), [0,2,3;1,4,5;0,6,7], [0,8,9;0,10,11;1,12,13]];
+algisassociative(mt)
+
+print("csa without maximal order");
+alginit(nfinit(y), [matid(1)], 'x, 0);
+
+print("nfgrunwaldwang SEGV #1669");
+nfgrunwaldwang(nfinit(y),[2,3],[1,2],Vecsmall(1))
+nfgrunwaldwang(nfinit(x),[2,3],[1,2],Vecsmall(1))
+
+print("simplify bug #1671");
+test(str,al)={
+ my(sal = simplify(al), x, y);
+ setrand(1);
+ print("testing simplify: ", str);
+ print(algtype(al) == algtype(sal));
+ print(algdim(al) == algdim(sal));
+ x = algrandom(al,3);
+ y = algrandom(al,10);
+ print(algsqr(al,x) == algsqr(sal,x));
+ print(algsplittingmatrix(al,x) == algsplittingmatrix(sal,x));
+ print(algcharpoly(al,x) == algcharpoly(sal,x));
+ print(algnorm(al,x) == algnorm(sal,x));
+ print(algmultable(al,x) == algmultable(sal,x));
+ print(algtrace(al,x) == algtrace(sal,x));
+ print(alginv(al,x) == alginv(sal,x));
+ print(algpow(al,x,42) == algpow(sal,x,42));
+ print(algmul(al,x,y) == algmul(sal,x,y));
+ print(algdivl(al,x,y) == algdivl(sal,x,y));
+
+ print(algbasistoalg(al,x) == algbasistoalg(sal,x));
+ x = algbasistoalg(al,x);
+ print(algbasistoalg(al,y) == algbasistoalg(sal,y));
+ y = algbasistoalg(al,y);
+ print(algsqr(al,x) == algsqr(sal,x));
+ print(algsplittingmatrix(al,x) == algsplittingmatrix(sal,x));
+ print(algcharpoly(al,x) == algcharpoly(sal,x));
+ print(algnorm(al,x) == algnorm(sal,x));
+ print(algmultable(al,x) == algmultable(sal,x));
+ print(algtrace(al,x) == algtrace(sal,x));
+ print(alginv(al,x) == alginv(sal,x));
+ print(algpow(al,x,42) == algpow(sal,x,42));
+ print(algmul(al,x,y) == algmul(sal,x,y));
+ print(algdivl(al,x,y) == algdivl(sal,x,y));
+
+ print(algadd(al,x,y) == algadd(al,x,simplify(y)));
+ print(algmul(al,x,y) == algmul(al,x,simplify(y)));
+ print(algmul(al,x,y) == algmul(al,simplify(x),simplify(y)));
+};
+test("degree 1 cyclic over Q", alginit(nfinit(y),1));
+test("degree 1 cyclic over Q(i)", alginit(nfinit(y^2+1),1));
+test("degree 1 csa over Q", alginit(nfinit(y), [matid(1)]));
+test("degree 1 csa over Q(i)", alginit(nfinit(y^2+1), [matid(1)]));
+test("quatalg over Q(s5)", alginit(nfinit(y^2-5), [-2,-3]));
+{m_i = [0,-1,0, 0;
+       1, 0,0, 0;
+       0, 0,0,-1;
+       0, 0,1, 0];
+m_j = [0, 0,-1,0;
+       0, 0, 0,1;
+       1, 0, 0,0;
+       0,-1, 0,0];
+m_k = [0, 0, 0, -1;
+       0, 0,-1, 0;
+       0, 1, 0, 0;
+       1, 0, 0, 0];
+mt = [matid(4), m_i, m_j, m_k];}
+test("quatalg csa over Q", alginit(nfinit(y), mt));
diff --git a/src/test/in/apply b/src/test/in/apply
index 3dc8bb7..9da623f 100644
--- a/src/test/in/apply
+++ b/src/test/in/apply
@@ -10,3 +10,8 @@ L=[1,2,3]; apply(f, L)
 L=[1,2,3]; [f(x) | x<-L]
 L=[1,2,3]; [x | x<-L, f(x)]
 L=[1,2,3]; select(f, L)
+
+fold((x,y)->x*y, [1,2,3,4])
+fold((x,y)->[x,y], [1,2,3,4])
+fold((x,f)->f(x), [2,sqr,sqr,sqr])
+fold((x,y)->(x+y)/(1-x*y),[1..5])
diff --git a/src/test/in/bnrL1 b/src/test/in/bnrL1
index 06208e1..7e46e2b 100644
--- a/src/test/in/bnrL1
+++ b/src/test/in/bnrL1
@@ -1,6 +1,8 @@
 default(realprecision,38);
-K=bnfinit(x^2+31);bnrL1(bnrinit(K,1,1))
-K=bnfinit(x^2-3);
-bnrL1(bnrinit(K,5,1))
-bnrL1(bnrinit(K,[5,[1,0]],1))
-bnrL1(bnrinit(K,[5,[1,1]],1))
+setrand(1); K=bnfinit(x^2+31);bnrL1(bnrinit(K,1,1))
+setrand(1); K=bnfinit(x^2-3);
+setrand(1); bnrL1(bnrinit(K,5,1),,5)
+setrand(1); bnrL1(bnrinit(K,[5,[1,0]],1),,5)
+setrand(1); bnrL1(bnrinit(K,[5,[1,1]],1),,5)
+setrand(1); K=bnfinit(x^2-168);\\#1601
+setrand(1); bnrL1(bnrinit(K,[6,[1,1]],1),,5)
diff --git a/src/test/in/bnrisgalois b/src/test/in/bnrisgalois
new file mode 100644
index 0000000..4f238b9
--- /dev/null
+++ b/src/test/in/bnrisgalois
@@ -0,0 +1,4 @@
+K=bnfinit(a^4-3*a^2+253009);B=bnrinit(K,9,1);G=galoisinit(K);
+[H|H<-subgrouplist(B,3), bnrisgalois(B,G,H)]
+M=bnrgaloismatrix(B,G)
+[H|H<-subgrouplist(B,3), bnrisgalois(B,M,H)]
diff --git a/src/test/in/characteristic b/src/test/in/characteristic
index fd1e009..83e1864 100644
--- a/src/test/in/characteristic
+++ b/src/test/in/characteristic
@@ -4,3 +4,5 @@ characteristic(v)
 characteristic(matid(2)*Mod(1,2))
 characteristic([])
 characteristic(List())
+characteristic(ffgen(2^3))
+characteristic([ffgen(2),ffgen(3)])
diff --git a/src/test/in/chinese b/src/test/in/chinese
index bc7a0cf..25248ea 100644
--- a/src/test/in/chinese
+++ b/src/test/in/chinese
@@ -2,3 +2,4 @@ chinese(Mod(x,x^2+1),Mod(x,x^2+1))
 chinese(Mod(x,x^2+1),Mod(x,x^2-1))
 chinese(Mod(1,2)*x+Mod(1,2), Mod(2,3)*x^2+Mod(1,3)*x+Mod(1,3))
 chinese([Mod(1,2),Mod(1,3)], [Mod(1,4),Mod(1,2)])
+chinese(1)
diff --git a/src/test/in/cmp b/src/test/in/cmp
index e1fcdc0..207788e 100644
--- a/src/test/in/cmp
+++ b/src/test/in/cmp
@@ -9,9 +9,19 @@ test(x,x+1)
 test(x,y)
 test(O(x),x+O(x^2))
 
-1 > "a"
-1. > "a"
-1/2 > "a"
-"a" > 0
+v=[-oo, 1/2, 1, oo];
+for (i=1, #v, for(j=i+1,#v, if( v[i] >= v[j], error([i,j]))));
+for (i=1, #v, for(j=i+1,#v, if( !(v[i] < v[j]), error([i,j]))));
+for (i=1, #v, if(!(v[i] == v[i]), error(i)));
+for (i=1, #v, if(!(v[i] === v[i]), error(i)));
+
 Mod(1,3) > 0
 lex(Vecsmall([1,2]),Vecsmall([1,3]))
+
+["x"<="y", "x"<="x", "x"<="w"]
+[oo <= -oo, oo <= oo, -oo <= -oo]
+1. <= oo
+1. <= -oo
+1 <= 'x
+1. <= 'x
+1/2 <= 'x
diff --git a/src/test/in/compat b/src/test/in/compat
index 954e7e2..19f0427 100644
--- a/src/test/in/compat
+++ b/src/test/in/compat
@@ -1,621 +1,393 @@
-\e
-default(compatible,3)
-+3
--5
-5+3
-5-3
-5/3
-5\3
-5\/3
-5%3
-5^3
-\precision=154
-pi
-\precision=38
-o(x^12)
-padicno=(5/3)*127+O(127^5)
-initrect(0,500,500)
-\\ A
-abs(-0.01)
-acos(0.5)
-acosh(3)
-acurve=initell([0,0,1,-1,0])
-apoint=[2,2]
-isoncurve(acurve,apoint)
-addell(acurve,apoint,apoint)
-addprimes([nextprime(10^9),nextprime(10^10)])
-adj([1,2;3,4])
-agm(1,2)
-agm(1+o(7^5),8+o(7^5))
-algdep(2*cos(2*pi/13),6)
-algdep2(2*cos(2*pi/13),6,15)
-akell(acurve,1000000007)
-nfpol=x^5-5*x^3+5*x+25
-nf=initalg(nfpol)
-ba=algtobasis(nf,mod(x^3+5,nfpol))
-anell(acurve,100)
-apell(acurve,10007)
-apell2(acurve,10007)
-apol=x^3+5*x+1
-apprpadic(apol,1+O(7^8))
-apprpadic(x^3+5*x+1,mod(x*(1+O(7^8)),x^2+x-1))
-4*arg(3+3*i)
-3*asin(sqrt(3)/2)
-asinh(0.5)
-assmat(x^5-12*x^3+0.0005)
-3*atan(sqrt(3))
-atanh(0.5)
-\\ B
-basis(x^3+4*x+5)
-basis2(x^3+4*x+5)
-basistoalg(nf,ba)
-bernreal(12)
-bernvec(6)
-bestappr(pi,10000)
-bezout(123456789,987654321)
-bigomega(12345678987654321)
-mcurve=initell([0,0,0,-17,0])
-mpoints=[[-1,4],[-4,2]]~
-mhbi=bilhell(mcurve,mpoints,[9,24])
-bin(1.1,5)
-binary(65537)
-bittest(10^100,100)
-boundcf(pi,5)
-boundfact(40!+1,100000)
-move(0,0,0);box(0,500,500)
-setrand(1);buchimag(1-10^7,1,1)
-setrand(1);bnf=buchinitfu(x^2-x-57,0.2,0.2)
-buchcertify(bnf)
-buchfu(bnf)
-setrand(1);buchinitforcefu(x^2-x-100000)
-setrand(1);bnf=buchinitfu(x^2-x-57,0.2,0.2)
-setrand(1);buchreal(10^9-3,0,0.5,0.5)
-setrand(1);buchgen(x^4-7,0.2,0.2)
-setrand(1);buchgenfu(x^2-x-100000)
-setrand(1);buchgenforcefu(x^2-x-100000)
-setrand(1);buchgenfu(x^4+24*x^2+585*x+1791,0.1,0.1)
-buchnarrow(bnf)
-buchray(bnf,[[5,3;0,1],[1,0]])
-bnr=buchrayinitgen(bnf,[[5,3;0,1],[1,0]])
-bnr2=buchrayinitgen(bnf,[[25,13;0,1],[1,1]])
-bytesize(%)
-\\ C
-ceil(-2.5)
-centerlift(mod(456,555))
-cf(pi)
-cf2([1,3,5,7,9],(exp(1)-1)/(exp(1)+1))
-changevar(x+y,[z,t])
-char([1,2;3,4],z)
-char(mod(x^2+x+1,x^3+5*x+1),z)
-char1([1,2;3,4],z)
-char2(mod(1,8191)*[1,2;3,4],z)
-acurve=chell(acurve,[-1,1,2,3])
-chinese(mod(7,15),mod(13,21))
-apoint=chptell(apoint,[-1,1,2,3])
-isoncurve(acurve,apoint)
-classno(-12391)
-classno(1345)
-classno2(-12391)
-classno2(1345)
-coeff(sin(x),7)
-compimag(qfi(2,1,3),qfi(2,1,3))
-compo(1+o(7^4),3)
-compositum(x^4-4*x+2,x^3-x-1)
-compositum2(x^4-4*x+2,x^3-x-1)
-comprealraw(qfr(5,3,-1,0.),qfr(7,1,-1,0.))
-concat([1,2],[3,4])
-conductor(bnf,[[25,13;0,1],[1,1]])
-conductorofchar(bnr,[2])
-conj(1+i)
-conjvec(mod(x^2+x+1,x^3-x-1))
-content([123,456,789,234])
-convol(sin(x),x*cos(x))
-core(54713282649239)
-core2(54713282649239)
-coredisc(54713282649239)
-coredisc2(54713282649239)
-cos(1)
-cosh(1)
-move(0,200,150)
-cursor(0)
-cvtoi(1.7)
-cyclo(105)
-\\ D
-degree(x^3/(x-1))
-denom(12345/54321)
-deplin(mod(1,7)*[2,-1;1,3])
-deriv((x+y)^5,y)
-((x+y)^5)'
-det([1,2,3;1,5,6;9,8,7])
-det2([1,2,3;1,5,6;9,8,7])
-detint([1,2,3;4,5,6])
-diagonal([2,4,6])
-dilog(0.5)
-dz=vector(30,k,1);dd=vector(30,k,k==1);dm=dirdiv(dd,dz)
-deu=direuler(p=2,100,1/(1-apell(acurve,p)*x+if(acurve[12]%p,p,0)*x^2))
-anell(acurve,100)==deu
-dirmul(abs(dm),dz)
-dirzetak(initalg(x^3-10*x+8),30)
-disc(x^3+4*x+12)
-discf(x^3+4*x+12)
-discrayabs(bnr,mat(6))
-discrayabs(bnr)
-discrayabscond(bnr2)
-lu=ideallistunitgen(bnf,55);discrayabslist(bnf,lu)
-discrayabslistlong(bnf,20)
-discrayrel(bnr,mat(6))
-discrayrel(bnr)
-discrayrelcond(bnr2)
-divisors(8!)
-divres(345,123)
-divres(x^7-1,x^5+1)
-divsum(8!,x,x)
-postdraw([0,0,0])
-\\ E
-eigen([1,2,3;4,5,6;7,8,9])
-eint1(2)
-erfc(2)
-eta(q)
-euler
-z=y;y=x;eval(z)
-exp(1)
-extract([1,2,3,4,5,6,7,8,9,10],1000)
-\\ F
-10!
-fact(10)
-factcantor(x^11+1,7)
-centerlift(lift(factfq(x^3+x^2+x-1,3,t^3+t^2+t-1)))
-factmod(x^11+1,7)
-factor(17!+1)
-p=x^5+3021*x^4-786303*x^3-6826636057*x^2-546603588746*x+3853890514072057
-fa=[11699,6;2392997,2;4987333019653,2]
-factoredbasis(p,fa)
-factoreddiscf(p,fa)
-factoredpolred(p,fa)
-factoredpolred2(p,fa)
-factornf(x^3+x^2-2*x-1,t^3+t^2-2*t-1)
-factorpadic(apol,7,8)
-factorpadic2(apol,7,8)
-factpol(x^15-1,3,1)
-factpol(x^15-1,0,1)
-fibo(100)
-floor(-1/2)
-floor(-2.5)
-for(x=1,5,print(x!))
-fordiv(10,x,print(x))
-forprime(p=1,30,print(p))
-forstep(x=0,pi,pi/12,print(sin(x)))
-forvec(x=[[1,3],[-2,2]],print1([x[1],x[2]]," "));print(" ");
-frac(-2.7)
-\\ G
-galois(x^6-3*x^2-1)
-nf3=initalg(x^6+108);galoisconj(nf3)
-aut=%[2];galoisapply(nf3,aut,mod(x^5,x^6+108))
-gamh(10)
-gamma(10.5)
-gauss(hilbert(10),[1,2,3,4,5,6,7,8,9,0]~)
-gaussmodulo([2,3;5,4],[7,11]~,[1,4]~)
-gaussmodulo2([2,3;5,4],[7,11]~,[1,4]~)
-gcd(12345678,87654321)
-getrand()
-globalred(acurve)
-\\ H
-hclassno(2000003)
-hell(acurve,apoint)
-hell2(acurve,apoint)
-hermite(amat=1/hilbert(7))
-hermite2(amat)
-hermitemod(amat,detint(amat))
-hermiteperm(amat)
-hess(hilbert(7))
-hilb(2/3,3/4,5)
-hilbert(5)
-hilbp(mod(5,7),mod(6,7))
-hvector(10,x,1/x)
-hyperu(1,1,1)
-\\ I
-i^2
-initalgred(nfpol)
-initalgred2(nfpol)
-vp=primedec(nf,3)[1]
-idx=idealmul(nf,idmat(5),vp)
-idy=ideallllred(nf,idx,[1,5,6])
-idealadd(nf,idx,idy)
-idealaddone(nf,idx,idy)
-idealaddmultone(nf,[idy,idx])
-idealappr(nf,idy)
-idealapprfact(nf,idealfactor(nf,idy))
-idealcoprime(nf,idx,idx)
-idz=idealintersect(nf,idx,idy)
-idealfactor(nf,idz)
-ideallist(bnf,20)
-idx2=idealmul(nf,idx,idx)
-idt=idealmulred(nf,idx,idx)
-idealdiv(nf,idy,idt)
-idealdivexact(nf,idx2,idx)
-idealhermite(nf,vp)
-idealhermite2(nf,vp[2],3)
-idealnorm(nf,idt)
-idp=idealpow(nf,idx,7)
-idealpowred(nf,idx,7)
-idealtwoelt(nf,idy)
-idealtwoelt2(nf,idy,10)
-idealval(nf,idp,vp)
-idmat(5)
-if(3<2,print("bof"),print("ok"));
-imag(2+3*i)
-image([1,3,5;2,4,6;3,5,7])
-image(pi*[1,3,5;2,4,6;3,5,7])
-incgam(2,1)
-incgam3(2,1)
-incgam4(4,1,6)
-indexrank([1,1,1;1,1,1;1,1,2])
-indsort([8,7,6,5])
-initell([0,0,0,-1,0])
-initrect(1,700,700)
-nfz=initzeta(x^2-2);
-integ(sin(x),x)
-integ((-x^2-2*a*x+8*a)/(x^4-14*x^3+(2*a+49)*x^2-14*a*x+a^2),x)
-intersect([1,2;3,4;5,6],[2,3;7,8;8,9])
-\precision=19
-intgen(x=0,pi,sin(x))
-sqr(2*intgen(x=0,4,exp(-x^2)))
-4*intinf(x=1,10^20,1/(1+x^2))
-intnum(x=-0.5,0.5,1/sqrt(1-x^2))
-2*intopen(x=0,100,sin(x)/x)
-\precision=38
-inverseimage([1,1;2,3;5,7],[2,2,6]~)
-isdiagonal([1,0,0;0,5,0;0,0,0])
-isfund(12345)
-isideal(bnf[7],[5,1;0,1])
-isincl(x^2+1,x^4+1)
-isinclfast(initalg(x^2+1),initalg(x^4+1))
-isirreducible(x^5+3*x^3+5*x^2+15)
-isisom(x^3+x^2-2*x-1,x^3+x^2-2*x-1)
-isisomfast(initalg(x^3-2),initalg(x^3-6*x^2-6*x-30))
-isprime(12345678901234567)
-isprincipal(bnf,[5,1;0,1])
-isprincipalgen(bnf,[5,1;0,1])
-isprincipalraygen(bnr,primedec(bnf,7)[1])
-ispsp(73!+1)
-isqrt(10!^2+1)
-isset([-3,5,7,7])
-issqfree(123456789876543219)
-issquare(12345678987654321)
-isunit(bnf,mod(3405*x-27466,x^2-x-57))
-\\ J
-jacobi(hilbert(6))
-jbesselh(1,1)
-jell(i)
-\\ K
-kbessel(1+i,1)
-kbessel2(1+i,1)
-x
-y
-ker(matrix(4,4,x,y,x/y))
-ker(matrix(4,4,x,y,sin(x+y)))
-keri(matrix(4,4,x,y,x+y))
-kerint(matrix(4,4,x,y,x*y))
-kerint1(matrix(4,4,x,y,x*y))
-f(u)=u+1;
-print(f(5));kill(f);
-f=12
-killrect(1)
-kro(5,7)
-kro(3,18)
-\\ L
-laplace(x*exp(x*y)/(exp(x)-1))
-lcm(15,-21)
-length(divisors(1000))
-legendre(10)
-lex([1,3],[1,3,5])
-lexsort([[1,5],[2,4],[1,5,1],[1,4,2]])
-lift(chinese(mod(7,15),mod(4,21)))
-lindep([(1-3*sqrt(2))/(3-2*sqrt(3)),1,sqrt(2),sqrt(3),sqrt(6)])
-lindep2([(1-3*sqrt(2))/(3-2*sqrt(3)),1,sqrt(2),sqrt(3),sqrt(6)],14)
-move(0,0,900);line(0,900,0)
-lines(0,vector(5,k,50*k),vector(5,k,10*k*k))
-m=1/hilbert(7)
-mp=concat(m,idmat(7))
-lll(m)
-lllgram(m)
-lllgramint(m)
-lllgramkerim(mp~*mp)
-lllint(m)
-lllintpartial(m)
-lllkerim(mp)
-\precision=96
-ln(2)
-lngamma(10^50*i)
-\precision=2000
-log(2)
-logagm(2)
-\precision=19
-bcurve=initell([0,0,0,-3,0])
-localred(bcurve,2)
-ccurve=initell([0,0,-1,-1,0])
-l=lseriesell(ccurve,2,-37,1)
-lseriesell(ccurve,2,-37,1.2)-l
-\\ M
-sbnf=smallbuchinit(x^3-x^2-14*x-1)
-makebigbnf(sbnf)
-concat(mat(vector(4,x,x)~),vector(4,x,10+x)~)
-matextract(matrix(15,15,x,y,x+y),vector(5,x,3*x),vector(3,y,3*y))
-ma=mathell(mcurve,mpoints)
-gauss(ma,mhbi)
-(1.*hilbert(7))^(-1)
-matsize([1,2;3,4;5,6])
-matrix(5,5,x,y,gcd(x,y))
-matrixqz([1,3;3,5;5,7],0)
-matrixqz2([1/3,1/4,1/6;1/2,1/4,-1/4;1/3,1,0])
-matrixqz3([1,3;3,5;5,7])
-max(2,3)
-min(2,3)
-minim([2,1;1,2],4,6)
-mod(-12,7)
-modp(-12,7)
-mod(10873,49649)^-1
-modreverse(mod(x^2+1,x^3-x-1))
-move(0,243,583);cursor(0)
-mu(3*5*7*11*13)
-\\ N
-newtonpoly(x^4+3*x^3+27*x^2+9*x+81,3)
-nextprime(100000000000000000000000)
-setrand(1);N=10^8;a=matrix(3,5,j,k,vvector(5,l,random()\N))
-aid=[idx,idy,idz,idmat(5),idx]
-bb=algtobasis(nf,mod(x^3+x,nfpol))
-da=nfdetint(nf,[a,aid])
-nfdiv(nf,ba,bb)
-nfdiveuc(nf,ba,bb)
-nfdivres(nf,ba,bb)
-nfhermite(nf,[a,aid])
-nfhermitemod(nf,[a,aid],da)
-nfmod(nf,ba,bb)
-nfmul(nf,ba,bb)
-nfpow(nf,bb,5)
-nfreduce(nf,ba,idx)
-nfsmith(nf,[a[,1..3],[1,1,1],[idealinv(nf,idx), idealinv(nf,idy),1]])
-nfval(nf,ba,vp)
-norm(1+i)
-norm(mod(x+5,x^3+x+1))
-norml2(vector(10,x,x))
-nucomp(qfi(2,1,9),qfi(4,3,5),3)
-form=qfi(2,1,9);nucomp(form,form,3)
-numdiv(2^99*3^49)
-numer((x+1)/(x-1))
-nupow(form,111)
-\\ O
-1/(1+x)+o(x^20)
-omega(100!)
-ordell(acurve,1)
-order(mod(33,2^16+1))
-tcurve=initell([1,0,1,-19,26]);
-orderell(tcurve,[1,2])
-ordred(x^3-12*x+45*x-1)
-\\ P
-padicprec(padicno,127)
-pascal(8)
-perf([2,0,1;0,2,1;1,1,2])
-permutation(7,1035)
-permutation2num([4,7,1,6,3,5,2])
-pf(-44,3)
-phi(257^2)
-pi
-b=10;a=1<<b;plot(x=-5,5,round(sin(x)<<b)/a)
-pnqn([2,6,10,14,18,22,26])
-pnqn([1,1,1,1,1,1,1,1;1,1,1,1,1,1,1,1])
-point(0,225,334)
-points(0,vector(10,k,10*k),vector(10,k,5*k*k))
-pointell(acurve,zell(acurve,apoint))
-polint([0,2,3],[0,4,9],5)
-polred(x^5-2*x^4-4*x^3-96*x^2-352*x-568)
-polred2(x^4-28*x^3-458*x^2+9156*x-25321)
-polredabs(x^5-2*x^4-4*x^3-96*x^2-352*x-568)
-polredabs2(x^5-2*x^4-4*x^3-96*x^2-352*x-568)
-polsym(x^17-1,17)
-polvar(name^4-other)
-poly(sin(x),x)
-polylog(5,0.5)
-polylog(-4,t)
-polylogd(5,0.5)
-polylogdold(5,0.5)
-polylogp(5,0.5)
-poly([1,2,3,4,5],x)
-polyrev([1,2,3,4,5],x)
-polzag(6,3)
-postdraw([0,20,20])
-postploth(x=-5,5,sin(x))
-postploth2(t=0,2*pi,[sin(5*t),sin(7*t)])
-postplothraw(vector(100,k,k),vector(100,k,k*k/100))
-powell(acurve,apoint,10)
-cmcurve=initell([0,-3/4,0,-2,-1])
-powell(cmcurve,[x,y],quadgen(-7))
-powrealraw(qfr(5,3,-1,0.),3)
-pprint((x-12*y)/(y+13*x));
-pprint([1,2;3,4])
-pprint1(x+y);pprint(x+y);
-\precision=96
-pi
-prec(pi,20)
-precision(cmcurve)
-\precision=38
-prime(100)
-primedec(nf,2)
-primedec(nf,3)
-primedec(nf,11)
-primes(100)
-forprime(p=2,100,print(p," ",lift(primroot(p))))
-principalideal(nf,mod(x^3+5,nfpol))
-print((x-12*y)/(y+13*x));
-print([1,2;3,4])
-print1(x+y);print1(" equals ");print(x+y);
-prod(1,k=1,10,1+1/k!)
-prod(1.,k=1,10,1+1/k!)
-pi^2/6*prodeuler(p=2,10000,1-p^-2)
-prodinf(n=0,(1+2^-n)/(1+2^(-n+1)))
-prodinf1(n=0,-2^-n/(1+2^(-n+1)))
-psi(1)
-\\ Q
-quaddisc(-252)
-quadgen(-11)
-quadpoly(-11)
-\\ R
-rank(matrix(5,5,x,y,x+y))
-rayclassno(bnf,[[5,3;0,1],[1,0]])
-rayclassnolist(bnf,lu)
-move(0,50,50);rbox(0,50,50)
-print1("give a value for s? ");s=read();print(1/s)
-37.
-real(5-7*i)
-recip(3*x^7-5*x^3+6*x-9)
-redimag(qfi(3,10,12))
-redreal(qfr(3,10,-20,1.5))
-redrealnod(qfr(3,10,-20,1.5),18)
-reduceddisc(x^3+4*x+12)
-regula(17)
-kill(y);print(x+y);
-resultant(x^3-1,x^3+1)
-resultant2(x^3-1.,x^3+1.)
-bezoutres(x^2+1, x^2-1)
-reverse(tan(x))
-rhoreal(qfr(3,10,-20,1.5))
-rhorealnod(qfr(3,10,-20,1.5),18)
-rline(0,200,150)
-cursor(0)
-rmove(0,5,5);cursor(0)
-rndtoi(prod(1,k=1,17,x-exp(2*i*pi*k/17)))
-qpol=y^3-y-1;setrand(1);bnf2=buchinit(qpol);nf2=bnf2[7];
-un=mod(1,qpol);w=mod(y,qpol);p=un*(x^5-5*x+w)
-aa=rnfpseudobasis(nf2,p)
-rnfbasis(bnf2,aa)
-rnfdiscf(nf2,p)
-rnfequation(nf2,p)
-rnfequation2(nf2,p)
-rnfhermitebasis(bnf2,aa)
-rnfisfree(bnf2,aa)
-rnfsteinitz(nf2,aa)
-rootmod(x^16-1,41)
-rootpadic(x^4+1,41,6)
-roots(x^5-5*x^2-5*x-5)
-rootsold(x^4-1000000000000000000000)
-round(prod(1,k=1,17,x-exp(2*i*pi*k/17)))
-rounderror(prod(1,k=1,17,x-exp(2*i*pi*k/17)))
-rpoint(0,20,20)
-\\ S
-initrect(3,600,600);scale(3,-7,7,-2,2);cursor(3)
-q*series(anell(acurve,100),q)
-aset=set([5,-2,7,3,5,1])
-bset=set([7,5,-5,7,2])
-setintersect(aset,bset)
-setminus(aset,bset)
-setprecision(28)
-setrand(10)
-setsearch(aset,3)
-setsearch(bset,3)
-setserieslength(12)
-setunion(aset,bset)
-shift(1,50)
-shift([3,4,-11,-12],-2)
-shiftmul([3,4,-11,-12],-2)
-sigma(100)
-sigmak(2,100)
-sigmak(-3,100)
-sign(-1)
-sign(0)
-sign(0.)
-signat(hilbert(5)-0.11*idmat(5))
-signunit(bnf)
-simplefactmod(x^11+1,7)
-simplify(((x+i+1)^2-x^2-2*x*(i+1))^2)
-sin(pi/6)
-sinh(1)
-size([1.3*10^5,2*i*pi*exp(4*pi)])
-smallbasis(x^3+4*x+12)
-smalldiscf(x^3+4*x+12)
-smallfact(100!+1)
-smallinitell([0,0,0,-17,0])
-smallpolred(x^4+576)
-smallpolred2(x^4+576)
-smith(matrix(5,5,j,k,random()))
-smith(1/hilbert(6))
-smithpol(x*idmat(5)-matrix(5,5,j,k,1))
-solve(x=1,4,sin(x))
-sort(vector(17,x,5*x%17))
-sqr(1+o(2))
-sqred(hilbert(5))
-sqrt(13+o(127^12))
-srgcd(x^10-1,x^15-1)
-move(0,100,100);string(0,pi)
-move(0,200,200);string(0,"(0,0)")
-postdraw([0,10,10])
-apol=0.3+legendre(10)
-sturm(apol)
-sturmpart(apol,0.91,1)
-subcyclo(31,5)
-subell(initell([0,0,0,-17,0]),[-1,4],[-4,2])
-subst(sin(x),x,y)
-subst(sin(x),x,x+x^2)
-sum(0,k=1,10,2^-k)
-sum(0.,k=1,10,2^-k)
-sylvestermatrix(a2*x^2+a1*x+a0,b1*x+b0)
-\precision=38
-4*sumalt(n=0,(-1)^n/(2*n+1))
-4*sumalt2(n=0,(-1)^n/(2*n+1))
-suminf(n=1,2.^-n)
-6/pi^2*sumpos(n=1,n^-2)
-supplement([1,3;2,4;3,6])
-\\ T
-sqr(tan(pi/3))
-tanh(1)
-taniyama(bcurve)
-taylor(y/(x-y),y)
-tchebi(10)
-teich(7+o(127^12))
-texprint((x+y)^3/(x-y)^2)
-theta(0.5,3)
-thetanullk(0.5,7)
-torsell(tcurve)
-trace(1+i)
-trace(mod(x+5,x^3+x+1))
-trans(vector(2,x,x))
-%*%~
-trunc(-2.7)
-trunc(sin(x^2))
-tschirnhaus(x^5-x-1)
-type(mod(x,x^2+1))
-\\ U
-unit(17)
-n=33;until(n==1,print1(n," ");if(n%2,n=3*n+1,n=n/2));print(1)
-\\ V
-valuation(6^10000-1,5)
-vec(sin(x))
-vecmax([-3,7,-2,11])
-vecmin([-3,7,-2,11])
-vecsort([[1,8,5],[2,5,8],[3,6,-6],[4,8,6]],2)
-vecsort([[1,8,5],[2,5,8],[3,6,-6],[4,8,6]],[2,1])
-\\ W
-weipell(acurve)
-wf(i)
-wf2(i)
-m=5;while(m<20,print1(m," ");m=m+1);print()
-\\ Z
-zell(acurve,apoint)
-zeta(3)
-zeta(0.5+14.1347251*i)
-zetak(nfz,-3)
-zetak(nfz,1.5+3*i)
-zidealstar(nf2,54)
-bid=zidealstarinit(nf2,54)
-zideallog(nf2,w,bid)
-znstar(3120)
-sin'(4)
-m = 3; if(m == 1,2, m == 3,4,5)
-A=[1,2,3];
-deplin(A)
-deplin(Mod(A,2))
-deplin(Mod(A,7))
-deplin(Mod(A,2^64+13))
+abs()
+addell()
+addprimes()
+adj()
+akell()
+algdep2()
+algtobasis()
+anell()
+apell()
+apell2()
+apprpadic()
+assmat()
+basis()
+basis2()
+basistoalg()
+bilhell()
+bin()
+boundcf()
+boundfact()
+buchcertify()
+buchfu()
+buchgen()
+buchgenforcefu()
+buchgenfu()
+buchimag()
+buchinit()
+buchinitforcefu()
+buchinitfu()
+buchnarrow()
+buchray()
+buchrayinit()
+buchrayinitgen()
+buchreal()
+bytesize()
+cf()
+cf2()
+changevar()
+char()
+char1()
+char2()
+chell()
+chptell()
+classno()
+classno2()
+coeff()
+compimag()
+compo()
+compositum()
+compositum2()
+comprealraw()
+conductor()
+conductorofchar()
+convol()
+core2()
+coredisc2()
+cvtoi()
+cyclo()
+decodefactor()
+decodemodule()
+degree()
+denom()
+deplin()
+det()
+det2()
+detint()
+diagonal()
+disc()
+discf()
+discf2()
+discrayabs()
+discrayabscond()
+discrayabslist()
+discrayabslistarch()
+discrayabslistarchall()
+discrayabslistlong()
+discrayrel()
+discrayrelcond()
+divres()
+divsum()
+eigen()
+euler()
+extract()
+fact()
+factcantor()
+factfq()
+factmod()
+factoredbasis()
+factoreddiscf()
+factoredpolred()
+factoredpolred2()
+factorpadic2()
+factpol()
+factpol2()
+fibo()
+fpn()
+galois()
+galoisapply()
+galoisconj()
+galoisconj1()
+galoisconjforce()
+gamh()
+gauss()
+gaussmodulo()
+gaussmodulo2()
+globalred()
+goto()
+hclassno()
+hell()
+hell2()
+hermite()
+hermite2()
+hermitehavas()
+hermitemod()
+hermitemodid()
+hermiteperm()
+hess()
+hilb()
+hilbp()
+hvector()
+i()
+idealaddmultone()
+idealaddone()
+idealapprfact()
+idealdivexact()
+idealhermite()
+idealhermite2()
+idealinv2()
+ideallistarchgen()
+ideallistunit()
+ideallistunitarch()
+ideallistunitarchgen()
+ideallistunitgen()
+ideallistzstar()
+ideallistzstargen()
+ideallllred()
+idealmulred()
+idealpowred()
+idealtwoelt2()
+idmat()
+image()
+image2()
+imagecompl()
+incgam1()
+incgam2()
+incgam3()
+incgam4()
+indexrank()
+indsort()
+initalg()
+initalgred()
+initalgred2()
+initell()
+initzeta()
+integ()
+intersect()
+intgen()
+intinf()
+intopen()
+inverseimage()
+isdiagonal()
+isfund()
+isideal()
+isincl()
+isinclfast()
+isirreducible()
+isisom()
+isisomfast()
+isoncurve()
+isprincipal()
+isprincipalforce()
+isprincipalgen()
+isprincipalgenforce()
+isprincipalray()
+isprincipalraygen()
+ispsp()
+isqrt()
+isset()
+issqfree()
+isunit()
+jacobi()
+jbesselh()
+jell()
+karamul()
+kbessel()
+kbessel2()
+ker()
+keri()
+kerint()
+kerint1()
+kerint2()
+kro()
+label()
+lambdak()
+laplace()
+legendre()
+lexsort()
+lindep2()
+lll()
+lll1()
+lllgen()
+lllgram()
+lllgram1()
+lllgramgen()
+lllgramint()
+lllgramkerim()
+lllgramkerimgen()
+lllint()
+lllintpartial()
+lllkerim()
+lllkerimgen()
+lllrat()
+ln()
+localred()
+logagm()
+lseriesell()
+makebigbnf()
+mat()
+matextract()
+mathell()
+matrixqz2()
+matrixqz3()
+minideal()
+minim()
+minim2()
+mod()
+modp()
+modulargcd()
+mu()
+nfdiv()
+nfdiveuc()
+nfdivres()
+nfhermite()
+nfhermitemod()
+nfmod()
+nfmul()
+nfpow()
+nfreduce()
+nfsmith()
+nfval()
+nucomp()
+numer()
+nupow()
+o()
+ordell()
+order()
+orderell()
+ordred()
+pascal()
+perf()
+permutation()
+permutation2num()
+pf()
+phi()
+pi()
+pnqn()
+pointell()
+polint()
+polred2()
+polredabs2()
+polredabsall()
+polredabsfast()
+polredabsnored()
+polvar()
+poly()
+polylogd()
+polylogdold()
+polylogp()
+polyrev()
+polzag()
+powell()
+powrealraw()
+prec()
+primedec()
+primroot()
+principalideal()
+principalidele()
+prodinf1()
+qfi()
+qfr()
+random()
+rank()
+rayclassno()
+rayclassnolist()
+recip()
+redimag()
+redreal()
+redrealnod()
+reduceddisc()
+regula()
+reorder()
+resultant()
+resultant2()
+reverse()
+rhoreal()
+rhorealnod()
+rndtoi()
+rnfdiscf()
+rnfequation2()
+rnfhermitebasis()
+rootmod()
+rootmod2()
+rootpadic()
+roots()
+rootsof1()
+rootsold()
+rounderror()
+series()
+set()
+sigmak()
+signat()
+signunit()
+simplefactmod()
+size()
+smallbasis()
+smallbuchinit()
+smalldiscf()
+smallfact()
+smallinitell()
+smallpolred()
+smallpolred2()
+smith()
+smith2()
+smithclean()
+smithpol()
+sort()
+sqred()
+srgcd()
+sturm()
+sturmpart()
+subcyclo()
+subell()
+sumalt2()
+sumpos2()
+supplement()
+sylvestermatrix()
+taniyama()
+tchebi()
+teich()
+threetotwo()
+threetotwo2()
+torsell()
+trans()
+trunc()
+tschirnhaus()
+twototwo()
+unit()
+vec()
+vecindexsort()
+veclexsort()
+vvector()
+weipell()
+wf()
+wf2()
+zell()
+zideallog()
+zidealstar()
+zidealstarinit()
+zidealstarinitgen()
 
-p=2^64+13; T=char(Mod(4*p*y+1,y^4+1), x); discf2(T)
-getstack()
-getheap()
+box()
+color()
+cursor()
+draw()
+initrect()
+killrect()
+line()
+lines()
+move()
+ploth2()
+plothmult()
+point()
+points()
+postdraw()
+postploth()
+postploth2()
+postplothraw()
+pprint()
+pprint1()
+print()
+print1()
+rbox()
+read()
+rline()
+rlines()
+rmove()
+rpoint()
+rpoints()
+scale()
+setprecision()
+setserieslength()
+settype()
+string()
+texprint()
diff --git a/src/test/in/deriv b/src/test/in/deriv
index b86acd3..f8bbb5a 100644
--- a/src/test/in/deriv
+++ b/src/test/in/deriv
@@ -1,7 +1,11 @@
 default(realprecision,38);
 sin'(4)
+sin'(1+I)
+sin'(x)
+sin'("")
 derivnum(x=4,sin(x))
 derivnum(x=t^2+O(t^4),sin(x))
+derivnum(x=1,Pi^x)
 v=[Mod(x*y+1,x^2+1), Mod(1,3), ffgen(2^3,'t), 1+x*y+O(x^3), x/(x+y), (x^3/3+x+1) / (x^2+1)^2, [x*y], Mat(x*y)];
 {
 for (i=1,#v,
diff --git a/src/test/in/digits b/src/test/in/digits
index 95a7b0f..76dbed4 100644
--- a/src/test/in/digits
+++ b/src/test/in/digits
@@ -1,7 +1,9 @@
 binary(0)
 digits(0)
+fromdigits([])
 digits(5^100)
-check(a,b)=my(v=digits(a,b));if(subst(Pol(v),'x,b)!=a || vecmax(v)>=b,error([a,b]));
+fromdigits(vector(100,i,i%7))
+check(a,b)=my(v=digits(a,b));if(subst(Pol(v),'x,b)!=a || vecmax(v)>=b || fromdigits(v,b)!=a,error([a,b]));
 check(5^100,2)
 check(5^100,3)
 check(3^100,2^64-1)
@@ -16,3 +18,6 @@ binary(0.005)
 binary(1.1)
 binary([0,1])
 binary(I)
+vector(10, i, sumdigits(123456789, i+1))
+digits(2^128+3, 2^64)
+sumdigits(2^128+3, 2^64)
diff --git a/src/test/in/dirmul b/src/test/in/dirmul
index 701623b..22ed578 100644
--- a/src/test/in/dirmul
+++ b/src/test/in/dirmul
@@ -4,3 +4,20 @@ dirmul(vector(10,n,moebius(n)),vector(10,n,1))
 dirmul([1,2,3,4],[1,2,3,4])
 dirdiv([1,2,3,4],[1,2,3,4])
 dirdiv([1,2,3,4],2*[1,2,3,4])
+
+direuler(p=1.5,10.5,1/((1-X)*(1-p*X)))
+direuler(p=2,10,1/((1-X)*(1-p*X)), -1)
+direuler(p=2,10,1/((1-X)*(1-p*X)), 1)
+direuler(p=2,10,1/((1-X)*(1-p*X)), 2)
+direuler(p=2,10,1/((1-X)*(1-p*X)), 3.5)
+direuler(p=2,10,-1/(X^2-1))
+direuler(p=2,10,(X^2-1)/(X^3+X-1))
+
+direuler(p=I,10.5,1/((1-X)*(1-p*X)))
+direuler(p=2.5,I,1/((1-X)*(1-p*X)))
+direuler(p=2,10,1/((1-X)*(1-p*X)), I)
+direuler(p=2,1,1/((1-X)*(1-p*X)), 1)
+direuler(p=2,2,1/((1-X)*(1-p*X)), 2)
+
+direuler(p=2,10,1/2)
+direuler(p=2,10,1/(x-2))
diff --git a/src/test/in/div b/src/test/in/div
index baefa9b..6434bf4 100644
--- a/src/test/in/div
+++ b/src/test/in/div
@@ -35,3 +35,8 @@ divrem(1,"a")
 (5/3) \/ 1
 
 floor((x^2+1)/x)
+
+[]/0
+[]~/0
+[;]/0
+[1]/0
diff --git a/src/test/in/ell b/src/test/in/ell
index 31e13b1..b0f302f 100644
--- a/src/test/in/ell
+++ b/src/test/in/ell
@@ -47,14 +47,6 @@ elllog(E,P,G)
 
 ellorder(ellinit([0,2],1),[-1,-1]*Mod(1,997))
 
-E = ellinit([-2147484185^2,0]);
-elltors(E)
-ellorder(E, [0,0])
-ellorder(E, [2147484185, 0])
-ellorder(E, [2147484185/3, 1/11])
-E = ellinit([1,1]); P = [72, 611];
-ellorder (E, ellmul(E, P, 20))
-
 ellinit([a1,a2,a3,a4,a6]*Mod(1,5));
 ellinit([a1,a2,a3,a4,a6]);
 ellinit(ellfromj(0)).j
@@ -68,8 +60,26 @@ ellinit(ellfromj(Mod(0,3))).j
 ellinit(ellfromj(j*Mod(1,3))).j
 a=ffgen(2^5,'a);ellinit(ellfromj(a)).j
 a=ffgen(3^5,'a);ellinit(ellfromj(a)).j
-elldivpol(ellinit([1,2,3,5,7]),4)
-elldivpol(ellinit([0,0,0,0,1]),8)
+e = ellinit([1,2,3,5,7]);
+elldivpol(e,4)
+ellxn(e,0)
+ellxn(e,1)
+ellxn(e,2)
+ellxn(e,4)
+ellxn(e,5)
+P=[-1,1]; Q=ellmul(e,P,20);
+if (ellisdivisible(e,Q,0,&A), A)
+if (ellisdivisible(e,[0],0,&A), A)
+if (ellisdivisible(e,Q,1,&A), A)
+if (ellisdivisible(e,Q,20,&A), A)
+if (ellisdivisible(e,Q,-20,&A), A)
+if (ellisdivisible(e,Q,2,&A), A)
+if (ellisdivisible(e,Q,5,&A), A)
+if (ellisdivisible(e,Q, ellxn(e,5), &A), A)
+if (ellisdivisible(e,Q,11,&A), A)
+if (ellisdivisible(e,Q,22,&A), A)
+e = ellinit([0,1]);
+elldivpol(e,8)
 
 e = ellinit([1.,2,3,4,5]);
 e.eta
@@ -122,8 +132,8 @@ ellmul(ellinit([3,0]), [1,2], -quadgen(-4))
 logsigma(e,z='x)=if(type(z) != "t_POL" && type(z) != "t_SER", ellsigma(e,z,1));
 v = [ellwp,ellzeta,ellsigma,logsigma];
 e = ellinit([1,1]);
-w = ellperiods([1,I])
-w2 = ellperiods([1,I], 1)
+w = ellperiods([1,I/2])
+w2 = ellperiods([1,I/2], 1)
 u = [e,w,w2];
 {
 for (i = 1, #v,
@@ -141,7 +151,7 @@ for (i = 1, #v,
 }
 elleta(e)
 elleta([1,I])
-v = [x->elleisnum(x,2),x->elleisnum(x,4,1),x->elleisnum(x,6,1),x->elleisnum(x,10)];
+v = [x->elleisnum(x,2),x->real(elleisnum(x,4,1)),x->real(elleisnum(x,6,1)),x->real(elleisnum(x,10))];
 {
 for (i = 1, #v,
   my(f = v[i]);
@@ -162,27 +172,7 @@ ellztopoint(e,-2.5261979245524788020279452840822073870+0.E-36*I)
 \\ #1308
 ellinit([108/91,11664/8281,-6561/8281,708588/753571,-14348907/68574961]).disc
 
-do(e)=elltors(ellinit(e));
-do([0, -1, 1, -7820, -263580])
-do([1, 0, 1, -171, -874])
-do([0, 1, 1, -9, -15])
-do([1, 1, 1, -80, 242])
-do([0, -1, 1, -10, -20])
-do([1, 0, 1, 4, -6])
-do([1, -1, 1, -3, 3])
-do([1, 1, 1, 35, -28])
-do([1, -1, 1, -14, 29])
-do([1, 0, 0, -45, 81])
-do([1, -1, 1, -122, 1721])
-
-do([1, 1, 1, -135, -660])
-do([1, 1, 1, -10, -10])
-do([1, 0, 1, -19, 26])
-do([1, 0, 0, -1070, 7812])
-do([1,0,0,-372368141774940800,87459461608665181808640000])
-do([0,706607569223786457,0,-1866575649655837263252847197205171425,-1298198297451307472292414787720779720378300792679274425])
-
-e=ellinit([1,3.+I]); x=1/2; y=ellordinate(e,x)[1];
+e=ellinit([1,3.+I]); x=1/2+I; y=ellordinate(e,x)[1];
 ellztopoint(e,ellpointtoz(e,[x,y]))
 e=ellinit([0,-1,1,0,0], O(11^5));
 ellpointtoz(e,[0,0])
@@ -232,7 +222,7 @@ ellcard(ellinit([1,2,3,4,5], p))
 E=ellinit([625,15625]);
 elllocalred(E,5)
 ellisoncurve(E,[0.,125.])
-ellisoncurve(E,[0.,125+1e-50])
+ellisoncurve(E,[1e-50,125+1e-50])
 elladd(E,[0.,125.],[0.,125+1e-38])
 iferr(ellmul([0,1,0,2,-15],[2,1],5),E,E)
 x='x;
@@ -255,6 +245,8 @@ E = ellinit([0,0,0,-82,0]);
 ellrootno(E,2)
 ellrootno(E)
 ellrootno(E,2)
+E=ellinit([0,20,0,-352,512]);
+ellrootno(E,2)
 
 E=ellinit([0,0,0,Mod(x,x^2+5),0]);
 ellwp(E)
@@ -269,3 +261,22 @@ ellsigma(E)
 \\#1558
 ellap(ellinit([-1137195,489565862]),2038074751)
 ellap(ellinit([582304190,64196421]),2147438927)
+e=ellinit([0,-1,1,-2,2]); P=[2,-2]; ellnonsingularmultiple(e, P)
+e=ellinit([-111,214]); P=[35,-198]; v = [4*3,12,214,12];
+e=ellchangecurve(e,v); P=ellchangepoint(P,v);
+ellnonsingularmultiple(e,P)
+e=ellinit([0,-1,1,-2,2]);
+test(f)=print(f(e,,'t)); print(f(e,5)); print(f(e,5,'t));
+F=[ellformalw,ellformalpoint,ellformaldifferential,ellformallog,ellformalexp];
+for(i=1,#F,print(F[i]);test(F[i]));
+ellformalw(e,0)
+ellformalw(e,-1)
+
+\\#1637
+U=[-245369975623514803521420211420402474815373720177518420696215292670924086780233779586506792145074717/4069861969699146045958032034788970995470603578576,-696053034387689435413673877713244121475782562610666903528251447608130654196417305610237634015759861/4069861969699146045958032034788970995470603578576,-49356694805693369953216822105035107974083562942605713355717183776373331122267882948881129025418396548321363993080002121985116427859996985649385099335/406986196969914604595803203478897099 [...]
+E=ellinit(U);
+P=[283188771261789732541662405743402980051199109235,39175522019721182331498476245534716069785193060995];
+ellheight(E,P)
+
+\\#1648
+ellinit([0,0,0,0,1]).a1
diff --git a/src/test/in/ellanal b/src/test/in/ellanal
index 4d0cae6..eb11870 100644
--- a/src/test/in/ellanal
+++ b/src/test/in/ellanal
@@ -13,6 +13,16 @@ he([-157^2,0])
 he([0,0,-9/484,0,-27/234256])
 getheap()[1]
 
-allocatemem(30000000);
 E=ellinit([0,-1437004800,0,458885065605120000,0]);
 ellglobalred(E); ellheegner(E)
+
+L = ellinit([0,0,1,7,6]);
+ellL1(L)
+ellL1(L,1)
+ellL1(L,3)
+ellL1(ellinit([0,1,1,-2,0]),2)
+default(realprecision,115);
+ellL1(L)
+ellL1(L,1)
+ellL1(L,3)
+ellL1(ellinit([0,1,1,-2,0]),2)
diff --git a/src/test/in/ellff b/src/test/in/ellff
index 4594564..18cb6f1 100644
--- a/src/test/in/ellff
+++ b/src/test/in/ellff
@@ -20,6 +20,7 @@ test(p,n=0,v='a,w=1)=
 test(2);
 test(2,78);
 test(2,100);
+test(2,255);
 test(2,1,,0);
 test(2,2,,0);
 test(2,4,,0);
@@ -34,6 +35,8 @@ test(5,50);
 test(7,3);
 test(7,51);
 test(11,2);
+test(11,18);
+test(11,19,,5);
 test(13,41);
 test(17,2);
 test(1009,3);
@@ -44,6 +47,12 @@ test(41);
 test(1073741827);
 test(nextprime(2^65),2);
 
+setrand(1);
+p=18446744073709551557;
+e=ellinit([3,3],p);
+g=ellgenerators(e)
+ellorder(e,g[1])
+
 a=ffgen(101^3,'a);
 E=ellinit([1,3],a); E.j
 E.disc
@@ -83,7 +92,7 @@ checkt(p,n,f,B=100)=
     until(b,b=random(a));
     E=ellinit(if(f==0,[0,b],f==1,[b,0],[b^2,b^3]));
     if(#E==0,next);
-    N=ellcard(ellinit(E,a));
+    N=ellcard(E);
     if(#ellmul(E,random(E),N)>1,error([p,n,f],b)));
 }
 checkt(3,5,0);
diff --git a/src/test/in/elliptic b/src/test/in/elliptic
index 2888daf..49d1a22 100644
--- a/src/test/in/elliptic
+++ b/src/test/in/elliptic
@@ -1,4 +1,4 @@
-HEAP=[77, if(precision(1.)==38,5279,5458)];
+HEAP=[75, if(precision(1.)==38,5437,5660)];
 default(realprecision,154); Pi; default(realprecision,38);
 \e
 ellinit([-1,0])
@@ -12,7 +12,7 @@ elladd(acurve,apoint,apoint)
 ellak(acurve,1000000007)
 ellan(acurve,100)
 ellap(acurve,10007)
-deu=direuler(p=2,100,1/(1-ellap(acurve,p)*x+if(acurve[12]%p,p,0)*x^2))
+deu=direuler(p=2,100,1/(1-ellap(acurve,p)*x+if(acurve.disc%p,p,0)*x^2))
 ellan(acurve,100)==deu
 ellisoncurve(acurve,apoint)
 acurve=ellchangecurve(acurve,[-1,1,2,3])
@@ -20,7 +20,6 @@ apoint=ellchangepoint(apoint,[-1,1,2,3])
 ellisoncurve(acurve,apoint)
 ellglobalred(acurve)
 ellheight(acurve,apoint)
-ellheight(acurve,apoint,1)
 ellordinate(acurve,1)
 ellpointtoz(acurve,apoint)
 ellztopoint(acurve,%)
@@ -40,8 +39,8 @@ tcurve=ellinit([1,0,1,-19,26]);
 ellorder(tcurve,[1,2])
 elltors(tcurve)
 \\
-mcurve=ellinit([-17,0])
-mpoints=[[-1,4],[-4,2]]~
+mcurve=ellinit([-17,0]);
+mpoints=[[-1,4],[-4,2]]~;
 mhbi=ellbil(mcurve,mpoints,[9,24])
 ma=ellheightmatrix(mcurve,mpoints)
 matsolve(ma,mhbi)
diff --git a/src/test/in/ellisogeny b/src/test/in/ellisogeny
new file mode 100644
index 0000000..f0d419a
--- /dev/null
+++ b/src/test/in/ellisogeny
@@ -0,0 +1,286 @@
+x; y; t;
+
+ellhyperellipticpolynomials(E, x = 'x) =
+{ my (one = E.j^0);
+  x *= one;
+  return([x^3 + E.a2 * x^2 + E.a4 * x + E.a6, E.a1 * x + E.a3]);
+}
+
+elldefiningequation(E, x = 'x, y = 'y) =
+{ my (one = E.j^0);
+  x *= one;
+  y *= one;
+  my (eqns = ellhyperellipticpolynomials(E, x));
+  return(y^2 + eqns[2]*y - eqns[1]);
+}
+
+ellbasechar(E) = iferr(E.p, unused_param, 0);
+
+ffone(p, n = 1, v = 't) = ffgen(p^n, v)^0;
+
+num_isog(E, isog) =
+{ my([x,y,d] = isog);
+  my(d2 = d^2, d3 = d2*d, d4 = d2^2, d6 = d3^2);
+  ((x + E.a2*d2)*x + E.a4*d4)*x + E.a6*d6 - y*(y + E.a1*d*x + d3*E.a3);
+}
+
+isog_satisfies_eqns(E, F, isog) =
+{
+  if (Mod(num_isog(F,isog), elldefiningequation(E)) != 0,
+    error("Isogeny polynomials don't satisfy the curve equations"));
+}
+
+kernel_poly_from_generator(E, P, ord = 0, x = 'x, check = 1) =
+{
+  if (check && ! ellisoncurve(E, P),
+      error("Given point is not on given curve."));
+  if (!ord, ord = ellorder(E, P));
+
+  my (one = E.j^0, rP = P, res = Pol([one], x));
+  for (r = 1, ord \ 2,
+       res *= x - rP[1];
+       rP = elladd(E, rP, P));
+  res;
+}
+
+
+check_ker_pol_from_gen() =
+{
+  my (x = 'x, one = ffone(101));
+  my (data = [
+              [1, [1, 1], [0], 1, Pol([1], x)],
+              [one, [37, 42], [85, 0], 2, x + 16],
+              [one, [37, 42], [89, 71], 3, x + 12],
+              [one, [37, 42], [21, 9], 5, x^2 + 12*x + 14],
+              [one, [37, 42], [58, 59], 18, x^9 + 100*x^8 + 68*x^7 + 59*x^6 + 49*x^5 + 86*x^4 + 98*x^3 + 12*x^2 + 70*x + 56]
+             ]);
+  for (i = 1, #data,
+    my ([rg_one, ainvs, pt, ord, expected] = data[i],
+        E = ellinit(ainvs * rg_one));
+    pt *= rg_one;
+    my (res = kernel_poly_from_generator(E, pt, ord, x));
+    if (res != expected || Mod(elldivpol(E, ord, x), res) != 0,
+        error("kernel polynomial is incorrect")));
+}
+
+check_data(E, P, ord) = {
+  my (p = ellbasechar(E), M = [7, 13, 3, 4]);
+  if (p != 0,
+    my (n = (E.j).f);
+    t = ffgen(p^n, 't);
+    if (
+      p == 2,
+      M = [t, t+1, t, 1] * t^0,
+
+      p == 3,
+      M = [t, t+1, 2*t, t+2] * t^0));
+  E = ellchangecurve(E, M);
+  P = ellchangepoint(P, M);
+  if (!ellisoncurve(E, P) || ellorder(E, P) != ord,
+      error("Broken data: ", ord, "-torsion"));
+  my (F, G, FF, GG, ker);
+  F = ellisogeny(E, P);
+  FF = ellisogeny(E, P, 1);
+  if (F[1] != FF,
+      error("Got different curve when only computing image"));
+  ker = kernel_poly_from_generator(E, P, ord, 'x);
+  G = ellisogeny(E, ker);
+  GG = ellisogeny(E, ker, 1);
+  if (G[1] != GG,
+      error("Got different curve when only computing image"));
+  if (F[1][1..5] != G[1][1..5],
+      error("Different curves obtained for same kernel"));
+  if (F[2] != G[2],
+      error("Different isogenies obtained for same kernel"));
+  isog_satisfies_eqns(E, F[1], F[2]);
+}
+
+tatecrv(b, c, p = 0, n = 1) =
+{ my (one = if (p == 0, 1, ffone(p, n)));
+  ellinit([1 - c, -b, -b, 0, 0] * one);
+}
+
+do_tate(b, c, ord, p = 0, n = 1) =
+{ my (E, P = [0, 0], t, M = Vec([1,0,0,1]));
+  E = tatecrv(b, c, p, n);
+  check_data(E, P, ord);
+}
+
+check_apply(E, ker, P, fP) =
+{ my ([F, f] = ellisogeny(E, ker));
+  if (ellisogenyapply(f, P) != fP, error("Wrong image of point"));
+}
+
+check_compose() =
+{ my (one = ffone(101),
+      E = ellinit([6, 53, 85, 32, 34] * one),
+      P = [84, 71] * one, \\ order 5
+      [F, f] = ellisogeny(E, P),
+      Q = [89, 44] * one, \\ order 2
+      [G, g] = ellisogeny(ellinit(F), Q),
+      gof = ellisogenyapply(g, f));
+  isog_satisfies_eqns(E, ellinit(G), gof);
+}
+
+check_prio_err(E, ker, var1, var2, tst, msg) =
+{
+  my (got_err = 0);
+  iferr(ellisogeny(E, ker, 0, var1, var2),
+        err, got_err = 1,
+        errname(err) == "e_PRIORITY"
+          && variable(component(err, 2)) == tst);
+  if (! got_err, error(msg));
+}
+
+check_errs() =
+{ my (E = ellinit([8, 5]), P = [0, 0], got_err = 0);
+  \\ ellisoncurve(E, P) = 0
+  iferr(ellisogeny(E, P),
+        err, got_err = 1,
+        errname(err) == "e_DOMAIN"
+          && component(err, 4) == E && component(err, 5) == P);
+  if (! got_err, error("No error when P not on E"));
+
+  my (var1 = 'var1, var2 = 'var2);
+  check_prio_err(E, P, var2, var1, 'var2, "No error with bad variable order");
+
+  iferr(ellisogeny(E, "banana bread"),
+        err, got_err = 1,
+        errname(err) == "e_TYPE"
+          && component(err, 2) == "banana bread");
+  if (! got_err, error("No error with bad kernel type"));
+
+  check_prio_err(E, ['pvx, 0], 'x, 'g1, 'pvx,
+                 "No error with bad x-point base field variable order");
+  check_prio_err(E, [0, 'pvy], 'x, 'g2, 'pvy,
+                 "No error with bad y-point base field variable order");
+  check_prio_err(E, 'x * 'asdf, 'x, 'g3, 'asdf,
+                 "No error with bad kernel variable order");
+  check_prio_err(ellinit(['a4, 'a6]), [0], 'x, 'g4, 'a4,
+                 "No error with bad j-invariant variable order");
+
+  my (t = ffgen(2^2, 't),
+      one = t^0,
+      E = ellinit([t, t + 1, 0, t, t] * one),
+      div2 = elldivpol(E, 2));
+  div2 /= polcoeff(div2, poldegree(div2));
+  iferr(ellisogeny(E, div2),
+        err, got_err = 1,
+        errname(err) == "e_DOMAIN"
+          && component(err, 4) == E && component(err, 5) == div2);
+  if (! got_err,
+      error("No error when quotienting E by E[2] in char 2"));
+}
+
+check_ker_pol_from_gen();
+check_compose();
+check_errs();
+P = [0, 0];
+E = ellinit([0, 3, 0, 7, 0]);
+\\ Doing "1-torsion"
+check_data(E, [0], 1);
+check_apply(E, [0], P, P);
+check_apply(E, P, [0], [0]);
+
+\\ Doing 2-torsion
+check_data(E, P, 2);
+one = ffone(1009);
+E = ellinit([0, 3, 0, 7, 0] * one);
+check_data(E, [0], 1);
+check_apply(E, [0], P, P);
+check_data(E, P * one, 2);
+check_apply(E, P, P, [0]);
+in = [149, 125] * one; out = [833, 506] * one;
+check_apply(E, P, in, out);
+check_apply(E, P, [0], [0]);
+
+\\ Doing 3-torsion...
+E = ellinit([1, 0, 1, 0, 0]);
+check_data(E, P, 3);
+E = ellinit([1, 0, 1, 0, 0] * ffone(1009));
+check_data(E, P, 3);
+
+t = ffgen(2^4, 't); one = t^0;
+E = ellinit([t^3+t^2+1,t^3+t+1,t^3+t^2+t+1,t^3+t+1,t^3+t+1]*one);
+Q = [t^2+t+1,t^3+t^2+1]*one;
+check_data(E, Q, 3);
+Q = [t^2+t,t^3+t^2+1]*one;
+check_data(E, Q, 2);
+Q = [t^3+t,t^3+t^2];
+check_data(E, Q, 6);
+
+t = ffgen(2^5, 't);
+E = ellinit([t^3+t^2+1,t^4+t^3+t,t^4+1,t^3+1,t^2+t]);
+Q = [t^4+t^3+t^2,t^3+t^2];
+check_data(E, Q, 3);
+
+t = ffgen(3^2, 't);
+one = t^0;
+Q = [t, 1] * one;
+E = ellinit([2,2*t,t+2,2*t,2*t+1]*one);
+check_data(E, Q, 3);
+
+\\ Quotient by full 2-torsion.  Arbitrary E here; just need char(k) != 2.
+E = ellinit([0, 3, 0, 7, 0] * ffone(1009));
+ker = elldivpol(E, 2) * E.j^0;
+F = ellisogeny(E, ker);
+FF = ellisogeny(E, ker, 1);
+if (F[1] != FF, error("Got different curve when only computing image"));
+isog_satisfies_eqns(E, F[1], F[2]);
+
+\\ See Kubert 1976 for why all this works.  Data was selected randomly.
+\\ Doing 4-torsion...
+b = -128/7; c = 0;
+do_tate(b, c, 4);
+
+\\ Doing 5-torsion...
+b = 121/13; c = b;
+do_tate(b, c, 5);
+do_tate(b, c, 5, 2, 7);
+
+\\ Doing 6-torsion...
+c = -7/2; b = c + c^2;
+do_tate(b, c, 6);
+do_tate(b, c, 6, 3, 3);
+
+\\ Doing 7-torsion...
+d = 21/11; c = d^2 - d; b = d * c;
+do_tate(b, c, 7);
+t = ffgen(2^3, 't);
+d = t; c = d^2 - d; b = d * c;
+do_tate(b, c, 7, 2, 3);
+
+\\ We do these two over a finite field to (1) avoid stack overflow
+\\ and (2) to make them run a bit faster.
+
+\\ Doing 8-torsion...
+d = 11/7; b = (2 * d - 1) * (d - 1); c = b/d;
+do_tate(b, c, 8);
+do_tate(b, c, 8, 1009);
+t = ffgen(2^3, 't);
+d = t; b = (2 * d - 1) * (d - 1); c = b/d;
+do_tate(b, c, 8, 2, 3);
+
+\\ Doing 9-torsion...
+f = 1/7; d = f * (f - 1) + 1; c = f * (d - 1); b = c * d;
+do_tate(b, c, 9);
+do_tate(b, c, 9, 61, 2);
+t = ffgen(3^3, 't);
+f = t; d = f * (f - 1) + 1; c = f * (d - 1); b = c * d;
+do_tate(b, c, 9, 3, 3);
+
+\\ Francois Brunault's example
+E = ellinit([0, -1, 1, 0, 0]);
+z = Mod('t, polcyclo(11, 't));
+a = z + 1/z;
+xP = a*(a - 1)*(a + 2);
+\\ [25]P = 0 on E.
+P = [xP, a*xP];
+F = ellisogeny(E, P, 0, 'x, 'y);
+G = ellisogeny(E, kernel_poly_from_generator(E, P, 25, 'x), 0, 'x, 'y);
+if (F[1] != G[1], error("Different curves obtained for same kernel"));
+if (F[2] != G[2], error("Different isogenies obtained for same kernel"));
+isog_satisfies_eqns(E, F[1], F[2]);
+
+ellisogenyapply(x,x)
+ellisogenyapply([f,g,h],1)
diff --git a/src/test/in/ellissupersingular b/src/test/in/ellissupersingular
new file mode 100644
index 0000000..d5ae41c
--- /dev/null
+++ b/src/test/in/ellissupersingular
@@ -0,0 +1,41 @@
+{
+p = 7;
+e = 5;
+q = p^e;
+g = ffprimroot(ffgen(q));
+S = [g^n | n <- [1 .. q - 1], ellissupersingular(g^n)];
+if (S != [6] || ellissupersingular(0 * g^0), error("Bad result"));
+
+p = 7;
+e = 4;
+q = p^e;
+g = ffprimroot(ffgen(q));
+S = [g^n | n <- [1 .. q - 1], ellissupersingular(g^n)];
+if (S != [6] || ellissupersingular(0 * g^0), error("Bad result"));
+S = [g^n | n <- [1 .. q - 1], ellissupersingular(ellinit(ellfromj(g^n)))];
+if (S != [6] || ellissupersingular(0 * g^0), error("Bad result"));
+
+p = 43;
+one = Mod(1, p);
+S = [lift(j) | j <- [0 .. p - 1] * one, ellissupersingular(j)];
+if (S != [8, 41], error("Bad result"));
+
+e = 2;
+q = p^e;
+T = ffgen(q, 't);
+one = T^0;
+g = (28*T + 6) * one; \\ Fix a primitive root so we always get the same ordering in S
+S = [g^n | n <- [1 .. q - 1], ellissupersingular(g^n)];
+if (S != [41, 8, 38*T + 31, 5*T + 36]*one, error("Bad result"));
+
+if([j | p<-primes(5);j<-[0..p-1],ellissupersingular(Mod(j,p))]!=[0,0,0,6,0,1],
+  error("Bad result"));
+
+E=ellinit([1,0,1,-6,4]);
+if([ellissupersingular(E,p)|p<-primes(5)]!=[0,0,1,0,0], error("Bad result"));
+
+badin = "my spoon is too big";
+iferr(ellissupersingular(badin), err, got_err = 1,
+      errname(err) == "e_TYPE" && component(err, 2) == badin);
+if ( ! got_err, error("Didn't catch type error"));
+}
diff --git a/src/test/in/ellnf b/src/test/in/ellnf
new file mode 100644
index 0000000..1b33243
--- /dev/null
+++ b/src/test/in/ellnf
@@ -0,0 +1,32 @@
+\\package:elldata
+K=nfinit(t^3-2);
+e=ellinit([t+1,t^2 - (t^3+(t+1)*t)], K);
+P=[t,t];
+ellisoncurve(e, P)
+elladd(e, P,P)
+ellmul(e, P,3)
+ellordinate(e, t)
+ellordinate(e, t+1)
+elldivpol(e, 3)
+ellfromj(Mod(t,t^3-2))
+ellinit(e, idealprimedec(K,2)[1])
+e5 = ellinit(e, idealprimedec(K,5)[1])
+
+{
+  K = nfinit(t);
+  forell(E, 1, 1000,
+    my(e,N,f,P,loc1,loc2);
+    e = ellinit(E[2],1);
+    eK= ellinit(E[2],K);
+    N = ellconvertname(E[1])[1];
+    f = factor(N)[,1];
+    for(i=1, #f,
+      my(p = f[i]);
+      if(p<=3, next);
+      P=idealprimedec(K,p)[1];
+      A=elllocalred(e,P.p);
+      B=elllocalred(eK,P);
+      if(A!=B, error(E[2]))
+    )
+  )
+}
diff --git a/src/test/in/ellpadic b/src/test/in/ellpadic
new file mode 100644
index 0000000..2a1aab2
--- /dev/null
+++ b/src/test/in/ellpadic
@@ -0,0 +1,81 @@
+default(parisize,"40M");
+
+e=ellinit([1,-1,1,-1,-14]);
+E=ellinit([0,0,0,-e.c4/48,-e.c6/864]);
+P=[1,-1/4;0,1];
+{
+  forprime(p=3,40,if(p==17,next);
+  A=ellpadicfrobenius(e,p,10);
+  B=ellpadicfrobenius(E,p,10);
+  if(P*B!=A*P,error(p)));
+}
+
+E=ellinit([1,-1,1,0,0]);P=[0,0];
+ellpadicheight(E,2,4, P)
+ellpadicheight(E,3,4, P)
+ellpadicheight(E,5,4, P)
+E=ellinit([0,-1,1,-10,-20]);P=[5,5];
+ellpadicheight(E,19,6, P)
+ellpadicheight(E,19,0, P)
+ellpadicL(E,2,5)
+
+E=ellinit([0,1,1,-9,-15]);
+ellpadicL(E,2,5)
+
+E=ellinit([0,0,1,-4,2]);P=[-2,1];
+ellpadicheight(E,3,5, P)
+P2 = ellmul(E,P,2);
+ellpadiclog(E,3,5,P)
+ellpadiclog(E,3,5,P2)
+E=ellinit([0,0,1,-7,6]);
+P=[-2,3]; P2=ellmul(E,P,2);
+Q=[-1,3]; Q2=ellmul(E,Q,2);
+R=[0,2];
+ellpadicheight(E,2,5, P,Q2)
+ellpadicheight(E,2,5, P2,Q)
+ellpadicheightmatrix(E,5,5, [P,Q,R])
+ellpadicheight(E,[3,[1,2]],5, P)
+ellpadicheight(E,[3,[1,2]],5, P,Q)
+M=ellpadicheightmatrix(E,[5,[1,0]],5, [P,Q,R])
+N=ellpadicheightmatrix(E,[5,[0,1]],5, [P,Q,R])
+matdet(M)
+matdet(N)
+
+E=ellinit([-577/48,14689/864]);
+ellpadics2(E,43,6)
+E=ellinit([1,0,1,-460,-3830]);
+ellpadics2(E,5,6)
+E=ellinit([0,0,1,-1,0]);
+ellpadics2(E,5,6)
+
+E=ellinit([1, -1, 1, 0, 0]);
+ellpadicfrobenius(E,5,7)
+E=ellinit([0,0,1,-4,2]);
+ellpadicfrobenius(E,3,5)
+
+e=ellinit([1,-1,1,-1,-14]);p=3;\\supersingular
+L=ellpadicL(e,p,4)
+F=[0,-p;1,ellap(e,p)];\\Frobeniusmatrixinthebasis(omega,F(omega)
+Lf=(1-p^{-1}*F)^-2*L~
+Lf/bestappr(ellL1(e,0)/e.omega[1])
+
+p=5;\\ordinary
+L=ellpadicL(e,p,4)
+al=polrootspadic(x^2-ellap(e,p)*x+p,p,7)[2];
+(1-al^(-1))^(-2)*L/bestappr(ellL1(e,0)/e.omega[1])
+
+e=ellinit([-4831,-129242]);p=3;\\supersingular
+L=ellpadicL(e,p,4);
+F=[0,-p;1,ellap(e,p)];
+Lf=(1-p^{-1}*F)^-2*L~;
+Lf/bestappr(ellL1(e,0)/e.omega[1])
+
+e=ellinit([1,-1,1,-3,3]);p=3;
+L=ellpadicL(e,p,4);
+F=[0,-p;1,ellap(e,p)];
+Lf=(1-p^{-1}*F)^-2*L~;
+Lf/bestappr(ellL1(e,0)/e.omega[1])
+
+e=ellinit([0,0,1,-4,2]);p=3;n=3;
+ellpadicL(e,p,n)
+
diff --git a/src/test/in/ellsea b/src/test/in/ellsea
index d5f696e..b7aaced 100644
--- a/src/test/in/ellsea
+++ b/src/test/in/ellsea
@@ -19,3 +19,14 @@ v=[[202600005603433095160409308644759862837,254968527823254532259731428909096005
 [18446744073709551629,1,42]];
 }
 for(i=1,#v, do(i,v[i]));
+J=
+{[Mod(139969198258936384621998533779, 896615193897208487551655423041),
+   Mod(153550450851144056623726364403,1160030981035862964864325445299),
+   Mod(386229222639189135614980939195,529656639561667839197968630433),
+   Mod(543979953519664739130128566041,817701636704151811034504702087),
+   Mod(80210534001353032236065226821, 983440823277044783790077069059),
+   Mod(1293115044598381293398949316, 383857664397975779060725841281)];
+}
+for(i=1,#J, print(i,":",ellcard(ellinit(ellfromj(J[i])))))
+g=ffgen(nextprime(2^32)^2);E=ellinit([g,3]);ellap(E)
+b=ffgen(37^18,'b);E=ellinit(ellfromj(b));ellap(E)
diff --git a/src/test/in/elltors b/src/test/in/elltors
new file mode 100644
index 0000000..0666838
--- /dev/null
+++ b/src/test/in/elltors
@@ -0,0 +1,123 @@
+do(e)=elltors(ellinit(e));
+do([0, -1, 1, -7820, -263580])
+do([1, 0, 1, -171, -874])
+do([0, 1, 1, -9, -15])
+do([1, 1, 1, -80, 242])
+do([0, -1, 1, -10, -20])
+do([1, 0, 1, 4, -6])
+do([1, -1, 1, -3, 3])
+do([1, 1, 1, 35, -28])
+do([1, -1, 1, -14, 29])
+do([1, 0, 0, -45, 81])
+do([1, -1, 1, -122, 1721])
+
+do([1, 1, 1, -135, -660])
+do([1, 1, 1, -10, -10])
+do([1, 0, 1, -19, 26])
+do([1, 0, 0, -1070, 7812])
+do([1,0,0,-372368141774940800,87459461608665181808640000])
+do([0,706607569223786457,0,-1866575649655837263252847197205171425,-1298198297451307472292414787720779720378300792679274425])
+
+K=nfinit(t^2-5);
+s=Mod(t,K.pol);
+E=ellinit([-31/60*s-1/12, -11/9*s-8/3, -11/9*s-8/3, 0, 0], K);
+T=elltors(E)
+ellorder(E,T.gen[1])
+ellorder(E,T.gen[2])
+
+K=nfinit(t^4+18*t^2-324*t-27);E=ellinit([1,3],K);
+elltors(E)
+
+do(v,K)=
+{
+  my(e=ellinit(v,K), t=elltors(e));
+  if (apply(p->ellorder(e,p),t.gen) != t.cyc, error(v));
+  t;
+}
+
+
+K=nfinit(t^8-998*t^6+44424*t^4+5106934*t^2+126046063);
+do([1,3],K)
+
+K=nfinit(polcyclo(11,t));
+do([0,-1,1,0,0],K)
+
+\\ [11]
+K = nfinit(y^2+7);
+a1=-209*y-579;
+a2=26752*y+147840;
+a3=-10486784*y-57953280;
+do([a1,a2,a3,0,0],K)
+
+\\ [15]
+a1=(-2*y+15);
+a2=26*y-14;
+a3=26*y-14;
+do([a1,a2,a3,0,0],K)
+
+\\ [10,2]
+a2=-261214369/131072;
+a4=75626226572068161/68719476736;
+K=nfinit(y^2+2);
+do([0,a2,0,a4,0],K)
+
+\\ [12,2]
+K=nfinit(y^2-13);
+a2=(-4289032*y+15673889)/65536
+a4=(-32028469200*y+115490749725)/4194304
+do([0,a2,0,a4,0],K)
+
+\\ [14]
+K=nfinit(y^2+11);
+a1=-2601888534886283704*y+154252733407512581857;
+a2=-313766195076761969526071169866614175160*y+1735663223649526033628839600302712469280
+a3=-43286504429925775681153399339981518914403432663035092419000*y+239448337641930912934754848966237361950084593095601008052000;
+do([a1,a2,a3,0,0],K)
+
+\\ [16,2]
+K=nfinit(y^4+2002*y^2+116281);
+a2=12974641/13176900;
+a4=16/14641;
+do([0,a2,0,a4,0],K)
+
+\\ [3,3]
+K=nfinit(y^2+3);
+do([1,-1,0,12,8],K)
+
+\\ [20]
+K=nfinit(y^3-y^2-2*y-2);
+a=(-5*y^2-y)/2;
+b=-14*y^2-12*y-8;
+do([a,b,b,0,0],K)
+
+\\ [6,6]
+K=nfinit(y^4+5*y^2+1);
+a=9/8;
+b=7/64;
+do([a,b,b,0,0],K)
+
+\\ [8,4]
+K=nfinit(y^4+541*y^2+72900);
+a=431/690;
+b=-259/529;
+do([a,b,b,0,0],K)
+
+\\ [8,8]
+K=nfinit(y^16-8*y^15+36*y^14-104*y^13+220*y^12-368*y^11+516*y^10-624*y^9+664*y^8-624*y^7+516*y^6-368*y^5+220*y^4-104*y^3+36*y^2-8*y+1);
+do([-1,0],K)
+
+\\ [9,3]
+K=nfinit(x^6+3);
+do([1,-1,1,-14,29],K)
+
+E = ellinit([-2147484185^2,0]);
+elltors(E)
+ellorder(E, [0,0])
+ellorder(E, [2147484185, 0])
+ellorder(E, [2147484185/3, 1/11])
+E = ellinit([1,1]); P = [72, 611];
+ellorder (E, ellmul(E, P, 20))
+
+\\#1660
+do([2,x],nfinit(x^2+2))
+
diff --git a/src/test/in/ellweilpairing b/src/test/in/ellweilpairing
index 67e3b6b..52eed98 100644
--- a/src/test/in/ellweilpairing
+++ b/src/test/in/ellweilpairing
@@ -59,3 +59,4 @@ test(p) =
 }
 test(3);
 test(5);
+p=nextprime(2^65);a=ffgen(p^2,'a);ellgroup(ellinit([a^0,0]))
diff --git a/src/test/in/equal b/src/test/in/equal
index aa1411e..d16c171 100644
--- a/src/test/in/equal
+++ b/src/test/in/equal
@@ -22,3 +22,33 @@ quadgen(5)==quadgen(13)
 L=List([1,2]);
 [L===List([]), L===List([2,1]), L===List([1]), L===L]
 [[]==0, []~==0]
+oo===oo
+-oo===-oo
+oo===-oo
+[I===1+I, I===I]
+w=quadgen(5);
+[w===1+w, w===w]
+w==w
+quadgen(5)===quadgen(13)
+
+f()=1;
+g()=0;
+[f==g,f==f]
+[f===g,f===f]
+
+List()==List()
+List(1)==List()
+List()==List(1)
+List(1)==List(1)
+List(2)==List(1)
+
+g=ffgen(2^3);
+h=ffgen(3^3);
+q=quadgen(5);
+v=[g,g^0,-g^0,h,h^0,-h^0,\
+ q,1+0*q,-1+0*q,\
+ O(x),x+O(x^2),1+O(x),-1+O(x),1+O(x^2),1+x+O(x^2),0./x+1+O(x^2),0./x+1+x+O(x^2),\
+ (x+0.)/x,(-x+0.)/x,(2*x+0.)/x,\
+ [], [1], []~, [1]~, [2]~, [1,1]~, [1,0]~,[-1,0]~,\
+ [;],Mat(1),Mat(2), matid(2), [1,0;0,2], [1,1;0,1], -matid(2)];
+for (i=1,#v, print([v[i]==1,v[i]==-1]))
diff --git a/src/test/in/err b/src/test/in/err
index 907dd0e..2be02a3 100644
--- a/src/test/in/err
+++ b/src/test/in/err
@@ -162,6 +162,8 @@ sqrtnint(-1,2)
 sqrtnint(2,-2)
 znprimroot(8)
 polroots(x^2+Mod(1,2))
+polroots(0)
+polroots(Mod(1,2))
 prime(-2)
 addprimes(-1)
 padicappr(x^2+1+O(3^5), 1+O(5))
@@ -231,7 +233,7 @@ concat([1,2],[3,4]~)
 concat([])
 concat(List())
 mathnfmod([1;2],2)
-polsturm(x^2)
+polsturm(x^2*1.)
 removeprimes(2)
 forstep(a=1,2,0,)
 e=ellinit([1,1+O(31^2)]);
@@ -245,6 +247,7 @@ thue(x*(x^3-2),0);
 direuler(p=2, 10, 2/(1-p*X))
 solve(x=0,1,x^2+1)
 warning(1)
+iferr(1/0,E,1,errname(E)=="e_DOMAIN")
 \\ backward compatibility. Eventually remove
 inv(x) = trap (e_INV, INFINITY, 1/x)
 inv(2)
diff --git a/src/test/in/eval b/src/test/in/eval
new file mode 100644
index 0000000..3c85da8
--- /dev/null
+++ b/src/test/in/eval
@@ -0,0 +1,2 @@
+eval("\\")
+eval("=")
diff --git a/src/test/in/extract b/src/test/in/extract
index 43983e0..4eefef7 100644
--- a/src/test/in/extract
+++ b/src/test/in/extract
@@ -37,3 +37,13 @@ polcoeff(s,0,x)
 polcoeff(s,1,x)
 
 vecextract(Vecsmall([3,4,5]),[2,3,1])
+vecextract([1], 11)
+vecextract([1], "1..2")
+vecextract([1], 1/2)
+vecextract(1, 1)
+vecextract(matid(2),[3],[])
+[1][2..3]
+[1][-10..3]
+1[1..2]
+[1/2..1]
+[1..1/2]
diff --git a/src/test/in/factormod b/src/test/in/factormod
index 605f176..2558c54 100644
--- a/src/test/in/factormod
+++ b/src/test/in/factormod
@@ -27,3 +27,5 @@ factorcantor(Pol(1),p)
 
 polisirreducible((x^2+x+1)*Mod(1,2))
 polisirreducible((x^2+1)*Mod(1,p))
+
+factormod((x+1)^2, 10^20+39)
diff --git a/src/test/in/ff b/src/test/in/ff
index 6404029..8ed968c 100644
--- a/src/test/in/ff
+++ b/src/test/in/ff
@@ -1,5 +1,6 @@
+jell(x)=if(#x,x.j,[]);
 {
-test(p,f) = setrand(1); a = ffgen(p^f, 'a); [
+test(p,f) = setrand(1); a = ffgen([p,f], 'a); [
 a^2+3*a+1,
 a/(1+a),
 2*(a+1)/3,
@@ -22,7 +23,7 @@ charpoly(a),
 minpoly(a),
 conjvec(a),
 factor(x^6-a*x^3+1),
-ellinit([a,1]),
+jell(ellinit([a,1])),
 a/x,
 (x+a)/(x-a),
 b=ffprimroot(a),
@@ -39,17 +40,8 @@ test(7, 7)
 test(precprime(2^32), 3)
 test(nextprime(2^32), 3)
 
-test2(p)=
-{
-  ffgen(x*Mod(1,p));
-  g = ffprimroot(ffgen((x+1)*Mod(1,p)), &o);
-  print([g, o]);
-  fflog(g^17, g, o);
-}
-test2(2)
-test2(3)
-test2(46744073709551653)
-test2(precprime(1<<32))
+ffgen(ffinit(2^32-5,101),'a)^10000
+ffgen(ffinit(2^64-59,101),'a)^10000
 
 for(i=1,10,print(ffnbirred(11,i)));
 for(i=1,10,print(ffnbirred(11,i,1)));
@@ -59,8 +51,6 @@ do(x^3+x^2+x-1,3,t^3+t^2+t-1)
 t = ffgen(3^3,'t); do((x^3+x^2+x-1)*t^0, t.p, t.mod)
 polrootsff(x^4+1,2,y^2+y+1)
 
-t = ffgen(7^4); fflog(t^6,t^2)
-
 t = ffgen(2^64)^((2^64-1)\5);1/t
 
 t = ffgen(('t^2+'t+1)*Mod(1,2));
@@ -74,10 +64,6 @@ sqrt(Mod(-1,4296540161))
 sqrt(Mod(-1,18446744073944432641))
 centerlift(factorcantor(prod(i=-10,10,(x^2-i)),2^64+13)[,1])
 #polrootsff(x^107+2*x^3+1,3,ffinit(3,107,'a))
-t = ffprimroot(ffgen(2^61)); fflog(t^1234567891012345678,t)
-t = ffprimroot(ffgen(3^23)); fflog(t^12345678910,t)
-t = ffprimroot(ffgen(5^23)); fflog(t^1234567891012345,t)
-t = ffprimroot(ffgen(5^17)); fflog(t^123456789101,t)
 ffgen(x^2+x+Mod(1,3))
 conjvec(Mod(x, x^2+Mod(1,3)))
 t = ffgen(5^4,'t);
@@ -102,7 +88,11 @@ test(2^5)
 test(7^5)
 test((2^64+13)^5)
 
-p=2^64+13; g=ffprimroot(ffgen(p^2), &o); a=2*g^0;
-v=[I,-1,Mat(1),matid(2)/2];
-for(i=1,#v, print(iferr(fflog(a,g,v[i]),E,E)));
-g^fflog(a,g,o) == a
+test(q)={
+  my(t = ffgen(q, 't), M = matrix(10, 10, i, j, random(t)));
+  subst(charpoly(M), 'x, M) == 0;
+}
+test(nextprime(2^7)^5)
+test(nextprime(2^15)^5)
+test(nextprime(2^31)^5)
+test(nextprime(2^63)^5)
diff --git a/src/test/in/fflog b/src/test/in/fflog
new file mode 100644
index 0000000..b075a8f
--- /dev/null
+++ b/src/test/in/fflog
@@ -0,0 +1,37 @@
+test2(p)=
+{
+  ffgen(x*Mod(1,p));
+  g = ffprimroot(ffgen((x+1)*Mod(1,p)), &o);
+  print([g, o]);
+  fflog(g^17, g, o);
+}
+test2(2)
+test2(3)
+test2(precprime(1<<32))
+test2(nextprime(1<<64))
+
+t = ffgen(7^4); fflog(t^6,t^2)
+t = ffprimroot(ffgen(2^61)); fflog(t^1234567891012345678,t)
+t = ffprimroot(ffgen(3^23)); fflog(t^12345678910,t)
+t = ffprimroot(ffgen(5^23)); fflog(t^1234567891012345,t)
+t = ffprimroot(ffgen(5^17)); fflog(t^123456789101,t)
+
+test(P,p)=
+{
+  my(a,b,u,l);
+  a=ffgen(P*Mod(1,p),'a);
+  b=ffprimroot(a);
+  u=random(a);
+  l=fflog(u,b);
+  b^l==u;
+}
+test(x^2+1,1073742623)
+test(x^2+1,1152921504606849707)
+test(x^4+699*x^2+107,1129)
+test(polcyclo(5),1073749723)
+test(polcyclo(7),1073741833)
+
+p=2^64+13; g=ffprimroot(ffgen(p^2), &o); a=2*g^0;
+g^fflog(a,g,o) == a
+v=[I,-1,Mat(1),matid(2)/2];
+for(i=1,#v, print(iferr(fflog(a,g,v[i]),E,E)));
diff --git a/src/test/in/for b/src/test/in/for
deleted file mode 100644
index 29b6724..0000000
--- a/src/test/in/for
+++ /dev/null
@@ -1,6 +0,0 @@
-N = 1<<64;
-for(a=N-2, N+2, print(a))
-for(a=-N-2, -N+2, print(a))
-
-forprime(p=2^32-50,2^32+30,print(p))
-forprime(p=2^64-70,2^64+50,print(p))
diff --git a/src/test/in/forvec b/src/test/in/forvec
new file mode 100644
index 0000000..8ff2601
--- /dev/null
+++ b/src/test/in/forvec
@@ -0,0 +1,25 @@
+V=vector(3,i,[3/2,3]);
+forvec(v=V,print(v))
+print()
+V=vector(3,i,[3/2,4]);
+forvec(v=V,print(v),1)
+print()
+forvec(v=V,print(v),2)
+V=vector(3,i,[1,3]);
+forvec(v=V,print(v))
+print()
+forvec(v=V,print(v),1)
+print()
+forvec(v=V,print(v),2)
+forvec(v=[[1,2],[0,1]],print(v),1)
+forvec(v=[[1,2],[0,1]],print(v),2)
+
+forvec(v=vector(3,i,[3/2,7/2]),print(v),1)
+print()
+forvec(v=[[3/2,3],[2,4],[3/2,5]],print(v),2)
+
+forvec(v=[],print(v))
+forvec(v=[1],)
+forvec(v=[[1]],)
+forvec(v=[[1,I]],)
+forvec(v=[[1,1],[1,1]],,3)
diff --git a/src/test/in/gamma b/src/test/in/gamma
index b2aa09f..968bee9 100644
--- a/src/test/in/gamma
+++ b/src/test/in/gamma
@@ -9,6 +9,7 @@ lngamma(-2+x)
 psi(2+I+x)
 psi(1+x)
 psi(-2+x)
+gamma(-1/2+x)
 
 psi(x)
 gamma(x)
diff --git a/src/test/in/genus2red b/src/test/in/genus2red
index ce78002..1f344a1 100644
--- a/src/test/in/genus2red
+++ b/src/test/in/genus2red
@@ -4,7 +4,7 @@
 \\ t is to be substituted with a prime number bigger or equal to 7
 \\ and can be taken to be 5 most of the time...
 \\ a, b, c are generic integers (to be changed if unexpected output)
-do(P, s) = print("Type: ", s); genus2red(0,subst(P,'t,7),7);
+do(P, s) = print("Type: ", s); genus2red(subst(P,'t,7),7);
 
 P0=x^5+a*x^3+b*x^2+c*x+1;
 do(substvec(P0, [a,b,c], [1,-2,3]), "[I{0-0-0}], p. 155")
@@ -14,7 +14,7 @@ do(substvec(P0, [a,b,c], [1,-2,3]), "[I*{0-0-0}], p. 155")
 
 P0=x^6+a*t*x^4+b*t^2*x^2+t^3;
 do(substvec(P0, [a,b], [4,-1]), "[II], p. 155")
-genus2red(0,substvec(P0,[a,b,t],[4,-1,3]),3)
+genus2red(substvec(P0,[a,b,t],[4,-1,3]),3)
 
 P0=x^6+a*t*x^3+t^2;
 do(subst(P0, 'a, 4), "[III], p. 155")
@@ -67,25 +67,25 @@ m = 10;
 P0=(x^3+a*x+1)*(x^3+b*t^(4*m)*x+t^(6*m)) ;
 do(substvec(P0, [a,b], [3,10]), Strprintf("[I{0}-I{0}-%ld], p. 158", m))
 \\ misprint in N-U: m+1 must be m.
-genus2red(0,substvec(P0,['a,'b,'t],[-1,1,3]),3)
+genus2red(substvec(P0,['a,'b,'t],[-1,1,3]),3)
 
 \\ m >= 0
 m = 10;
 P0=((x-1)^3+a*t^2*(x-1)+t^3)*(x^3+b*t^(4*m+2)*x+t^(6*m+3));
 do(substvec(P0, [a,b], [3,10]), Strprintf("[I{0}*-I{0}*-%ld], p. 158", m))
-genus2red(0,substvec(P0,['a,'b,'t],[-1,1,3]),3)
+genus2red(substvec(P0,['a,'b,'t],[-1,1,3]),3)
 
 \\ m >= 0
 m = 10;
 P0=(x^3+a*x+1)*(x^3+b*t^(4*m+2)*x+t^(6*m+3));
 do(substvec(P0, [a,b], [3,10]), Strprintf("[I{0}-I{0}*-%ld], p. 159", m))
-genus2red(0,substvec(P0,['a,'b,'t],[-1,1,3]),3)
+genus2red(substvec(P0,['a,'b,'t],[-1,1,3]),3)
 
 \\ m >= 0
 m = 10;
 P0=(x^2-t)^3+a*t^(2*m+4)*(x^2-t)+t^(3*m+6);
 do(subst(P0, 'a, 3), Strprintf("[2I{0}-%ld], p. 159",m+1))
-genus2red(0,substvec(P0,['a,'t],[-1,3]),3)
+genus2red(substvec(P0,['a,'t],[-1,3]),3)
 
 \\ m >= 0
 m = 10;
@@ -106,31 +106,31 @@ do(subst(P0, 'a, 3), Strprintf("[I{0}-II-%ld], p. 159",m))
 m = 10;
 P0=(x^3+t^(6*m+5))*(x^2+a*x+1);
 do(subst(P0, 'a, 3), Strprintf("[I{0}-II*-%ld], p. 160",m))
-genus2red(0,substvec(P0,['a,'t],[3,3]),3)
+genus2red(substvec(P0,['a,'t],[3,3]),3)
 
 \\ m >= 0
 m = 10;
 P0=(x^3+t^(6*m+2))*(x^2+a*x+1);
 do(subst(P0, 'a, 3), Strprintf("[I{0}-IV-%ld], p. 160",m))
-genus2red(0,substvec(P0,['a,'t],[3,3]),3)
+genus2red(substvec(P0,['a,'t],[3,3]),3)
 
 \\ m >= 0
 m = 10;
 P0=(x^3+t^(6*m+4))*(x^2+a*x+1);
 do(subst(P0, 'a, 3), Strprintf("[I{0}-IV*-%ld], p. 160",m))
-genus2red(0,substvec(P0,['a,'t],[3,3]),3)
+genus2red(substvec(P0,['a,'t],[3,3]),3)
 
 \\ m >= 0
 m = 10;
 P0=t*(x^3+t^(6*m+4))*(x^2+a*x+1);
 do(subst(P0, 'a, 3), Strprintf("[I{0}*-II-%ld], p. 160",m))
-genus2red(0,substvec(P0,['a,'t],[3,3]),3)
+genus2red(substvec(P0,['a,'t],[3,3]),3)
 
 \\ m >= -1
 m = 10;
 P0=t*(x^3+t^(6*m+8))*(x^2+a*x+1);
 do(subst(P0, 'a, 3), Strprintf("[I{0}*-II*-%ld], p. 160-161",m))
-genus2red(0,substvec(P0,['a,'t],[3,3]),3)
+genus2red(substvec(P0,['a,'t],[3,3]),3)
 
 \\ m >= 0
 m = 10;
@@ -166,13 +166,13 @@ do(subst(P0, 'a, 3), Strprintf("[I{0}*-III*-%ld], p. 162",m))
 m = 10;
 P0=(x^2-t)^3+t^(3*m+3)*x;
 do(P0, Strprintf("[2II-%ld], p. 162",m))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ m >= 0
 m = 10;
 P0=(x^2-t)^3+t^(3*m+5)*x;
 do(P0, Strprintf("[2II*-%ld], p. 163",m))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ m >= 0
 m = 10;
@@ -221,13 +221,13 @@ do(P0, Strprintf("[II*-IV*-%ld], p. 164-165",m))
 m = 10;
 P0=(x^2-t)^3+t^(3*m+4);
 do(P0, Strprintf("[2IV-%ld], p. 165",m))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ m >= 0
 m = 10;
 P0=(x^2-t)^3+t^(3*m+5);
 do(P0, Strprintf("[2IV*-%ld], p. 165",m))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ m >= 0
 m = 10;
@@ -272,13 +272,13 @@ do(P0, Strprintf("[II*-III*-%ld], p. 167",m))
 m = 10;
 P0=x*(x^2+t^(4*m+1))*((x-1)^3+t^2);
 do(P0, Strprintf("[IV-III-%ld], p. 167",m))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ m >= 0
 m = 10;
 P0=x*(x^2+t^(4*m+3))*((x-1)^3+t^2);
 do(P0, Strprintf("[IV-III*-%ld], p. 167",m))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ m = -1
 P0=x*(x^2+t)*(x^3+t);
@@ -299,13 +299,13 @@ do(P0, Strprintf("[IV*-III*-%ld], p. 168",m))
 m = 10;
 P0=(x^2-t)*((x^2-t)^2+t^(2*m+2)*x);
 do(P0, Strprintf("[2III-%ld], p. 168",m))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ m >= 0
 m = 10;
 P0=(x^2-t)*((x^2-t)^2+t^(2*m+3)*x);
 do(P0, Strprintf("[2III*-%ld], p. 168",m))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ m >= 0
 m = 10;
@@ -332,13 +332,13 @@ do(subst(P0, 'a, 3), Strprintf("[I{%ld-0-0}], p. 170",n))
 n = 9; m = 10;
 P0=(x^3+a*t^(4*m)*x+t^(6*m))*((x-1)^2+t^n);
 do(subst(P0, 'a, 3), Strprintf("[I{%ld}-I{0}-%ld], p. 170",n, m))
-genus2red(0,substvec(P0,['a,'t],[-1,3]),3)
+genus2red(substvec(P0,['a,'t],[-1,3]),3)
 
 \\ n, m >= 0
 n = 9; m = 10;
 P0=(x+t)*(x^2+t^(n+2))*((x-1)^3+a*t^(4*m)*(x-1)+t^(6*m));
 do(subst(P0, 'a, 3), Strprintf("[I{0}-I*{%ld}-%ld], p. 170",n, m))
-genus2red(0,substvec(P0,['a,'t],[-1,3]),3)
+genus2red(substvec(P0,['a,'t],[-1,3]),3)
 
 \\ n, m >= 0
 n = 9; m = 10;
@@ -414,60 +414,60 @@ do(P0, Strprintf("[IV*-I*{%ld}-%ld], p. 174",n, m))
 n = 9;
 P0=t*((x-1)^2+t^n)*(x^3+t);
 do(P0, Strprintf("[IV*-I*{%ld}-(-1)], p. 175",n))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n >= 0
 n = 9;
 P0=x*(x^3+t)*((x-1)^2+t^n);
 do(P0, Strprintf("[IV-II{%ld}], p. 175",n))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n > 0
 n = 9;
 P0=x*(x^3+t^2)*((x-1)^2+t^(n-1));
 do(P0, Strprintf("[IV*-II{%ld}], p. 175",n))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n = 0
 P0=(x^2+t^3)*(x^3+t^4);
 do(P0, "[IV*-II{0}], p. 175")
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n >= 0
 n = 9;
 P0=(x^3+t)*(x^2+t^(n+1));
 do(P0, Strprintf("[II-II*{%ld}], p. 176",n))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n >= 0
 n = 9;
 P0=t*x*(x^3+t)*((x-1)^2+t^n);
 do(P0, Strprintf("[II*-II*{%ld}], p. 176",n))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n > 0, m >= 0
 n = 9; m = 10;
 P0=x*(x^2+t^(4*m+1))*((x-1)^2+t^n);
 do(P0, Strprintf("[III-I{%ld}-%ld], p. 176",n,m))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n > 0, m >= 0
 n = 9; m = 10;
 P0=x*(x^2+t^(4*m+3))*((x-1)^2+t^n);
 do(P0, Strprintf("[III*-I{%ld}-%ld], p. 176",n,m))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n, m >= 0
 n = 9; m = 10;
 P0=(x+t)*(x^2+t^(n+2))*(x-1)*((x-1)^2+t^(4*m+1));
 do(P0, Strprintf("[III-I*{%ld}-%ld], p. 177",n,m))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n, m >= 0
 n = 9; m = 10;
 P0=(x+t)*(x^2+t^(n+2))*(x-1)*((x-1)^2+t^(4*m+3));
 do(P0, Strprintf("[III*-I*{%ld}-%ld], p. 177",n,m))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n >= 0, m = -1
 n = 9;
@@ -515,7 +515,7 @@ do(P0, Strprintf("[I{%ld}-I{%ld}-%ld}], p. 179",n,p,m))
 n = 9; p = 8;
 P0=t*(x^2+t^n)*((x+1)^2+t^p)*(x-1);
 do(P0, Strprintf("[I*{%ld-%ld-0}], p. 180",n,p))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n, p > 0, m >= 0
 n = 9; p = 8; m = 10;
@@ -526,13 +526,13 @@ do(P0, Strprintf("[I*{%ld}-I*{%ld}-%ld], p. 180",n,p,m))
 n = 9; p = 8; m = 10;
 P0=(x+t^(2*m+1))*(x^2+t^(4*m+p+2))*((x-1)^2+t^n);
 do(P0, Strprintf("[I{%ld}-I*{%ld}-%ld], p. 180",n,p,m))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n > 0 even, m > 0
 k = 4; m = 10; n=2*k;
 P0=((x^2-t)+t^(m+1))*((x^2-t)^2+t^(2*m+k+2));
 do(P0, Strprintf("[2I{%ld}-%ld], p. 181",n,m))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n > 0 odd, m > 0
 k = 4; m = 10; n=2*k+1;
@@ -553,7 +553,7 @@ do(subst(P0, 'a, 2), Strprintf("[2I{%ld}-0], p. 181",n))
 k = 4; m = 10; n=2*k;
 P0=((x^2-t)+t^(m+1)*x)*((x^2-t)^2+t^(2*m+k+3));
 do(P0, Strprintf("[2I*{%ld}-%ld}], p. 181",n,m))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n > 0 odd, m
 k = 4; m = 10; n=2*k+1;
@@ -564,7 +564,7 @@ do(P0, Strprintf("[2I*{%ld}-%ld}], p. 181",n,m))
 n = 9; p = 8;
 P0=(x^2+t)*(x^2+t^(p+1))*((x-1)^2+t^(n-1));
 do(P0, Strprintf("[II{%ld-%ld}], p. 182",n,p))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n > 0 even
 k = 4; n=2*k;
@@ -590,13 +590,13 @@ do(P0, Strprintf("[I*{%ld-%ld-%ld}], pp. 183",n,p,q))
 n = 9; k = 4; p=2*k;
 P0=((x^2-t)^2+t^(k+2))*((x-1)^2+t^(n-1));
 do(P0, Strprintf("[II{%ld-%ld}], p. 183",n,p))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n, p > 0, p odd
 n = 9; k = 4; p=2*k+1;
 P0=((x^2-t)^2+t^(k+2)*x)*((x-1)^2+t^(n-1));
 do(P0, Strprintf("[II{%ld-%ld}], p. 183",n,p))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n, p > 0
 n = 9; k = 4; l = 0; p=2*k+l;
@@ -612,88 +612,88 @@ do(P0, Strprintf("[II*{%ld-%ld}], p. 184",n,p))
 k = 4; l = 0; n=3*k+l;
 P0=(x^3-t)^2+t^(k+2)*x^l;
 do(P0, Strprintf("[III{%ld}], p. 184",n))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n > 0
 k = 4; l = 1; n=3*k+l;
 P0=(x^3-t)^2+t^(k+2)*x^l;
 do(P0, Strprintf("[III{%ld}], p. 184",n))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n > 0
 k = 4; l = 2; n=3*k+l;
 P0=(x^3-t)^2+t^(k+2)*x^l;
 do(P0, Strprintf("[III{%ld}], p. 184",n))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n > 0
 k = 2; l = 0; n=3*k+l;
 P0=t*((x^3-t)^2+t^(k+2)*x^l);
 do(P0, Strprintf("[III*{%ld}], p. 184",n))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n > 0
 k = 2; l = 1; n=3*k+l;
 P0=t*((x^3-t)^2+t^(k+2)*x^l);
 do(P0, Strprintf("[III*{%ld}], p. 184",n))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ n > 0
 k = 2; l = 2; n=3*k+l;
 P0=(x^3-t)^2+t^(k+2)*x^l;
 do(P0, Strprintf("[III{%ld}], p. 184",n))
-genus2red(0,subst(P0,'t,3),3)
+genus2red(subst(P0,'t,3),3)
 
 \\ Extras : p = 3
 \e
 \\ Colin Stahlke, bug28
-genus2red(0,-x^6-6*x^2-7,3)
-genus2red(0,-9*x^6+6*x^5-8*x^4-5*x^3+5*x^2-10*x+3,3)
+genus2red(-x^6-6*x^2-7,3)
+genus2red(-9*x^6+6*x^5-8*x^4-5*x^3+5*x^2-10*x+3,3)
 \\ M. Stoll, bug28
-genus2red(0,3*x^6+3*x^4+3*x^3+x^2-5*x-5,3)
+genus2red(3*x^6+3*x^4+3*x^3+x^2-5*x-5,3)
 \\ Colin Stahlke, bug28
-genus2red(0,-3*x^6+6*x^5-1*x^4+6*x^3-6*x^2-1*x-6,3)
+genus2red(-3*x^6+6*x^5-1*x^4+6*x^3-6*x^2-1*x-6,3)
 \\ J. Mueller, bug28
-genus2red(0,(x^3+2*x+1)*(x^3+3^2*x^2+3^8),3)
+genus2red((x^3+2*x+1)*(x^3+3^2*x^2+3^8),3)
 
 \\ A. Brumer, bug28
 P=x^6+4*x^5-24*x^4-16*x^3-52*x^2-48*x;
-genus2red(0,P,3)
+genus2red(P,3)
 
 P=x^6+4*x^5+24*x^4+32*x^3+56*x^2+48*x+24;
-genus2red(0,P,3)
+genus2red(P,3)
 
 P=24*x^5+56*x^4+76*x^3+33*x^2-4*x-20;
-genus2red(0,P,3)
+genus2red(P,3)
 
 P=-3*x^6+6*x^5-25*x^4+36*x^3-69*x^2+38*x-39;
-genus2red(0,P,3)
+genus2red(P,3)
 
 \\ M. Stoll, bug28
 P=-5*x^5+5*x^4+10*x^3-7;
-genus2red(1,P,3)
+genus2red([P,1],3)
 
 P=-5*x^6-3*x^5-10*x^4-10*x^3-7;
-genus2red(1,P,3)
+genus2red([P,1],3)
 
 P=3*x^5+5*x^4+5*x-4;
-genus2red(1,P,3)
+genus2red([P,1],3)
 
 Q=x^2+x; P=-9*x^6+6*x^5-8*x^4-5*x^3+5*x^2-10*x+3;
-genus2red(Q,P,3)
+genus2red([P,Q],3)
 
 \\ M. Stoll, bug27
 Q=x^3+1; P=-7*x^6+5*x^3+5*x^2-6*x+1;
-genus2red(Q,P,3)
+genus2red([P,Q],3)
 
 \\ #1596
-genus2red(0,27*x^5 + 97*x^4 + 118*x^3 + 60*x^2 + 13*x + 1,3)
+genus2red(27*x^5 + 97*x^4 + 118*x^3 + 60*x^2 + 13*x + 1,3)
 
 \\ #1597
-genus2red(x,-x^6 - 3*x^4 - 10*x^2 - 1,3)
+genus2red([-x^6 - 3*x^4 - 10*x^2 - 1,x],3)
 \\ #1597
-genus2red(x^3+x^2+x+1,-60*x^6-203*x^5-291*x^4-244*x^3-129*x^2-41*x-7)
+genus2red([-60*x^6-203*x^5-291*x^4-244*x^3-129*x^2-41*x-7,x^3+x^2+x+1])
 \\ #1597
-genus2red(0,6*x^6+5*x^4+x^2+1,7)
+genus2red(6*x^6+5*x^4+x^2+1,7)
 \\ #1597
-genus2red(x^3-1,1)
+genus2red([1,x^3-1])
diff --git a/src/test/in/help b/src/test/in/help
index 00d6f59..d551a56 100644
--- a/src/test/in/help
+++ b/src/test/in/help
@@ -12,6 +12,9 @@ addhelp(sin,"test2")
 addhelp(f,"test3")
 addhelp(echo,"test4")
 addhelp(new,"test5")
+install(addii,GG)
+?addii
+addhelp(addii,"test6")
 ?x
 ?sin
 ?f
@@ -22,4 +25,7 @@ addhelp(new,"test5")
 ?.
 ?\
 ?1
+?addii
 \t
+g()=0;
+\u
diff --git a/src/test/in/hyperell b/src/test/in/hyperell
new file mode 100644
index 0000000..37db19c
--- /dev/null
+++ b/src/test/in/hyperell
@@ -0,0 +1,45 @@
+checkfeq(P,q)=
+{
+  my(M=minpoly(Mod(x+q/x,P)));
+  if(poldegree(M)!=poldegree(P)/2,error([P,q,M]));
+  M;
+}
+{
+  for(g=1,6,
+    for(n=1,2*g,
+      H=hyperellcharpoly(n*(x^(2*g+1)-2*x^n+1)*Mod(1,19));
+      printsep(":",g,n,checkfeq(H,19))))
+}
+
+{
+  for(g=1,5,
+    for(n=1,2*g+1,
+      H=hyperellcharpoly(n*(x^(2*g+2)-3*x^n+1)*Mod(1,29));
+      printsep(":",g,n,checkfeq(H,29))))
+}
+
+{
+  forprime(p=3,7,
+    H=hyperellcharpoly((x^6+x+1)*Mod(1,p));
+    print(checkfeq(H,p)));
+  forprime(p=5,11,
+    H=hyperellcharpoly((x^10+x+1)*Mod(1,p));
+    print(checkfeq(H,p)));
+  forprime(p=3,7,
+    g=ffgen(ffinit(p,3),'g);
+    H=hyperellcharpoly((x^6+g*x+1));
+    print(checkfeq(H,p^3)));
+}
+
+g=ffgen(ffinit(79,2),'g);
+P=hyperellcharpoly(x^5+g*x^3+2*x+5);checkfeq(P,79^2)
+P=hyperellcharpoly(g*(x^5+g*x^3+2*x+5));checkfeq(P,79^2)
+P=hyperellcharpoly(x^5+Mod('g,g.mod*Mod(1,79))*x^3+2*x+5);checkfeq(P,79^2)
+P=hyperellcharpoly(x^6+g*x^3+2*x+5);checkfeq(P,79^2)
+P=hyperellcharpoly(g*(x^6+g*x^3+2*x+5));checkfeq(P,79^2)
+P=hyperellcharpoly((x^7+x^3+2*x+5)*Mod(1,79));checkfeq(P,79)
+P=hyperellcharpoly((x^8+x^3+2*x+5)*Mod(1,79));checkfeq(P,79)
+P=hyperellcharpoly([x^5+x+1,x]*Mod(1,79));checkfeq(P,79)
+
+hyperellcharpoly((256*a^5+5)*Mod(1,5))
+hyperellcharpoly((256*a^5+5)*ffgen(5^2))
diff --git a/src/test/in/ideal b/src/test/in/ideal
index 3556795..17d508e 100644
--- a/src/test/in/ideal
+++ b/src/test/in/ideal
@@ -67,6 +67,15 @@ test(nf,F,v)
 F[,2] = [1,1,1,1]~;
 test(nf,F,[1,0,0,0])
 test(nf,F,[0,1/11,0,0])
+P = F[2,1];
+v = nfeltval(nf, 0, P, &y); [v == valuation(0,2),y]
+v = nfeltval(nf, 12, P, &y); [v,y]
+v = nfeltval(nf, (2/5*(1-x))^3, P, &y); [v,y]
+v = nfeltval(nf, nfeltpow(nf,P.gen[2],4), P, &y); [v,y]
+
+\\ #1643
+K=nfinit(x^8-1310*x^6+575380*x^4-93689568*x^2+3644295424);
+idealprimedec(K,17,1)
 
 K=nfinit(2*x^2+1);
 idealprimedec(K,2)
diff --git a/src/test/in/incgam b/src/test/in/incgam
index f3cf3d7..a848b1b 100644
--- a/src/test/in/incgam
+++ b/src/test/in/incgam
@@ -18,7 +18,7 @@ test(fun, p) =
 
 test(incgam, 19)
 test(incgam, 38)
-test(incgam, 100)
+test(incgam, 96)
 
 mylog(x)=if(x==0, "oo", round(log(abs(x))/log(10)));
 
diff --git a/src/test/in/intnum b/src/test/in/intnum
index bdaeda7..26e17c7 100644
--- a/src/test/in/intnum
+++ b/src/test/in/intnum
@@ -1,7 +1,6 @@
 default(echo,1);
 allocatemem(20 * 10^6);
-check(a,b) = my(t = abs((a-b)/b)); if (t, ceil(log(t)/log(10)), "-oo");
-oo = [1];
+check(a,b) = my(t = abs((a-b)/b)); if (t, ceil(log(t)/log(10)), -oo);
 \p96
 check(intcirc(s=1, 0.5, zeta(s)), 1)
 check(intlaplaceinv(x=2, 1, 1/x), 1)
@@ -19,6 +18,16 @@ check(intnum(x = 0, [oo,1],  f(x)), Euler)
 check(intnum(x = 0, [oo,1],  g(x)), Euler)
 check(intnum(x = 0, 1,  1/sqrt(x)), 2)
 check(intnum(x = [0,-1/2], 1,  1/sqrt(x)), 2)
+
+check(intnum(x = [0,-1/2], [oo,-3/2],  1/(sqrt(x)+x^(3/2))), Pi)
+check(intnum(x = [-oo,-3/2], [oo,-3/2],  1/(1+abs(x)^(3/2))), 8*Pi/sqrt(27))
+
+f(x)=if (x<0,1/(1+(-x)^(3/2)), 1/(1+x^(5/2)));
+a=4*Pi/sqrt(27) + 2*(Pi/5)/sin(2*Pi/5);
+check(intnum(x = [-oo,-3/2], [oo,-5/2], f(x)),a)
+f(x)=if (x<0,1/(1+(-x)^(3/2)), exp(-x));
+check(intnum(x = [-oo,-3/2], [oo,1], f(x)), 1+4*Pi/sqrt(27))
+
 check(intnum(x = 0, [oo,1], sin(x)/x), Pi/2)
 check(intnum(x = 0, [oo,-I], sin(x)/x), Pi/2)
 check(intnum(x = 0, [oo,-2*I], sin(2*x)/x), Pi/2)
@@ -34,13 +43,17 @@ check(intnum(x=-1,1, intnum(y=-sqrt(1-x^2),sqrt(1-x^2),x^2+y^2,tab),tab), Pi/2)
 \\
 \p 308
 a = sumpos(n=1, 1/(n^3+n+1));
+b = sumpos(n=1, 1/(n^3+n+1), 1);
+check(a, b)
 tab = sumnuminit(2);
 b = sumnum(n=1,2, 1/(n^3+n+1), tab);
 check(a, b)
 check(sumnum(n=1,2, 1/(n^3+n+1), tab, 1), a)
-c = sumnum(n=1,2,1/(n^2+1),tab,1);
-d = sumpos(n=1,1/(n^2+1));
-check(c, d)
+a = sumpos(n=1,1/(n^2+1));
+b = sumpos(n=1,1/(n^2+1), 1);
+check(a, b)
+b = sumnum(n=1,2,1/(n^2+1),tab,1);
+check(a, b)
 check(sumnum(n=1,2,n^(-4/3),,1), zeta(4/3))
 tab = sumnuminit([2,-3/2]);
 check(sumnum(n=1,[2,-3/2],1/(n*sqrt(n)),tab,1), zeta(3/2))
@@ -68,8 +81,17 @@ intnumromb(x=0,1,sin(x))
 intnumromb(x=0,1,sin(x), 1)
 intnumromb(x=1,100,exp(-x^2), 2)
 intnumromb(x=0,1,sin(x)/x, 3)
+\\ sloooow
+\\intnumromb(x=0,110,x, 1)
+\\intnumromb(x=-110,90,x, 1)
+intnumromb(x=2,1,x, 1)
 
 f(x) = -log(cos(x));
 F = truncate( f(t + O(t^16)) );
 g(x) = if (x > 1e-2, f(x), subst(F,t,x));
 sumpos(n=1,g(1/n))
+sumpos(n=0,0)
+
+intnuminit([oo,1+I],[oo,""])
+intnum(x=oo,oo,1)
+intnum(x=-oo,-oo,1)
diff --git a/src/test/in/ispower b/src/test/in/ispower
index 21495b9..d26430e 100644
--- a/src/test/in/ispower
+++ b/src/test/in/ispower
@@ -51,6 +51,10 @@ for (k = 1, #v,
 \\  if ([s,t] != correct[k], error(k))
 )
 }
+n=(2^100+277)^10;
+ispseudoprimepower(n)
+ispseudoprimepower(n,&p)
+p
 
 isprimepower(541^121)
 ispowerful(4)
@@ -94,6 +98,12 @@ issquare(O(x))
 issquare(x+O(x^2))
 issquare(4*x^2+O(x^3))
 issquare(4/x^2)
+if (issquare(x^0/4,&z),z)
+if (issquare((x+1/2)^2,&z),z)
+if (issquare(x^0/4,&z),z)
+issquare(Mod(1,4)*x^2)
+issquare(Mod(1,4)*(x+1)^2)
+
 ispower(-8,4)
 if(ispower(-8,3,&z),z)
 ispower(-8/27,3)
diff --git a/src/test/in/isprime b/src/test/in/isprime
index 78998af..ce6c26a 100644
--- a/src/test/in/isprime
+++ b/src/test/in/isprime
@@ -14,3 +14,5 @@ ispseudoprime([1,3,4,5],2)
 \\isprime(2^2000+841, 2) 1 min
 \\isprime(2^1600+895, 2) 27s
 isprime(2^1000+297, 2)
+
+isprime(2^256+5721)
diff --git a/src/test/in/iterator b/src/test/in/iterator
index 1ae8e8b..c9a76c6 100644
--- a/src/test/in/iterator
+++ b/src/test/in/iterator
@@ -1,5 +1,29 @@
+default(realprecision,38);
+N = 1<<64;
+for(a=N-2, N+2, print(a))
+for(a=-N-2, -N+2, print(a))
+
+forprime(p=2^32-50,2^32+30,print(p))
+forprime(p=2^64-70,2^64+50,print(p))
+
+for(a=0.5,3,print(a))
+for(a=1,10, print(a+=2))
+
+forstep(a=5,1,-2,print1(a," "))
+forstep(a=1,10,[1,3],print1(a," "))
+
+forprime(p=2,10,p=4)
+
 forcomposite(a=2,10,print(a))
 forcomposite(a=5,11,print(a))
 forcomposite(a=6,12,print(a))
 forcomposite(a=6,,print(a); if (a>8, break))
 forcomposite(a=6,12,print(a); a=1)
+forcomposite(a=2,3,print(a))
+
+{
+for(i=1,4,for(j=5,8,
+  if ([i,j]==[2,6], next,
+      [i,j]==[3,6], next(2),
+      [i,j]==[4,6], next(3)); print([i,j])))
+}
diff --git a/src/test/in/krasner b/src/test/in/krasner
index ab09b69..a6ad81c 100644
--- a/src/test/in/krasner
+++ b/src/test/in/krasner
@@ -1,5 +1,12 @@
-allocatemem(20*10^6);
-filter_output(p, v) = vecsort(vector(#v, j, my([D,e,f,d]=v[j]); [valuation(poldisc(D), p), e, f, d]), cmp);
+filter_output(p, v) =
+{
+  vecsort(vector(#v, j,
+    if (type(v[j]) == type([]),
+      my([D,e,f,d]=v[j]); [valuation(poldisc(D), p), e, f, d]
+    ,
+      valuation(poldisc(v[j]), p)))
+  , cmp);
+}
 
 do(p,N,flag)=filter_output(p, padicfields(p,N,flag));
 
@@ -7,9 +14,12 @@ p = 2; for (d = 2, 50, if (d%p, print(do(p,d,1))))
 p = 3; for (d = 2, 50, if (d%p, print(do(p,d,1))))
 do(2, 105, 1)
 do(5, 21, 1)
-do(23, 55, 1)
-do(23459, 12, 1)
+do(23, 75, 1)
+do(23459, 18, 1)
 do(2, [8,12], 1)
-padicfields(2^64+13, 8, 2)
+do(2^21+17, 30, 1)
+do(2^64+13, 8, 1)
 do(2^64+13, 2, 1)
+padicfields(2^64+13, 8, 2)
 do(2, 4, 1)
+do(2, 3, 0)
diff --git a/src/test/in/lambert b/src/test/in/lambert
index 3597451..e3528bd 100644
--- a/src/test/in/lambert
+++ b/src/test/in/lambert
@@ -5,3 +5,26 @@ default(realprecision,38);
 do(2)
 default(realprecision,211);
 do(1e14)
+do(y)=
+{ my(x = lambertw(y), e = normlp(Vec(exp(x)*x - y)));
+  if (e > 5e-38, error([e, y]));
+}
+default(realprecision,38);
+do(O(x^10))
+do(O(x^30))
+do(3+O(x^10))
+do(3+O(x^30))
+do(x)
+do(x+O(x^10))
+do(x+O(x^30))
+do(3+O(x))
+do(3+x)
+do(3+x+O(x^10))
+do(3+x+O(x^30))
+do(x^2-2*x^3)
+do(x^2-2*x^3+O(x^10))
+do(x^2-2*x^3+O(x^30))
+do(3+x^2-2*x^3)
+do(3+x^2-2*x^3+O(x^10))
+do(3+x^2-2*x^3+O(x^30))
+lambertw(1/x)
diff --git a/src/test/in/lex b/src/test/in/lex
index e255dd2..1b2306f 100644
--- a/src/test/in/lex
+++ b/src/test/in/lex
@@ -13,3 +13,15 @@ isvec(x) = type(x) == "t_VEC" || type(x) == "t_COL";
     )
   );
 }
+
+v = Vecsmall([1,2,3]);
+lex(v, [1,2,3])
+lex(v, [1,2])
+lex(v, [1,2,4])
+lex(v, [4,2,3])
+lex(v, [0,2,3])
+lex(v, [[1,2,3],2,3])
+lex(v, [[0,2,3],2,3])
+lex(v, [[],2,3])
+lex(v, [Vecsmall([]),2,3])
+lex(v, [Vecsmall(1),2,3])
diff --git a/src/test/in/list b/src/test/in/list
index 834cafe..74d8fbf 100644
--- a/src/test/in/list
+++ b/src/test/in/list
@@ -35,3 +35,11 @@ getheap()[1]
 chinese(List())
 chinese(List([Mod(1,3)]))
 chinese(List([Mod(0,2),Mod(1,3),Mod(2,5)]))
+liftint(List([0,1]))
+
+L = List([1,2,3]);
+L[1]
+L[1]*=2
+L
+L[1]=3
+L
diff --git a/src/test/in/mat b/src/test/in/mat
index 2033e72..cba9ef9 100644
--- a/src/test/in/mat
+++ b/src/test/in/mat
@@ -14,6 +14,8 @@ default(realprecision,38);
 h=mathilbert(40);
 [Q,R] = matqr(h); vecmax(abs(h-Q*R)) < 1e-37
 [q,R] = matqr(h,1); vecmax(abs(mathouseholder(q,h)-R)) < 1e-37
+matqr([;])
+matqr([;],1)
 mathouseholder(1,1)
 mathouseholder(q,1)
 Mat(List())
@@ -71,6 +73,7 @@ matdet(A*Mod(1,2^64+13))
 matsolve(A*Mod(1,2^64+13),[1,2,3]~)
 
 matker([1.,I;I,-1.])
+matkerint(Mat([1,1]))
 
 trace(matid(3))
 trace([;])
@@ -92,3 +95,37 @@ Ap=Mod(A,p);
 vecsum([])
 vecsum([2])
 vecsum(primes(4))
+vecsum(1)
+1~
+
+content([])
+content([;])
+content(matrix(0,2))
+
+vectorsmall(3)
+v=vectorsmall(3,i,3*i^2)
+content(v)
+content(vectorsmall(0))
+v=vectorsmall(5,i,(3-i)*i)
+content(v)
+vectorsmall(3,i,i^100)
+
+m=[1,0;0,0;0,1]; b=[1,2;0,0;3,4];
+liftint(Mod(m,2)^(-1))
+liftint(Mod(m,3)^(-1))
+liftint(Mod(m,2^64+13)^(-1))
+liftint(matsolve(Mod(m,2),b))
+liftint(matsolve(Mod(m,3),b))
+liftint(matsolve(Mod(m,2^64+13),b))
+(m*ffgen(2^2)^0)^(-1)
+(m*ffgen(3^2)^0)^(-1)
+(m*ffgen((2^64+13)^2)^0)^(-1)
+
+m=[1,2,3;4,5,6];
+m[1,]=[1,2]
+m[1,]=[1,2,3,4]
+m[1,]=[1,2,3]~
+m[2,]=[1,2,3]
+m
+m[1,]*=2
+m
diff --git a/src/test/in/matsnf b/src/test/in/matsnf
index 0c29d00..0025ebd 100644
--- a/src/test/in/matsnf
+++ b/src/test/in/matsnf
@@ -5,13 +5,20 @@ minpoly([-5,0,-1,1;0,-5,-1,-1;1,1,-5,0;-1,1,0,-5]*a)
 matsnf([1,2;3,4],2)
 matsnf([-X-5,-1,-1,0;0,X^2+10*X+26,-1,-X-5;1,-X-5,-X-5,1;-1,0,0,1],2)
 minpoly([a+4/51*d,29/51*d,55/17*d,-9/17*d;-11/51*d,a+35/51*d,-11/17*d,12/17*d;23/51*d,1/51*d,a+6/17*d,-5/17*d;11/17*d,16/17*d,33/17*d,a-19/17*d])
+
+checkfrobenius(M)=
+{
+  my([F,B] = matfrobenius(M,2));
+  if(M!=B^-1*F*B, error("matfrobenius:",M));
+  F
+}
 {
   for(i=1,15,
-      print(matfrobenius(matrix(i,i,k,j,k>=j),2)));
+      print(checkfrobenius(matrix(i,i,k,j,k>=j))));
   for(i=1,10,
-     print(matfrobenius(matpascal(i),2)));
+     print(checkfrobenius(matpascal(i))));
   for(i=1,8,
-     print(matfrobenius(mathilbert(i),2)));
+     print(checkfrobenius(mathilbert(i))));
 }
 matsnf(matdiagonal([x,0,x]), 2)
 matsnf(matdiagonal([1+x,0,x]), 2)
diff --git a/src/test/in/member b/src/test/in/member
index 8783781..1c8dc00 100644
--- a/src/test/in/member
+++ b/src/test/in/member
@@ -69,7 +69,7 @@ print("BNF");test( BNF = bnfinit(NF) )
 print("BNR");test( bnrinit(BNF, 4) )
 print("RNF");test( rnfinit(NF, x^2-y) )
 print("QUADCLASSUNIT"); test( quadclassunit(1105) )
-print("GAL"); test( galoisinit(x^2-2) )
+print("GAL"); test( galoisinit(x^2-2^129) )
 print("ELL");test( ellinit([1,2,3,4,5]) )
 print("ELLFp");test( ellinit([1,2,3,4,5], 13) )
 print("ELLFq");test( ellinit([1,2,3,4,5], ffgen(13^2)) )
diff --git a/src/test/in/modfun b/src/test/in/modfun
index 9eab702..47f9976 100644
--- a/src/test/in/modfun
+++ b/src/test/in/modfun
@@ -6,3 +6,4 @@ ellj(2+O(2^20))
 ellj(x+x^2+x^3+x^4+O(x^5))
 theta(1/2,I)
 weber(1.0*I,1)
+weber(1+I)
diff --git a/src/test/in/modsym b/src/test/in/modsym
new file mode 100644
index 0000000..e3704dd
--- /dev/null
+++ b/src/test/in/modsym
@@ -0,0 +1,96 @@
+allocatemem(20*10^6)
+N = 11;
+W2 = msinit(N,2,-1);
+W1 = msinit(N,2,1);
+W = msinit(N,2);
+mshecke(W2, 2)
+mshecke(W1, 2)
+mshecke(W, 2)
+mshecke(W1, 11)
+
+E=ellinit([1,2]);
+[W,xpm]= msfromell(E,1);
+mseval(W,xpm,[1/2,1/3])
+E=ellinit([0,-1,1,-10,-20]);
+[W,xpm]= msfromell(E,1);
+mseval(W,xpm,[1/2,1/3])
+E=ellinit([1,-1,1,-1,-14]);
+[W,xpm]= msfromell(E,1);
+mseval(W,xpm)
+mseval(W,xpm,[0,1/3])
+
+N = 227;
+W = msinit(N,2,1);
+mssplit(W, msnew(W))
+
+N = 1000;
+W = msinit(N,2,1);
+matsize( msnew(W)[1] )
+W = msinit(2, 4);
+charpoly(mshecke(W, 2))
+
+W = msinit(3, 6);
+charpoly(mshecke(W, 2))
+
+W = msinit(4, 4);
+charpoly(mshecke(W, 3))
+
+W = msinit(11, 4);
+charpoly(mshecke(W, 2))
+
+W = msinit(2, 8);
+charpoly(mshecke(W, 2))
+[g,R]=mspathgens(W)
+mspathlog(W,g[1])
+mspathlog(W,g[2])
+mspathlog(W,[1/3,1/2])
+mseval(W,[0,0])
+s=msnew(W)[1][,1];
+mseval(W,s)
+mseval(W,s,[0,0])
+mseval(W,s,g[1])
+mseval(W,s,g[2])
+
+W = msinit(11, 2);
+T = mshecke(W, 3);
+[S,E] = mscuspidal(W, 1)
+E == mseisenstein(W)
+S == mscuspidal(W)
+
+W = msinit(23,2, 1);
+V = mssplit(W, msnew(W));
+msqexpansion(W, V[1], 30)
+msqexpansion(W, V[1])
+
+M=msinit(603,2,1);L=msnew(M);V=mssplit(M,L);
+Set([v|v<-vector(#V,i,msqexpansion(M,V[i])),type(v[1])=="t_INT"])
+
+W = msinit(6,4);
+m=msatkinlehner(W,1)
+matdet(m)
+m=msatkinlehner(W,2)
+matdet(m)
+m=msatkinlehner(W,3)
+matdet(m)
+m=msatkinlehner(W,6)
+matdet(m)
+msatkinlehner(W,4)
+msstar(W)
+
+N = msnew(W)[1];
+s = N[,1];
+msissymbol(W,s)
+S = mseval(W,s);
+msissymbol(W,S)
+T=S; T[3]++;
+msissymbol(W,T)
+
+M = msinit(7,8, 1);
+N = msnew(M)[1];
+s = N[,1];
+S = mseval(M,s);
+msissymbol(M, S)
+
+W=msinit(17,2);
+G=mspathgens(W)[1];
+vector(#G,i,mspathlog(W,G[i]))
diff --git a/src/test/in/modular b/src/test/in/modular
index caabcbc..362e7ac 100644
--- a/src/test/in/modular
+++ b/src/test/in/modular
@@ -27,3 +27,26 @@ Pol(0)*Mod(1,2)
 k=100000000000000000000;
 Mod(3,7)^-k
 Mod(3,7)^k
+
+\g1
+a=Mod(1,2);b=Mod(1,3);
+a+b
+a-b
+a*b
+a/b
+a+a
+a-a
+a*a
+a/a
+a=Mod(1,x);b=Mod(1,x+1);
+a+b
+a-b
+a*b
+a/b
+a+a
+a-a
+a*a
+a/a
+
+\\#1652
+p=436^56-35;lift(Mod(271,p)^((p-1)/2))
diff --git a/src/test/in/nf b/src/test/in/nf
index 4e9a1b7..ec14dc2 100644
--- a/src/test/in/nf
+++ b/src/test/in/nf
@@ -1,4 +1,4 @@
-\p38
+default(realprecision,38);
 setrand(1429412696);bnfinit(x^2+29051222508*x-12).clgp
 setrand(1); bnfinit(x^8 + 12*x^6 + 30*x^4 + 24*x^2 + 4).reg
 setrand(1); bnfinit(x^4 - 3*x^2 + 49).reg
@@ -26,7 +26,7 @@ try(f) = for (i=1, #v, for (j=1,#v, print( f(nf, v[i],v[j])) ))
 for (i = 1, #funs, try(funs[i]))
 
 nfisincl(nfinit(x-1),y)
-p=x^2+3;nfbasis(p, 0, factor(poldisc(p)))
+p=x^2+3;nfbasis([p, factor(poldisc(p))])
 
 \\#1253
 k=bnfinit(z^2+19*z+6,1); bnfisunit(k,k.fu[1]^2)
@@ -80,3 +80,22 @@ nfnewprec(vector(6))
 nfnewprec(vector(8))
 nfnewprec(vector(9))
 nfnewprec(vector(16))
+
+g=polcyclo(13);
+f=x^12-2*x^11+17*x^10-73*x^9+198*x^8-578*x^7+1533*x^6-3404*x^5+5716*x^4-8260*x^3+18652*x^2-25578*x+15601;
+nfisincl(f,g)
+
+\\#1631
+setrand(1);bnfinit(x^16-48*x^14+934*x^12-9632*x^10+57251*x^8-198568*x^6+386172*x^4-377776*x^2+137288).no
+
+K = nfinit(y^2-5);
+L = nfcompositum(K, x^5-y, polcyclo(5))
+L = nfcompositum(K, x^5-y, polcyclo(5), 1);
+[R,a,b,k] = L[1]
+a^5 - y
+liftall(b^5)
+L = nfcompositum(K, x^5-y, x^5-y)
+L = nfcompositum(K, x^5-y, polcyclo(3),2)
+L = nfcompositum(K, x^5-y, polcyclo(3),3)
+
+nfcompositum(nfinit(y),x,x^2+x+1,3)
diff --git a/src/test/in/nffactor b/src/test/in/nffactor
index a23b68f..a3579a0 100644
--- a/src/test/in/nffactor
+++ b/src/test/in/nffactor
@@ -52,7 +52,7 @@ do(y^16-24*y^12+80*y^10-172*y^8+192*y^6-112*y^4+32*y^2+4, x^16-24*x^12+80*x^10-1
 
 \\ Bug #959
 P=x^36+12*x^35-900*x^34-585*x^33+232905*x^32-1232184*x^31-15039873*x^30+110066100*x^29+430062960*x^28-3889034165*x^27-6885371553*x^26+72277665264*x^25+75990228525*x^24-788853282390*x^23-669954405945*x^22+5321235823803*x^21+4528671343041*x^20-22706777648475*x^19-20887787332600*x^18+62214414690960*x^17+62136364754205*x^16-111213087488775*x^15-118854042392850*x^14+131983619890275*x^13+148593402314775*x^12-105099439356375*x^11-122927027339625*x^10+56029221057500*x^9+67224101142000*x^8-195789 [...]
-#nfgaloisconj(nfinit([P,nfbasis(P,, factor(poldisc(P), 175069))]),1)
+#nfgaloisconj(nfinit([P,nfbasis([P, factor(poldisc(P), 175069)])]),1)
 
 \\ Bug #1006
 #do(y^24-12*y^23+72*y^22-286*y^21+849*y^20-2022*y^19+4034*y^18-6894*y^17+10182*y^16-13048*y^15+14532*y^14-13974*y^13+11365*y^12-7578*y^11+4038*y^10-1766*y^9+762*y^8-408*y^7+236*y^6-126*y^5+69*y^4-38*y^3+18*y^2-6*y+1,8*x^9+42*x^6+6*x^3-1)
diff --git a/src/test/in/nfields b/src/test/in/nfields
index 89ff6f1..6e3fd91 100644
--- a/src/test/in/nfields
+++ b/src/test/in/nfields
@@ -1,3 +1,4 @@
+HEAP=[213, if(precision(1.)==38,91496,101423)];
 default(realprecision,154); Pi; default(realprecision,38);
 dobnf(T,flag=0,tech=[])= setrand(1); my(K = bnfinit(T,flag,tech)); [K.cyc,K.fu];
 \e
@@ -81,13 +82,8 @@ bb=nfalgtobasis(nf,x^3+x)
 bc=matalgtobasis(nf,[x^2+x;x^2+1])
 matbasistoalg(nf,bc)
 nfbasis(x^3+4*x+5)
-nfbasis(x^3+4*x+5,2)
-nfbasis(x^3+4*x+12,1)
 nfbasistoalg(nf,ba)
-nfbasis(p2,0,fa)
 nfdisc(x^3+4*x+12)
-nfdisc(x^3+4*x+12,1)
-nfdisc(p2,0,fa)
 nfeltdiv(nf,ba,bb)
 nfeltdiveuc(nf,ba,bb)
 nfeltdivrem(nf,ba,bb)
@@ -143,5 +139,4 @@ zetak(nfz,1.5+3*I)
 \\
 setrand(1);quadclassunit(1-10^7,,[1,1])
 setrand(1);quadclassunit(10^9-3,,[0.5,0.5])
-sizebyte(%)
-getheap
+if (getheap()!=HEAP, getheap())
diff --git a/src/test/in/nfsplitting b/src/test/in/nfsplitting
new file mode 100644
index 0000000..5e3dd48
--- /dev/null
+++ b/src/test/in/nfsplitting
@@ -0,0 +1,10 @@
+nfsplitting(1)
+nfsplitting(Pol(0))
+nfsplitting(Pol(1))
+nfsplitting(x)
+nfsplitting(x^5-x-1)
+nfsplitting(x^8+3)
+nfsplitting(x^8+3,32)
+nfsplitting(nfinit(x^8+3))
+nfsplitting(x^5+5/4*x+1)
+nfsplitting(polcyclo(23))
diff --git a/src/test/in/objets b/src/test/in/objets
index abbae8a..bd15846 100644
--- a/src/test/in/objets
+++ b/src/test/in/objets
@@ -1,4 +1,3 @@
-HEAP=[63, if(precision(1.)==38,822,846)];
 default(realprecision,38);
 \e
 +3
@@ -59,4 +58,4 @@ padicno=(5/3)*127+O(127^5)
 padicprec(padicno,127)
 length(divisors(1000))
 Mod(10873,49649)^-1
-if (getheap()!=HEAP, getheap())
+(1+I)*(1+1/2*I)
diff --git a/src/test/in/op b/src/test/in/op
index 89f8ddc..d1fbc6c 100644
--- a/src/test/in/op
+++ b/src/test/in/op
@@ -3,4 +3,10 @@ b = 5; b \/= 2
 c = 5; c >>= 2
 d = 5; d <<= 1
 e = 5; e %= 3
+m=[a,b,c,d,e]
+a++
+e--
+m[2]--
+m[3]++
+m
 [a,b,c,d,e]
diff --git a/src/test/in/padic b/src/test/in/padic
index cf2bbc4..f0bf0d2 100644
--- a/src/test/in/padic
+++ b/src/test/in/padic
@@ -1,8 +1,8 @@
 padicappr(x,O(2))
 padicappr(x^2+1+O(3), Mod(-1+O(5^10),y^2-2))
 padicappr(x^2+1+O(3), -1+O(5^10))
-factorpadic(y^3+5*y,7,8,1)
 factorpadic(y^2+3^5,3,5)
+p=2^64+13; liftint(padicappr((x-1)^30+p^30, 1+O(p^40)))
 
 test(p, e = 1)=
 { my (N = 7*p^2);
diff --git a/src/test/in/parallel b/src/test/in/parallel
index 25feb21..c7c90c3 100644
--- a/src/test/in/parallel
+++ b/src/test/in/parallel
@@ -32,3 +32,5 @@ chkell(n)=a->my(E=ellinit([1,0,0,0,ffgen(2^n)^a]),N=ellcard(E)/4);if(isprime(N),
 ellp(n)=parfirst(chkell(n),[1..10000]);
 ellp(128)
 uninline();
+
+my(N=1);until(type(A)=="t_ERROR",A=alarm(1,parfor(i=1,10,for(i=1,N,isprime(i))));N*=2);
diff --git a/src/test/in/ploth b/src/test/in/ploth
index 2b07d56..55fc73f 100644
--- a/src/test/in/ploth
+++ b/src/test/in/ploth
@@ -10,12 +10,14 @@ plotcolor(0,2);
 plotmove(0,0,900); plotlines(0,900,0)
 plotlines(0,vector(5,k,50*k),vector(5,k,10*k*k))
 plotmove(0,243,583); plotcursor(0)
+plot(x=-1,1,floor(x))
+plot(x=-1,1,-floor(x))
+plot(x=0,1,-0.29)
 plot(x=-5,5,sin(x))
 ploth(x=-5,5,sin(x))
 ploth(t=0,2*Pi,[sin(5*t),sin(7*t)])
-ploth(t=0,2*Pi,[sin(5*t),sin(7*t)],1,100)
-ploth(t=0,2*Pi,[sin(5*t),sin(7*t)],2,100)
-ploth(t=0,2*Pi,[sin(5*t),sin(7*t)],3,100)
+ploth(t=0,2*Pi,[sin(5*t),sin(7*t)],"Parametric",100)
+ploth(t=0,2*Pi,[sin(5*t),sin(7*t)],"Parametric|Recursive",100)
 plothraw(vector(501,k,k-1),vector(501,k,(k-1)*(k-1)/500));
 plothraw(vector(501,k,k-1),vector(501,k,(k-1)*(k-1)/500),1);
 plotpoints(0,225,334)
@@ -32,5 +34,47 @@ plotmove(0,100,100); plotstring(0,Pi)
 plotmove(0,200,200); plotstring(0,"(0,0)")
 plotdraw([0,10,10])
 psdraw([0,10,10])
-ploth(x=0,2*Pi,if (x <1, [cos(x),sin(x)], 1),1)
+ploth(x=0,1, x^3,"Splines")
+ploth(x=0,1, [x^2,x^3],"Parametric|Splines")
+plotinit(1);
+plotcopy(0,1, 300,0);
+plotclip(1);
+plotdraw([1,10,10]);
+plotkill(1);
+
+plotinit(1);
+plotcopy(0,1, 1/2,0, 1);
+plotclip(1);
+plotdraw([1,10,10]);
+plotkill(1);
+
+plotinit(1);
+plotcopy(0,1, 1/2,1/3, 3);
+plotclip(1);
+plotdraw([1,10,10]);
+plotkill(1);
+
+plotinit(1);
+plotcopy(0,1, 1/3,1/3, 5);
+plotclip(1);
+plotdraw([1,10,10]);
+plotkill(1);
+
+plotinit(1);
+plotcopy(0,1, 1/3,1/3, 7);
+plotclip(1);
+plotdraw([1,10,10]);
+
+/*errors*/
+plotinit(-1)
+plotinit(100)
+plotmove(-1,0,0)
+plotmove(100,0,0)
+plotcopy(0,1,2,1,1)
+plotcopy(0,1,-1,1,1)
+plotcopy(0,1,1,2,1)
+plotcopy(0,1,1,-1,1)
+ploth(x=0,2*Pi,if (x <1, [cos(x),sin(x)], 1),"Parametric")
+ploth(t=0,2*Pi,[sin(5*t),sin(7*t)],"Recursive",100)
+ploth(x=0,2*Pi,1,"Parametric")
 ploth(x=0,1,x,,1)
diff --git a/src/test/in/pol b/src/test/in/pol
index e02dfd3..02fcf93 100644
--- a/src/test/in/pol
+++ b/src/test/in/pol
@@ -13,6 +13,8 @@ o = [2*x+3*y, 2+x+y+O(x^2), 2+x+y+O(y^2)];
     printsep(" ",pollead(v), pollead(v,x), pollead(v,y))
   )
 }
+pollead(z,y)
+pollead(y,z)
 polgraeffe(x^2+x+1)
 polgraeffe(x^3+x+1)
 polsym(2*x^4+1,4)
@@ -20,3 +22,9 @@ norm(I*x+1)
 trace(I*x+1)
 matcompanion(2*x^2+1)
 Pol("")
+serlaplace(1+x+x^2)
+serlaplace(x^2+x^3)
+
+\\#1651
+f1=(x-1)/(x*x-x);
+type(subst(1/f1,x,1))
diff --git a/src/test/in/polclass b/src/test/in/polclass
new file mode 100644
index 0000000..5379507
--- /dev/null
+++ b/src/test/in/polclass
@@ -0,0 +1,66 @@
+hash_base = 2^64;
+init_h = 5381;
+
+split_Z(n) =
+{
+    my (bits = 8, base = 2^bits, sgn = sign(n) % base, res = []);
+    n = abs(n);
+    while (n != 0,
+           res = concat(res, bitand(n, base - 1));
+           n = shift(n, -bits));
+    res = concat(res, sgn);
+}
+
+glue(h, a) = bitand((((h << 5) + h) + a), hash_base - 1);
+
+hash_Z(n) =
+{
+    my (v = split_Z(n), h = init_h);
+    for (i = 1, #v, h = glue(h, v[i]));
+    h;
+}
+
+hash_ZX(pol) =
+{
+    my (v = Vec(pol), h = init_h);
+    for (i = 1, #v, h = glue(h, hash_Z(v[i])));
+    h;
+}
+
+
+check_disc(D, hash, seed = 0) =
+{
+    if (seed != 0, setrand(seed));
+    if (hash_ZX(polclass(D)) != hash, error("Wrong class polynomial for D = ", D));
+}
+
+{
+D = [-3, -4, -7, -8, -11, -20, -23, -39, -47, -87, -71, -95, -56,
+     -264, -152, -3792, -7139, -163, -24, -40, -131, -451, -356,
+     -120, -311, -335, -519, -84, -271, -167, -231, -280, -251, -1620];
+
+H = [199415601, 392824566, 392666638, 392685999, 392619250, 427908603366,
+     466294765623259, 16505852200663133551, 6402944422652024363, 4174888675786545598,
+     9700283236680509421, 13008454496997756490, 11998671908550620494, 12912619012374504058,
+     10731008721722142465, 7620467061686776546, 12274439570299924406, 249740438023929931,
+     7166885172778, 236296854599224, 8331420221009258450, 14359598510137794606,
+     4527984144770046237, 6891115741722954474, 15021837413190908510, 17672415898312866530,
+     13506744947615842737, 4664273993601588884, 4652420391100252414, 2826053336532203363,
+     6425030865187792225, 6063510379317462346, 5232582682029074054, 1232737106430825415
+     ];
+
+for (i = 1, #D, check_disc(D[i], H[i]));
+
+DR = [[-75, 7797221584007659, 376671349665989785645468855509664073846994182881400101766546260394720617934366189060409433769160357181533432220573885805924825693540852008021952564459774590810585211475243394327684717245750110745945026072328072760225571953639433771639283459668005522842154890829456908826675941553773883099694408386765914172430146193260890042281309331937613624260297092915479077192844416843235737033853226359061755041806842898913531132580673421160537655521664429456369047671439914 [...]
+      [-243, 10890205224450786941, 8198165390033377039515510303344919858112195907358086501800841424258890874282789684748169670787886944965209475446322478451482939601284311842164299133755647389834351201713728704638330595399194752401157553414478598567401484634380916311478173940802770375771893182644947068217213459832570072076049765656590024454595337527564034395945951479548771847279592823335989336905238902224865748623382772716516033755517221916244355925520607760020531344617390501231890555988 [...]
+      [-588, 879637271447453785, 722172781875446948725027515502840397805803222574263498938157594834753683539692286353539379550260903961870953681724730652335944539054343214809842109182109376376073404934944783430561780090926711128352240351787729618963067414744940653491552049787247397068335298858059915825702852961307136083870626600760767835946633951456834700248463253765418088580513814400067434333278000748727896494114214077094766308557268821917667449381466097345351641374194851269731747888023 [...]
+      [-1936, 12042224483327737942, 121686610233308813022652448791314420876373495991710369134596940920751686829171835436318316807996516289586816411045406829585240391368706389731607645673218024431469349111185907266884595182617646131522123005888201679922170915515295247196401273633088545108991113634052185192113728873171164598501865320798702459482144952195547997607291749765570481113646935591773373020253702875909839569389116812785372368872846168754752469298092468100973977806291668859927460092 [...]
+
+for (i = 1, #DR, check_disc(DR[i][1], DR[i][2], DR[i][3]));
+
+my (got_err = 0);
+iferr(polclass(-5), err, got_err = 1, errname(err) == "e_DOMAIN");
+if ( ! got_err, error("No error when given non discriminant"));
+
+if (variable(polclass(-7, 'z)) != 'z, error("Didn't use user-provided variable"));
+}
diff --git a/src/test/in/polmodular b/src/test/in/polmodular
new file mode 100644
index 0000000..4812af5
--- /dev/null
+++ b/src/test/in/polmodular
@@ -0,0 +1,150 @@
+hash_base = 2^64;
+init_h = 5381;
+
+split_Z(n) =
+{
+    my (bits = 8, base = 2^bits, sgn = sign(n) % base, res = []);
+    n = abs(n);
+    while (n != 0,
+           res = concat(res, bitand(n, base - 1));
+           n = shift(n, -bits));
+    res = concat(res, sgn);
+}
+
+glue(h, a) = bitand((((h << 5) + h) + a), hash_base - 1);
+
+hash_Z(n) =
+{
+    my (v = split_Z(n), h = init_h);
+    for (i = 1, #v, h = glue(h, v[i]));
+    h;
+}
+
+hash_ZX(pol) =
+{
+    my (v = Vec(pol), h = init_h);
+    for (i = 1, #v, h = glue(h, hash_Z(v[i])));
+    h;
+}
+
+hash_ZXX(pol) =
+{
+    my (v = [Vec(c) | c <- Vec(pol)], h = init_h);
+    for (i = 1, #v, h = glue(h, hash_ZX(v[i])));
+    h;
+}
+
+{
+lvl_idx = [0, 1, 2, 0, 3, 0, 4, 0, 0, 0, 5, 0, 6, 0, 0, 0, 7, 0, 8, 0, 0, 0, 9];
+modpoly_hashes = [
+953115400354185,
+619732354788530567,
+7671381920119322245,
+1662362517513198972,
+11499552816775494464,
+10945716853871337038,
+1858790070632847848,
+16279119036202003022,
+9091292905489559584
+];
+
+}
+
+check_modpoly(L) =
+{
+    if (hash_ZXX(polmodular(L)) != modpoly_hashes[lvl_idx[L]],
+        error("Bad modpoly"));
+}
+
+{
+MAX_LEVEL = 23;  \\ This already gives 89% coverage in 1.2s
+forprime(L = 2, MAX_LEVEL, check_modpoly(L));
+
+\\ Check that specifying variables works
+my (phi7 = polmodular(7));
+if (phi7 != polmodular(7, 'x, 'y) || phi7 != polmodular(7, 'x)
+    || polmodular(7, 's, 't) != substvec(phi7, ['x, 'y], ['s, 't]),
+    error("Bad variables"));
+
+\\ Check argument checking
+my (got_err);
+iferr (polmodular(7, "I am the queen of France", 'x),
+       err, got_err = 1, errname(err) == "e_TYPE");
+if ( ! got_err, error("No type error from bad param"));
+
+got_err = 0;
+iferr (polmodular(7, ffgen(2^3), 'x),
+       err, got_err = 1, errname(err) == "e_DOMAIN");
+if ( ! got_err, error("No domain error from non-prime field arg"));
+
+got_err = 0;
+iferr (polmodular(1), err, got_err = 1, errname(err) == "e_DOMAIN");
+if ( ! got_err, error("No error from level 1"));
+
+got_err = 0;
+iferr (polmodular(6), err, got_err = 1, errname(err) == "e_IMPL");
+if ( ! got_err, error("No error from composite level"));
+
+got_err = 0;
+iferr (polmodular(nextprime(5000)), err, got_err = 1, errname(err) == "e_IMPL");
+if ( ! got_err, error("No error from huge level"));
+
+got_err = 0;
+iferr (polmodular(7, 'x, 'y, 1), err, got_err = 1, errname(err) == "e_FLAG");
+if ( ! got_err, error("No error from inappropriate flag"));
+
+got_err = 0;
+iferr (polmodular(7, 'x, 'x), err, got_err = 1, errname(err) == "e_PRIORITY");
+if ( ! got_err, error("No error from same variables"));
+
+got_err = 0;
+iferr (polmodular(7, 'y, 'x), err, got_err = 1, errname(err) == "e_PRIORITY");
+if ( ! got_err, error("No error from bad variables"));
+}
+
+all(v) = { my (r = 1); for (i = 1, #v, r = r && v[i]); r; }
+poloftype(f, tp) =
+{
+    type(f) == "t_POL" && all([type(polcoeff(f, d)) == tp | d <- [0 .. poldegree(f)]]);
+}
+
+lift_ffx(f) =
+{
+    my (v = Vec(f));
+    if ( ! all([poldegree(c.pol) == 0 | c <- v]),
+        error("Polynomial has coeffs in extension"));
+    Pol([polcoeff(c.pol, 0) | c <- Vec(f)], variable(f));
+}
+
+check_eval_modpoly(L, j, p, expected) =
+{
+    my (jm = Mod(j, p),
+        jf = j * ffgen(p)^0,
+        um = polmodular(L, jm, 'y, 0),
+        uf = polmodular(L, jf, 'y, 0),
+        vm = polmodular(L, jm, 'y, 1),
+        vf = polmodular(L, jf, 'y, 1));
+    if ( ! poloftype(um, "t_INTMOD") || ! poloftype(uf, "t_FFELT")
+        || type(vm) != "t_VEC" || #vm != 3 || type(vf) != "t_VEC" || #vf != 3,
+        error("Invalid return type"));
+    if ( ! all([poloftype(v, "t_INTMOD") | v <- vm])
+        || ! all([poloftype(v, "t_FFELT") | v <- vf]),
+        error("Invalid coefficients"));
+
+    if (um != vm[1] || uf != vf[1] || lift(um) != lift_ffx(uf) || hash_ZX(lift(um)) != expected[1],
+        error("Wrong result for modpoly eval"));
+    if (hash_ZX(lift(vm[2])) != expected[2],
+        error("Wrong derivative"));
+    if (hash_ZX(lift(vm[3])) != expected[3],
+        error("Wrong second derivative"));
+}
+
+{
+my (p = nextprime(2^40));
+check_eval_modpoly( 5, 7, 151, [8033941431460000, 243641761686181, 243612090562303]);
+check_eval_modpoly(19, 7, 151, [11844895572672018496, 369501438945078285, 13082720985735388448]);
+\\check_eval_modpoly( 5, 7, factorial(12), XXXX);
+check_eval_modpoly( 5, 7, p, [3901199766181530739, 4054334766401667256, 16751141247645108349]);
+\\check_eval_modpoly(23, 7, factorial(12), XXXX);
+check_eval_modpoly(23, 7, p, [2360118342899681926, 2787294817779511277, 18359991236545579908]);
+}
diff --git a/src/test/in/polred b/src/test/in/polred
index 4902bed..6b4e89a 100644
--- a/src/test/in/polred
+++ b/src/test/in/polred
@@ -53,3 +53,7 @@ polredord(4*x^2+1)
 polredbest(x^8+24*x^6+80*x^5+1040*x^4-4288*x^3-12736*x^2-61952*x+311296,1)
 \\ #1511
 polredabs(x^16-4*x^15-334*x^14+264*x^13+32231*x^12+57392*x^11-1031422*x^10-3628868*x^9+7185297*x^8+42417784*x^7+11283472*x^6-137773504*x^5-127243504*x^4+69059728*x^3+56307944*x^2-6264432*x+6436)
+\\ #1653
+default(parisize, 3<<23);
+f=x^40+10*x^39+75*x^38+410*x^37+1888*x^36+7364*x^35+25310*x^34+77140*x^33+211669*x^32+524946*x^31+1183823*x^30+2430610*x^29+4548530*x^28+7743916*x^27+11954920*x^26+16627228*x^25+20626386*x^24+22445616*x^23+20835590*x^22+15611648*x^21+8209812*x^20+1290846*x^19-2562740*x^18-2525172*x^17-76374*x^16+2095346*x^15+2320830*x^14+1050748*x^13-71120*x^12-238080*x^11+31952*x^10+106808*x^9+12549*x^8-18470*x^7-485*x^6+3202*x^5-232*x^4-430*x^3+150*x^2-20*x+1;
+polredbest(f);
diff --git a/src/test/in/polyser b/src/test/in/polyser
index 1c4ca26..72271d3 100644
--- a/src/test/in/polyser
+++ b/src/test/in/polyser
@@ -1,4 +1,4 @@
-HEAP=[62, if(precision(1.)==38,7190,7252)];
+HEAP=[61, if(precision(1.)==38,7092,7154)];
 default(realprecision,154); Pi; default(realprecision,38);
 \e
 apol=y^3+5*y+1
@@ -9,7 +9,6 @@ direuler(s=1,40,1+s*X+s^2*X)
 dirmul(abs(dm),dz)
 zz=yy;yy=xx;eval(zz)
 factorpadic(apol,7,8)
-factorpadic(apol,7,8,1)
 intformal(sin(x))
 intformal((-x^2-2*a*x+8*a)/(x^4-14*x^3+(2*a+49)*x^2-14*a*x+a^2))
 newtonpoly(x^4+3*x^3+27*x^2+9*x+81,3)
diff --git a/src/test/in/pow b/src/test/in/pow
index bef4286..e86958a 100644
--- a/src/test/in/pow
+++ b/src/test/in/pow
@@ -34,3 +34,6 @@ Mod(1,4)^(1/2)
 sqrt(1+O(2))
 sqrt(1+O(2^3))
 sqrt(Mod(2,4))
+
+powers(Mod(2,11),10)
+powers(Pi,7)
diff --git a/src/test/in/prec b/src/test/in/prec
index 627862e..91243a0 100644
--- a/src/test/in/prec
+++ b/src/test/in/prec
@@ -9,6 +9,7 @@ precision([1+O(3),2],3)
 default(realprecision,38);
 t=(precision(1.,77)*x+1);
 precision(t)
+localprec(57);precision(1.)
 precision(1./t)
 precision(Qfb(1,0,-2));
 
diff --git a/src/test/in/primes b/src/test/in/primes
index e39aca6..66b838a 100644
--- a/src/test/in/primes
+++ b/src/test/in/primes
@@ -1,6 +1,10 @@
 primes(50)
+primes([-5,5])
 primes([10,20])
 primes([2^32-100,2^32+100])
 primes([2^64-100,2^64+100])
+#primes([2^50,2^50+200000])
 #primes([10^7, 10^7+10^6])
 #primes([2^1023+5000, 2^1023+7000])
+\\#1668
+primes([1,Pol(2)]);
diff --git a/src/test/in/printf b/src/test/in/printf
index 7e0491e..a9931b0 100644
--- a/src/test/in/printf
+++ b/src/test/in/printf
@@ -73,3 +73,4 @@ printf("%c",97+1/2)
 printf("%c",97 + 0.*I)
 printf("%c",97 +0*quadgen(5))
 printf("%1.2f",Mat([1.,2.]))
+printf("%c",'x)
diff --git a/src/test/in/qfb b/src/test/in/qfb
index 1e1ac6d..eaf0769 100644
--- a/src/test/in/qfb
+++ b/src/test/in/qfb
@@ -14,7 +14,16 @@ qfbpowraw(q,3)
 qfbred(q3,1)
 q=Qfb(1009, 60, 99108027750247771)
 qfbnupow(q, 8839368315)
-qfbred(Qfb(22000957029, 25035917443, 7122385192))
+q=Qfb(22000957029,25035917443,7122385192);
+qfbred(q)
+qfbredsl2(q)
+q=Qfb(1099511627776,1879224363605,802966544317);
+qfbredsl2(q)
+D=poldisc(q);
+qfbredsl2(q,[D,sqrtint(D)])
+qfbredsl2(q,[D]);
+qfbredsl2(q,[D,1.]);
 p=2^64+13;
 qfbprimeform(-4,p)
 qfbprimeform(5,p)
+
diff --git a/src/test/in/qfbclassno b/src/test/in/qfbclassno
new file mode 100644
index 0000000..c034362
--- /dev/null
+++ b/src/test/in/qfbclassno
@@ -0,0 +1,16 @@
+qfbclassno(-44507759)
+qfbclassno(-57403799)
+qfbclassno(-94361767)
+qfbclassno(-111385627)
+qfbclassno(-136801204)
+qfbclassno(-185415288)
+qfbclassno(-198154147)
+qfbclassno(-223045972)
+qfbclassno(-1253840791)
+qfbclassno(-1382998299)
+qfbclassno(-1567139127)
+qfbclassno(-1788799151)
+qfbclassno(-1850979435)
+qfbclassno(-4386842803)
+qfbclassno(-5082406399)
+
diff --git a/src/test/in/qfsolve b/src/test/in/qfsolve
new file mode 100644
index 0000000..ad80a74
--- /dev/null
+++ b/src/test/in/qfsolve
@@ -0,0 +1,35 @@
+{M=[[-634,-706,-200;-706,527,-110;-200,-110,-997],[-670,164,205;164,-391,-509;205,-509,-117],[586,-448,120;-448,-342,-233;120,-233,-851],[-387,-147,450;-147,-808,-22;450,-22,-119],[739,-44,-48;-44,-739,-134;-48,-134,459],[-519,-45,-514;-45,324,178;-514,178,-83],[-482,-683,18;-683,705,852;18,852,315],[808,-16,555;-16,-723,-538;555,-538,-66],[243,205,-14;205,-119,853;-14,853,891],[-220,10,-564;10,-440,-9;-564,-9,413],[383,66,53;66,-962,-104;53,-104,300],[-845,257,264;257,-7,-866;264,-866,2 [...]
+TEST(deb=1,fin=6)=
+{
+  for(i=deb,fin,
+    print("dim=",i+2);
+    for(j=1,100,
+      Q=M[i,j];
+      s=qfsolve(Q);
+      if(type(s)=="t_INT", print([j,s]), if(s~*Q*s, error(Q)));
+    );
+  );
+}
+TEST()
+
+G = [1,0,0;0,1,0;0,0,-34];
+qfparam(G, qfsolve(G))
+qfparam(G, qfsolve(G),1)
+qfparam(G, qfsolve(G),2)
+
+qfsolve(Mat(0))
+qfsolve(Mat(1))
+qfsolve([1,2;2,1])
+qfsolve([0,1;1,1])
+qfsolve([35, 46; 46, 60])
+
+qfparam(matdiagonal([1,1,-1]),[1,0,1])
+qfsolve(matdiagonal([1,1,-25]))
+
+qfsolve([1,0,0;0,3,0;0,0,-2])
+qfparam([0,0,-12;0,-12,0;-12,0,-1],[1,0,0]~,3)
+q=[-1,-4,-8;-4,-15,-31;-8,-31,-62]/4; qfparam(q,qfsolve(q))
+
+\\#1661
+qfsolve([1,0,0;0,1,1;0,0,1]);
+
diff --git a/src/test/in/quadray b/src/test/in/quadray
index 5040344..ca7b13d 100644
--- a/src/test/in/quadray
+++ b/src/test/in/quadray
@@ -17,3 +17,20 @@ Q(-251,2)
 Q(-35,2)
 Q(-4,31)
 Q(-51,3)
+Q(8-48*3,2)
+Q(1-48*3,3)
+Q(1-48*3,4)
+Q(40-48*3,6)
+Q(-7,7)
+
+K = bnfinit(y^2+5);
+P5=idealprimedec(K,5)[1];
+Q(K,P5)
+
+K = bnfinit(y^2+5*12);
+P2=idealprimedec(K,2)[1];
+P5=idealprimedec(K,5)[1];
+Q(K,idealmul(K,P2,P5))
+
+\\#1633
+quadray(-11,3)
diff --git a/src/test/in/random b/src/test/in/random
index 2d871e1..4672036 100644
--- a/src/test/in/random
+++ b/src/test/in/random
@@ -11,6 +11,7 @@ random(Mod(1,3))
 doff(2,3)
 doff(precprime(2^32), 3)
 doff(nextprime(2^64), 3)
+default(realprecision,38)
 random(1.)
 random(x^5*Mod(1,7))
 randomprime(2)
diff --git a/src/test/in/real b/src/test/in/real
index 10dcf92..73db5fb 100644
--- a/src/test/in/real
+++ b/src/test/in/real
@@ -1,4 +1,37 @@
+{
+if (precision(1.)==38,
 \\ #1322
-default(realprecision,19)
-1. << 2^60
-1. >> 2^60
+  default(realprecision,2);
+  print(1. << 2^60);
+  print(1. >> 2^60);
+,
+\\ can't be tested on 32-bit kernel: fake answer
+  print("5.9 E347063955532709820");
+  print("1.7 E-347063955532709821");
+);
+}
+1. << 2^64
+1. >> 2^64
+
+1+0e1
+0e1==1
+0e1==1.
+0e1<1
+0e1<1.
+0e1<=1
+0e1<=1.
+0e1>1
+0e1>1.
+0e1>=1
+0e1>=1.
+
+0e-1==1
+0e-1==1.
+0e-1<1
+0e-1<1.
+0e-1<=1
+0e-1<=1.
+0e-1>1
+0e-1>1.
+0e-1>=1
+0e-1>=1.
diff --git a/src/test/in/resultant b/src/test/in/resultant
index 5680268..ac6eabf 100644
--- a/src/test/in/resultant
+++ b/src/test/in/resultant
@@ -1,3 +1,5 @@
+k;c;d;e;f;g;junk2;junk3;b;h;j;a;z;x2;x3;x4;x1;
+
 allocatemem(20*10^6);
 do(P,Q)=my(v=variable()); substvec(polresultant(P,Q), v, vector(#v,i,i));
 
@@ -75,3 +77,7 @@ poldisc(x^3 + Mod(2,3)*x^2+1)
 norm(Mod(Pol(Mod(0,2)), 3*x))
 
 polresultantext(x+1, x^2)
+\\#1614
+polresultant(1+x*z^2,1+y*z^4,z)
+
+polcompositum(x^5-5,x^4-2,2)
diff --git a/src/test/in/rnf b/src/test/in/rnf
index 9e72dab..b7f6fda 100644
--- a/src/test/in/rnf
+++ b/src/test/in/rnf
@@ -52,6 +52,21 @@ K = nfinit(z^3+z^2-2*z-1); rnf = rnfinit(K, x^2+Mod(-z,z^3+z^2-2*z-1)*x+1);
 a = rnfeltup(rnf,z^2)
 rnfeltdown(rnf, a)
 
+setrand(1);a=matrix(3,4,j,k,vectorv(3,l,random(21)));
+idx=idealprimedec(K,3)[1];
+aid=[idx,1,1,1];
+[A,U]=nfhnf(K,[a,aid],1);
+A
+U
+lift(matbasistoalg(K,a)*matbasistoalg(K,U))
+
+a=a[,1..3];
+[A,U,V]=nfsnf(K,[a, aid[1..3], [1,1,1]],1);
+A
+U
+V
+lift(matbasistoalg(K,U)*matbasistoalg(K,a)*matbasistoalg(K,V))
+
 nf=nfinit(y); A = [[1,1/2;0,1],[1,1]];
 nfhnfmod(nf, A, nfdetint(nf,A))
 
diff --git a/src/test/in/rnfkummer b/src/test/in/rnfkummer
index f9b6e3e..d1472d5 100644
--- a/src/test/in/rnfkummer
+++ b/src/test/in/rnfkummer
@@ -8,7 +8,8 @@ do(y^4+12*y^3+15*y^2+15*y-15,1)
 do(y^4-13*y^3+2*y^2+2*y-15,1)
 do(y^4-y^3-2404*y^2+2404*y+1154401, 5, matdiagonal([5,1]))
 do(quadpoly(-8,y), 11, [5,2;0,1])
-do(quadpoly(181433,y),1)
+\\ behaviour depend on kernel (bnfinit(Kz) too complicated
+\\do(quadpoly(181433,y),1)
 do(quadpoly(-1752,y), 19, matdiagonal([5,1,1]))
 do(nf=nfinit(y^6-2*y^5+3*y^4+y^2+3*y+1), idealprimedec(nf,2)[1])
 do(y^4-52*y^2+26, 3, Mat(5))
@@ -43,3 +44,10 @@ do(y^4 - 34*y^2 + 1189, 5, matdiagonal([3,1,1]))
 
 do(y, [36,[1]], matdiagonal([3,1]), 3)
 
+do(y, [36,[1]], matdiagonal([3,1]))
+
+K=bnrinit(bnfinit(y^4-y^3+16*y^2-16*y+61),[89,9,52,85;0,1,0,0;0,0,1,0;0,0,0,1],1);
+rnfkummer(K,,5)
+
+\\ #1632
+do(quadpoly(3409,y),25,[5,1;0,1])
diff --git a/src/test/in/rootsreal b/src/test/in/rootsreal
new file mode 100644
index 0000000..a94314c
--- /dev/null
+++ b/src/test/in/rootsreal
@@ -0,0 +1,45 @@
+default(realprecision,38);
+T=x^3-6*x^2+11*x-6;
+polrootsreal(T)
+polrootsreal(T, [-oo,3/2])
+polrootsreal(T, [3/2,6])
+polrootsreal(T, [-oo,+oo])
+polrootsreal(T, [2,3])
+polrootsreal(T, [1,2])
+polsturm(T, [-oo,3/2])
+polsturm(T, [3/2,6])
+polsturm(T, [-oo,+oo])
+polsturm(T, [2,3])
+polsturm(T, [1,2])
+polsturm(T, [1,+oo])
+polsturm(T, 2,3)
+polsturm(T, 2.,3)
+polsturm(T,,2)
+polrootsreal(x^10 + 23*x^9 + 19*x^8 + 18*x^7 + 39*x^6 + 41*x^5 + 46*x^4 + 24*x^3 - 4*x^2 + 2*x + 42)
+polrootsreal(polchebyshev(9))
+polrootsreal(polchebyshev(10))
+polrootsreal(x^0)
+polrootsreal(1)
+polrootsreal(0)
+polrootsreal(Pol(0))
+polrootsreal(Mod(1,2))
+
+polroots(T*x+0.)
+polroots(1)
+polrootsreal(T,[1,1])
+polrootsreal(T,[0,0])
+polsturm(T,[1,1])
+polsturm(T,[2,1])
+
+U=(x^2-1)*(x-2);
+polsturm(U)
+polsturm(U,[-oo,1])
+polsturm(U,[-1,+oo])
+
+polrootsreal(x^3-2)
+polrootsreal(x^3+2)
+\\#1605
+polsturm(33*x^2-4*x-1)
+polrootsreal(4*x)
+polsturm(-4*x)
+polsturm((x^4-2)^2)
diff --git a/src/test/in/round b/src/test/in/round
index d588294..24ad620 100644
--- a/src/test/in/round
+++ b/src/test/in/round
@@ -8,6 +8,6 @@ test(floor)
 test(frac)
 test(round)
 round(0,&E);
-test(x->[round(x,&e), if(e==E,-'oo,e)])
+test(x->[round(x,&e), if(e==E,-oo,e)])
 test(truncate)
-test(x->[truncate(x,&e), if(e==E,-'oo,e)])
+test(x->[truncate(x,&e), if(e==E,-oo,e)])
diff --git a/src/test/in/round4 b/src/test/in/round4
index 1ec20e5..3057246 100644
--- a/src/test/in/round4
+++ b/src/test/in/round4
@@ -460,9 +460,9 @@ nfdisc(x^72-75690*x^66+2229471657*x^60-36061389458264*x^54+392606586400579
 }
 
 f=x^3 - 17298759218009623610183566031041339386720075700346652258609213718601496711017550 61362121841699226629974891813971909562156420018402691827454215309735885355556958 2565670693186076986600637143595083773458690435867304359843677566038921950799648* x^2 + 18711064803260370378157988406301782093292956776803873824168436875360414402394604 63586013733720488993651052248629894449551488639706757608435718517657626971261696 1979263694661040207430295034473827583701817472886223534079585752374021477 [...]
-d=poldisc(f); e=valuation(d,2); valuation(nfdisc(f, [2, e; d/2^e, 1]),2)
-valuation(nfdisc(f, [2]), 2)
+d=poldisc(f); e=valuation(d,2); valuation(nfdisc([f, [2,e; d/2^e,1]]),2)
+valuation(nfdisc([f, [2]]), 2)
 
 T = (x+1)^2 + 3*5^2*7^31;
-P = [[7], [5,7], factor(poldisc(T)), 7, 2, 1];
-for (i=1,#P, print(nfbasis(T,P[i]), ", ", nfdisc(T,P[i])));
+P = [[7], [5,7], factor(poldisc(T)), 7, 2];
+for (i=1,#P, print(nfbasis([T,P[i]]), ", ", nfdisc([T,P[i]])));
diff --git a/src/test/in/select b/src/test/in/select
index 51fef21..eaed48a 100644
--- a/src/test/in/select
+++ b/src/test/in/select
@@ -4,3 +4,6 @@ select(isprime, List([1,2,3,4,5]))
 select(x->(x<100), %)
 select(x->x, [0,1,2;0,2,0])
 select(x->!x, [0,1,2;0,2,0])
+
+[x|x<-List(),x%2]
+[x|x<-List([1..4]), x%2]
diff --git a/src/test/in/self b/src/test/in/self
new file mode 100644
index 0000000..502498a
--- /dev/null
+++ b/src/test/in/self
@@ -0,0 +1 @@
+(n->if(n==0,1,n*self()(n-1)))(5)
diff --git a/src/test/in/ser b/src/test/in/ser
index 3f16965..9f99c7c 100644
--- a/src/test/in/ser
+++ b/src/test/in/ser
@@ -5,6 +5,7 @@ f=[atan,asin,acos,cosh,sinh,tanh,acosh,asinh,atanh];
 for (i=1,#f,
   print(f[i](s));
   print(f[i](O(x^5)));
+  print(f[i]([Pol(1)]));
 )
 }
 O(x^-2)
@@ -20,3 +21,33 @@ serreverse(tan(x)/2)
 Ser(x+y+O(x^2),x)
 Ser(x+y+O(x^2),y)
 Ser("")
+s = Ser(Mod(0,7))
+Ser(Mod(1,7)*(x^4+x^2), x,3)
+s+O(x^16)
+s+Mod(1,7)
+s+Mod(1,7)*x
+s/x
+s'
+deriv(s,y)
+trace(s)
+round(s)
+round(s,&e)
+lift(s)
+lift(s,x)
+liftint(s)
+Ser(x,, -5)
+O(x^2)*0
+deriv(Mod(2,4)*x^2+O(x^3))
+x^3*(1+O(y^2))
+Mod(1,3)*x^3*(1+O(y^2))
+O(x)/2
+s = O(3^2)+O(x);
+s/3
+s/2
+s*3
+(1+O(x))^2
+1/(x+0.)+O(x^2)
+[1==O(x), 1==O(x^0), 1==O(x^-1)]
+[-1==O(x), -1==O(x^0), -1==O(x^-1)]
+[2==O(x), 2==O(x^0), 2==O(x^-1)]
+
diff --git a/src/test/in/size b/src/test/in/size
index b098e64..0a3783e 100644
--- a/src/test/in/size
+++ b/src/test/in/size
@@ -1,4 +1,5 @@
 default(realprecision,38)
+#0.
 #1
 #1. == if (#(2^32)==1, 2, 4)
 length([x])
diff --git a/src/test/in/subgroup b/src/test/in/subgroup
index 276447c..9f2c3d2 100644
--- a/src/test/in/subgroup
+++ b/src/test/in/subgroup
@@ -8,3 +8,9 @@ forsubgroup(h=[],[2],print(h))
 forsubgroup(h=[],2,print(h))
 forsubgroup(h=[2,3],2,print(h))
 forsubgroup(h=matid(2),2,print(h))
+default(debug,5);
+#subgrouplist(vector(4,i,2))
+default(debug,0);
+subgrouplist(1)
+subgrouplist([2,2],[2]~)
+subgrouplist([2,2],-1)
diff --git a/src/test/in/sumdiv b/src/test/in/sumdiv
index 566ec43..2ee6e35 100644
--- a/src/test/in/sumdiv
+++ b/src/test/in/sumdiv
@@ -39,3 +39,6 @@ sumdiv(n, d, d)
 sumdiv(fa, d, d)
 sumdivmult(n, d, d)
 sumdivmult(fa, d, d)
+
+\\#1664
+divisors([1,2])
diff --git a/src/test/in/thue b/src/test/in/thue
index daff338..d27a3d3 100644
--- a/src/test/in/thue
+++ b/src/test/in/thue
@@ -26,3 +26,45 @@ thue((x^2+1)^2*(x^2-2),-4)
 thue(x^3-12*x-13,87)
 thue(x^3-537825*x^2+537824*x+1, 1)
 thue(thueinit(x^3-x-1),1578191)
+thue((10946*x-6765)*(x^2+x-1), 1)
+thue((x^3-2)^2,-4)
+thue((x^3-2)^2,4)
+thue((x^3-2)^3,-8)
+thue((x^3-x+1)^3,-512)
+thue((2*x^3+2)^3*(x+1)^3, 157464)
+thue(x^4+1,20^30+3)
+thue(-(x^4+1),10^20)
+thue(x^2+x+1, 7*13*11^2*10^4)
+do(T,a)=
+{
+  my(L = thue(T,a), d = poldegree(T));
+  for(i=1,#L,
+    my([u,v]=L[i]);
+    my(h = if(v, v^d*subst(T,x,u/v), pollead(T)*u^d));
+    if(h!=a, error([u,v]))); #L;
+}
+do(x^2+1,10^10)
+do(4*x^2+1,10^10)
+do(x^2+5,10^10)
+do(4*x^2+5,10^10)
+do(x^2+x+1,7*13*11^2*10^4)
+do(25*x^2+45*x+21,10^4)
+
+\\ short continued fraction [#1629]
+thue(-14*x^3+10*x^2+63*x-5,1)
+
+\\ round error
+thue(29*x^3+130*x^2-35*x-48,1)
+
+\\ #1630
+T=thueinit(10*x^3+6*x^2-41*x+8,1);
+thue(T,8)
+
+thue(-26*x^3+106*x^2+117*x-53,1)
+
+T=thueinit(8758*x^3 - 15667*x^2 - 10120*x - 23938,1);
+thue(T,1)
+
+P=-74*x^3+236*x^2+1500*x-469;
+thue(P,1)
+thue(thueinit(P,1),1)
diff --git a/src/test/in/valuation b/src/test/in/valuation
index 010c0f9..d6aab0f 100644
--- a/src/test/in/valuation
+++ b/src/test/in/valuation
@@ -1,12 +1,10 @@
 default(realprecision,38);
 a = [0, 1, 1/3, 1.0, Mod(1,2), Mod(1,3), ffgen(Mod(1,3)*(x^2+1)), 2*I, 3 + O(3^2), Mod(x,x^2+1), 2*x + 2, 3*(x +O(x^2)) ];
 b = [2, 3, x, x^2+1 ];
-oo = valuation(0, 2);
 {
 for (i = 1, #a,
   for(j = 1, #b,
     v = iferr(valuation(a[i],b[j]), E, "ERROR");
-    if (v == oo, v = "oo");
     print1(v, " ")
   );
   print()
@@ -15,6 +13,11 @@ for (i = 1, #a,
 valuation(0,1)
 valuation(0,-1)
 valuation(0,0)
+valuation(0,I)
+
+z=1+'x;
+valuation(Mod(z^2,z^3), z)
+valuation(y+O(y^2),x)
 
 \\ #1319
 s=Mod(1,3)*(1+x); valuation((s+O(x^2)) - s,x)
@@ -24,3 +27,6 @@ s=Mod(1,3)*(1+x); valuation((s+O(x^2)) - s,x)
 valuation(0*x,3) == oo
 
 1+O(x)-1
+poldegree(0)
+poldegree(Pol(Mod(0,3)))
+poldegree(0./x)
diff --git a/src/test/in/vararg b/src/test/in/vararg
new file mode 100644
index 0000000..a59f683
--- /dev/null
+++ b/src/test/in/vararg
@@ -0,0 +1,21 @@
+myprintsep(s,v[..])=if(#v>0,print1(v[1]);for(i=2,#v,print1(s,v[i])));print();
+print(myprintsep)
+?myprintsep
+print1(":");myprintsep()
+print1(":");myprintsep(", ")
+myprintsep(", ",a,b,c,d)
+myprintsep(", ",a,,c,)
+myprintsep(,a,b,c,d)
+
+myprintf = printf;
+myprintf("x=%d\n",5)
+myprintf("x=%d y=%d\n",5,7)
+myprintf("x=%d y=%d z=%d\n",5,7,9)
+
+default(strictargs,1)
+myprintsep(s,v[..])=if(#v>0,print1(v[1]);for(i=2,#v,print1(s,v[i])));print();
+print1(":");myprintsep()
+print1(":");myprintsep(", ")
+myprintsep(", ",a,b,c,d)
+myprintsep(,a,b,c,d)
+myprintsep(", ",a,,c,)
diff --git a/src/test/in/variable b/src/test/in/variable
index f053d13..5e71cf1 100644
--- a/src/test/in/variable
+++ b/src/test/in/variable
@@ -5,3 +5,22 @@ for(i=1,#v,
 )
 }
 variable()
+
+varhigher("y");
+tt=varlower("y");
+variable()
+zz=varhigher("y",x);
+variable()
+varhigher("y",zz);
+variable()
+varlower("y",zz);
+variable()
+varlower("y",tt);
+variable()
+varlower("tt",y);
+varhigher("y",y);
+variable()
+varhigher("zzz",y);1/0
+variable()
+variables([v,tt,zz])
+variables()
diff --git a/src/test/in/zn b/src/test/in/zn
index 001b1e9..3508e10 100644
--- a/src/test/in/zn
+++ b/src/test/in/zn
@@ -27,6 +27,11 @@ do(2^3*5^2*nextprime(10^10)^2)
 znlog(7,Mod(3,8),znorder(Mod(3,8)))
 znlog(7,Mod(3,8))
 znlog(0,Mod(3,4))
+znlog(0,Mod(3,4),1)
+znlog(1,Mod(3,4))
+znlog(1,Mod(3,4),1)
+znlog(0,Mod(2,4))
+znlog(0,Mod(2,4),1)
 znlog(6,Mod(2,7),znorder(Mod(2,7)))
 znlog(3,Mod(3,8),znorder(Mod(3,8)))
 znlog(5,Mod(2,401))
diff --git a/src/test/kerntest.c b/src/test/kerntest.c
index bcd7889..500ed12 100644
--- a/src/test/kerntest.c
+++ b/src/test/kerntest.c
@@ -1,21 +1,25 @@
 #include "pari.h"
 
 GEN   gen_0, gen_1, gen_m1, gen_2, gen_m2;
-THREAD pari_sp top, bot, avma;
+THREAD pari_sp avma;
 THREAD size_t memused = 0;
 ulong  DEBUGLEVEL,DEBUGMEM = 0;
 const double LOG10_2 = 0.;
 const long lontyp[] = {0};
 THREAD VOLATILE int PARI_SIGINT_block, PARI_SIGINT_pending;
+struct pari_mainstack * pari_mainstack;
 
 void mt_sigint_block(void) { }
 void mt_sigint_unblock(void) { }
+void new_chunk_resize(size_t x) {(void)x;}
 
 void specinit()
 {
   long size = 100000L;
-  bot = (pari_sp)malloc(size);
-  top = avma = bot + size;
+  pari_mainstack = malloc(sizeof(*pari_mainstack));
+  pari_mainstack->size = size;
+  pari_mainstack->bot = (pari_sp)malloc(size);
+  pari_mainstack->top = avma = pari_mainstack->bot + size;
   gen_0 = cgeti(2); affui(0, gen_0);
   gen_1 = utoipos(1);
   gen_m1= utoineg(1);
@@ -26,7 +30,8 @@ void specinit()
 void sorstring(ulong x)
 {
 #ifdef LONG_IS_64BIT
-  printf("%016lx  ", x);
+  if (x>>32) printf("%08lx  ", x>>32);
+  printf("%08lx  ", x & 0xFFFFFFFF);
 #else
   printf("%08lx  ", x);
 #endif
@@ -36,15 +41,15 @@ void _voiri(GEN x)
 {
   long i, lx = lgefint(x);
   GEN y = int_MSW(x);
-  /* sorstring(x[0]); depends on the kernel and contains no useful info */
-  sorstring(x[1]);
+  printf("signe: %ld, ",signe(x));
   for (i=2; i < lx; i++, y = int_precW(y)) sorstring(*y);
   printf("\n");
 }
 void _voirr(GEN x)
 {
   long i, lx = lg(x);
-  for (i=1; i < lx; i++) sorstring(x[i]);
+  printf("signe: %ld, expo: %ld, ",signe(x),expo(x));
+  for (i=2; i < lx; i++) sorstring(x[i]);
   printf("\n");
 }
 
diff --git a/src/test/tune.c b/src/test/tune.c
index e4c15c9..4d759dc 100644
--- a/src/test/tune.c
+++ b/src/test/tune.c
@@ -38,7 +38,7 @@ GEN LARGE_mod;
 
 typedef struct {
   ulong reps, type;
-  long *var, *var_disable, size, enabled;
+  long *var, *var_disable, *var_enable, var_enable_min,  size, enabled;
   GEN x, y;
   ulong l;
   GEN p;
@@ -57,6 +57,7 @@ typedef struct {
   double            step_factor; /* how much to step sizes (rounded down) */
   double            stop_factor;
   long              *var_disable;
+  long              *var_enable;
 } tune_param;
 
 /* ========================================================== */
@@ -125,13 +126,16 @@ rand_NFlx(long n, ulong l)
   return gerepileuptoleaf(av, x);
 }
 
-#define t_Fhx   99
-#define t_Flx  100
-#define t_Fl1x 101
-#define t_Fl2x 102
-#define t_NFlx 103
-#define t_FpX  104
-#define t_NFpX 105
+#define t_Fhx   100
+#define t_Flx   101
+#define t_Fl1x  102
+#define t_Fl2x  103
+#define t_NFhx  110
+#define t_NFlx  111
+#define t_NFl1x 112
+#define t_NFl2x 113
+#define t_FpX   200
+#define t_NFpX  210
 
 static GEN
 rand_g(long n, long type)
@@ -143,7 +147,10 @@ rand_g(long n, long type)
     case t_Flx:  return rand_Flx(n,DFLT_mod);
     case t_Fl1x: return rand_Flx(n,DFLT_mod1);
     case t_Fl2x: return rand_Flx(n,DFLT_mod2);
+    case t_NFhx: return rand_NFlx(n,DFLT_hmod);
     case t_NFlx: return rand_NFlx(n,DFLT_mod);
+    case t_NFl1x: return rand_NFlx(n,DFLT_mod1);
+    case t_NFl2x: return rand_NFlx(n,DFLT_mod2);
     case t_FpX:  return rand_FpX(n);
     case t_NFpX: return rand_NFpX(n);
   }
@@ -158,7 +165,10 @@ dftmod(speed_param *s)
     case t_Flx:  s->l=DFLT_mod;  return;
     case t_Fl1x: s->l=DFLT_mod1; return;
     case t_Fl2x: s->l=DFLT_mod2; return;
+    case t_NFhx: s->l=DFLT_hmod;  return;
     case t_NFlx: s->l=DFLT_mod;  return;
+    case t_NFl1x: s->l=DFLT_mod1;  return;
+    case t_NFl2x: s->l=DFLT_mod2;  return;
     case t_FpX:  s->p=LARGE_mod; return;
     case t_NFpX: s->p=LARGE_mod; return;
   }
@@ -176,6 +186,7 @@ dftmod(speed_param *s)
   return speed_endtime();                \
 }
 
+#define m_menable(s,var,min) (*(s->var)=minss(lg(s->x)-2,s->min))
 #define  m_enable(s,var) (*(s->var)=lg(s->x)-2)/* enable  asymptotically fastest */
 #define m_disable(s,var) (*(s->var)=lg(s->x)+1)/* disable asymptotically fastest */
 
@@ -183,12 +194,14 @@ static void enable(speed_param *s)
 {
   m_enable(s,var); s->enabled = 1;
   if (s->var_disable) m_disable(s,var_disable);
+  if (s->var_enable) m_menable(s,var_enable,var_enable_min);
 }
 
 static void disable(speed_param *s)
 {
   m_disable(s,var); s->enabled = 0;
   if (s->var_disable) m_disable(s,var_disable);
+  if (s->var_enable) m_menable(s,var_enable,var_enable_min);
 }
 
 static double speed_mulrr(speed_param *s)
@@ -251,6 +264,7 @@ static double speed_Flx_rem(speed_param *s) {
 static double speed_Flxq_red(speed_param *s) {
   GEN x = rand_NFlx((degpol(s->x)-1)*2, s->l);
   GEN q = Flx_get_red(s->x, s->l);
+  if(typ(q)==t_VECSMALL) err_printf("."); else err_printf("+");
   TIME_FUN(Flx_rem(x, q, s->l));
 }
 
@@ -330,10 +344,24 @@ static tune_param param[] = {
 {0,   var(Flx_SQR_SQRI_LIMIT),     t_Fl1x,5,0, speed_Flx_sqr},
 {0,   var(Flx_MUL_MULII2_LIMIT),   t_Fl2x,5,20000, speed_Flx_mul,0.05},
 {0,   var(Flx_SQR_SQRI2_LIMIT),    t_Fl2x,5,20000, speed_Flx_sqr,0.05},
-{0,   var(Flx_INVBARRETT_LIMIT),  t_NFlx,10,0, speed_Flx_inv,0.05},
+{0,  var(Flx_INVBARRETT_KARATSUBA_LIMIT), t_NFlx,5,20000,
+            speed_Flx_inv,0,0,&Fmod_MUL_MULII_LIMIT,&Flx_MUL_KARATSUBA_LIMIT},
+{0,  var(Flx_INVBARRETT_HALFMULII_LIMIT), t_NFhx,5,0,
+            speed_Flx_inv,0,0,NULL,&Flx_MUL_HALFMULII_LIMIT},
+{0,  var(Flx_INVBARRETT_MULII_LIMIT), t_NFl1x,5,0,
+            speed_Flx_inv,0,0,NULL,&Flx_MUL_MULII_LIMIT},
+{0,  var(Flx_INVBARRETT_MULII2_LIMIT),t_NFl2x,5,0,
+            speed_Flx_inv,0,0,NULL,&Flx_MUL_MULII2_LIMIT},
 {0,  var(Flx_DIVREM_BARRETT_LIMIT),t_NFlx,10,0, speed_Flx_divrem,0.05},
 {0,  var(Flx_REM_BARRETT_LIMIT),  t_NFlx,10,0, speed_Flx_rem,0.05},
-{0,  var(Flx_BARRETT_LIMIT),      t_NFlx,10,0, speed_Flxq_red},
+{0,  var(Flx_BARRETT_KARATSUBA_LIMIT), t_NFlx,5,0,
+            speed_Flxq_red,0,0,&Fmod_MUL_MULII_LIMIT,&Flx_MUL_KARATSUBA_LIMIT},
+{0,  var(Flx_BARRETT_HALFMULII_LIMIT), t_NFhx,5,0,
+            speed_Flxq_red,0,0,NULL,&Flx_MUL_HALFMULII_LIMIT},
+{0,  var(Flx_BARRETT_MULII_LIMIT), t_NFl1x,5,0,
+            speed_Flxq_red,0,0,NULL,&Flx_MUL_MULII_LIMIT},
+{0,  var(Flx_BARRETT_MULII2_LIMIT),t_NFl2x,5,0,
+            speed_Flxq_red,0,0,NULL,&Flx_MUL_MULII2_LIMIT},
 {0,  var(Flx_HALFGCD_LIMIT),       t_Flx,10,0, speed_Flx_halfgcd},
 {0,  var(Flx_GCD_LIMIT),           t_Flx,10,0, speed_Flx_gcd,0.1},
 {0,  var(Flx_EXTGCD_LIMIT),        t_Flx,10,0, speed_Flx_extgcd},
@@ -425,7 +453,7 @@ diag(const char *format, ...)
 }
 void
 print_define(const char *name, long value)
-{ printf("#define __%-25s  %5ld\n", name, value); }
+{ printf("#define __%-30s %ld\n", name, value); }
 
 long
 analyze_dat(int final)
@@ -478,11 +506,13 @@ Test(tune_param *param)
   DEFAULT(stop_factor, 1.2);
   DEFAULT(max_size, 10000);
   if (param->var_disable) save_var_disable = *(param->var_disable);
+  if (param->var_enable)  s.var_enable_min = *(param->var_enable);
 
   s.type = param->type;
   s.size = param->min_size;
   s.var  = param->var;
   s.var_disable  = param->var_disable;
+  s.var_enable  = param->var_enable;
   dftmod(&s);
   ndat = since_positive = since_change = thresh = 0;
   if (option_trace >= 1)
@@ -558,6 +588,7 @@ Test(tune_param *param)
   print_define(param->name, thresh);
   *(param->var) = thresh; /* set to optimal value for next tests */
   if (param->var_disable) *(param->var_disable) = save_var_disable;
+  if (param->var_enable) *(param->var_enable) = s.var_enable_min;
 }
 
 void error(char **argv) {
@@ -588,7 +619,7 @@ main(int argc, char **argv)
   DFLT_hmod = 257;
   DFLT_mod2 = 281474976710677UL;
 #else
-  DFLT_hmod = 17;
+  DFLT_hmod = 3;
   DFLT_mod1 = 1031UL;
 #endif
   v = new_chunk(argc);
diff --git a/src/whatnow b/src/whatnow
deleted file mode 100644
index f6f3b28..0000000
--- a/src/whatnow
+++ /dev/null
@@ -1,653 +0,0 @@
-!_
-#_
-%
-+_
--_
-O
-O(_^_)
-_!
-_!=_
-_%=_
-_%_
-_&&_
-_'
-_*=_
-_*_
-_++
-_+=_
-_+_
-_--
-_-=_
-_-_
-_.a1
-_.a2
-_.a3
-_.a4
-_.a6
-_.area
-_.b2
-_.b4
-_.b6
-_.b8
-_.bid
-_.bnf
-_.c4
-_.c6
-_.clgp
-_.codiff
-_.cyc
-_.diff
-_.disc
-_.e
-_.eta
-_.f
-_.fu
-_.futu
-_.gen
-_.group
-_.index
-_.j
-_.mod
-_.nf
-_.no
-_.omega
-_.orders
-_.p
-_.pol
-_.r1
-_.r2
-_.reg
-_.roots
-_.sign
-_.t2
-_.tate
-_.tu
-_.tufu
-_.zk
-_.zkst
-_/=_
-_/_
-_<<=_
-_<<_
-_<=_
-_<_
-_==_
-_>=_
-_>>=_
-_>>_
-_>_
-_[_.._,_.._]
-_[_.._]
-_\\/=_
-_\\/_
-_\\=_
-_\\_
-_^_
-_^s
-__
-_derivfun
-_eval_mnemonic
-_multi_if
-_void_if
-_||_
-_~
-Str
-abs
-acos
-acosh
-addell(e,z1,z2)=elladd(e,z1,z2);
-addprimes
-adj(x)=matadjoint(x);
-agm
-akell(e,n)=ellak(e,n);
-algdep
-algdep2(x,n,dec)=algdep(x,n,dec);
-algtobasis(nf,x)=nfalgtobasis(nf,x);
-allocatemem
-anell(e,n)=ellan(e,n);
-apell(e,n)=ellap(e,n);
-apell2(e,n)=ellap(e,n);
-apprpadic(x,a)=padicappr(x,a);
-arg
-asin
-asinh
-assmat(x)=matcompanion(x);
-atan
-atanh
-basis(x)=nfbasis(x);
-basis2(x)=nfbasis(x,2);
-basistoalg(nf,x)=nfbasistoalg(nf,x);
-bernreal
-bernvec
-bestappr
-bezout
-bezoutres
-bigomega
-bilhell(e,z1,z2)=ellbil(e,z1,z2);
-bin(x,y)=binomial(x,y);
-binary
-bittest
-boundcf(x,lmax)=contfrac(x,,lmax);
-boundfact(x,lim)=factor(x,lim);
-box(x,a)=plotbox(x,a);
-buchcertify(bnf)=bnfcertify(bnf);
-buchfu(bnf)=;
-buchgen(P)=;
-buchgenforcefu(P)=;
-buchgenfu(P)=;
-buchimag(D,c1,c2,g)=quadclassunit(D,,[c1,c2,g]);
-buchinit(P)=bnfinit(P,2);
-buchinitforcefu(P)=bnfinit(P,1);
-buchinitfu(P)=bnfinit(P);
-buchnarrow(bnf)=bnfnarrow(bnf);
-buchray(bnf,ideal)=bnrinit(bnf,ideal);
-buchrayinit(bnf,ideal)=bnrinit(bnf,ideal);
-buchrayinitgen(bnf,ideal)=bnrinit(bnf,ideal,1);
-buchreal(D)=quadclassunit(D);
-bytesize(x)=sizebyte(x);
-ceil
-centerlift
-cf(x)=contfrac(x);
-cf2(b,x)=contfrac(x,b);
-changevar=;
-char(x,y)=charpoly(x,y);
-char1(x,y)=charpoly(x,y,1);
-char2(x,y)=charpoly(x,y,2);
-chell(x,y)=ellchangecurve(x,y);
-chinese
-chptell(x,y)=ellchangepoint(x,y);
-classno(x)=qfbclassno(x);
-classno2(x)=qfbclassno(x,1);
-coeff(x,s)=polcoeff(x,s);
-color(w,c)=plotcolor(w,c);
-compimag(x,y)=x*y;
-compo(x,s)=component(x,s);
-compositum(pol1,pol2)=polcompositum(pol1,pol2);
-compositum2(pol1,pol2)=polcompositum(pol1,pol2,1);
-comprealraw(x,y)=qfbcompraw(x,y);
-concat
-conductor(a1)=bnrconductor(a1);
-conductorofchar(bnr,chi)=bnrconductorofchar(bnr,chi);
-conj
-conjvec
-content
-convol(x,y)=serconvol(x,y);
-core
-core2(x)=core(x,1);
-coredisc
-coredisc2(x)=coredisc(x,1);
-cos
-cosh
-cursor(w)=plotcursor(w);
-cvtoi(x)=truncate(x,&e);
-cyclo(n)=polcyclo(n);
-decodefactor(fa)=factorback(fa);
-decodemodule(nf,fa)=bnfdecodemodule(nf,fa);
-default
-degree(x)=poldegree(x);
-denom(x)=denominator(x);
-deplin(x)=lindep(x,-1);
-deriv
-det(x)=matdet(x);
-det2(x)=matdet(x,1);
-detint(x)=matdetint(x);
-diagonal(x)=matdiagonal(x);
-dilog
-dirdiv
-direuler
-dirmul
-dirzetak
-disc(x)=poldisc(x);
-discf(x)=nfdisc(x);
-discf2(x)=nfdisc(x,2);
-discrayabs(bnr,subgroup)=bnrdisc(bnr,subgroup);
-discrayabscond(bnr)=bnrdisc(bnr,,,2);
-discrayabslist(bnf,list)=bnrdisclist(bnf,list);
-discrayabslistarch(bnf,arch,bound)=bnrdisclist(bnf,bound,arch);
-discrayabslistarchall(bnf,bound)=bnrdisclist(bnf,bound,,1);
-discrayabslistlong(bnf,bound)=bnrdisclist(bnf,bound);
-discrayrel(bnr,subgroup)=bnrdisc(bnr,subgroup,,1);
-discrayrelcond(bnr,subgroup)=bnrdisc(bnr,subgroup,,3);
-divisors
-divres(x,y)=divrem(x,y);
-divsum(n,X,expr)=sumdiv(n,X,expr);
-draw(list)=plotdraw(list);
-eigen(x)=mateigen(x);
-eint1
-erfc
-eta
-euler=Euler;
-eval
-exp
-extract(x,y)=vecextract(x,y);
-fact(x)=factorial(x);
-factcantor(x,p)=factorcantor(x,p);
-factfq(x,p,a)=factorff(x,p,a);
-factmod(x,p)=factormod(x,p);
-factor
-factoredbasis(x,p)=nfbasis(x,,p);
-factoreddiscf(x,p)=nfdisc(x,,p);
-factoredpolred(x,p)=polred(x,,p);
-factoredpolred2(x,p)=polred(x,2,p);
-factornf
-factorpadic
-factorpadic2(x,p,r)=factorpadic(x,p,r,1);
-factpol(x,l,hint)=factor(x);
-factpol2(x,l,hint)=factor(x);
-fibo(x)=fibonacci(x);
-floor
-for
-fordiv
-forprime
-forstep
-forvec
-fpn(p,n)=ffinit(p,n);
-frac
-galois(x)=polgalois(x);
-galoisapply(nf,aut,x)=nfgaloisapply(nf,aut,x);
-galoisconj(nf)=nfgaloisconj(nf);
-galoisconj1(nf)=nfgaloisconj(nf,2);
-galoisconjforce=nfgaloisconj(nf,1);
-gamh(x)=gammah(x);
-gamma
-gauss(a,b)=matsolve(a,b);
-gaussmodulo(M,D,Y)=matsolvemod(M,D,Y);
-gaussmodulo2(M,D,Y)=matsolvemod(M,D,Y,1);
-gcd
-getheap
-getrand
-getstack
-gettime
-globalred(x,y)=ellglobalred(x,y);
-goto=;
-hclassno(x)=qfbhclassno(x);
-hell(e,x)=ellheight(e,x);
-hell2(e,x)=ellheight(e,x,1);
-hermite(x)=mathnf(x);
-hermite2(x)=mathnf(x,1);
-hermitehavas(x)=;
-hermitemod(x,d)=mathnfmod(x,d);
-hermitemodid(x,d)=mathnfmodid(x,d);
-hermiteperm(x)=mathnf(x,3);
-hess(x)=mathess(x);
-hilb(x,y)=hilbert(x,y);
-hilbert(n)=mathilbert(n);
-hilbp(x,y,p)=hilbert(x,y,p);
-hvector(n,X,expr)=vector(n,X,expr);
-hyperu
-i=I;
-idealadd
-idealaddmultone(nf,list)=idealaddtoone(nf,list);
-idealaddone(nf,x,y)=idealaddtoone(nf,x,y);
-idealappr
-idealapprfact(nf,x)=idealappr(nf,x,1);
-idealchinese
-idealcoprime
-idealdiv
-idealdivexact(nf,x,y)=idealdiv(nf,x,y,1);
-idealfactor
-idealhermite(nf,x)=idealhnf(nf,x);
-idealhermite2(nf,x)=idealhnf(nf,x);
-idealintersect
-idealinv
-idealinv2(nf,x)=idealinv(nf,x,1);
-ideallist
-ideallistarch
-ideallistarchgen(nf,list,arch)=ideallistarch(nf,list,arch);
-ideallistunit(nf,list)=ideallist(nf,list,2);
-ideallistunitarch=ideallistarch(nf,list,arch);
-ideallistunitarchgen=ideallistarch(nf,list,arch);
-ideallistunitgen=ideallist(nf,list,3);
-ideallistzstar(nf,bound)=ideallist(nf,bound);
-ideallistzstargen(nf,bound)=ideallist(nf,bound,1);
-ideallllred(nf,x,vdir)=idealred(nf,x,vdir);
-idealmul
-idealmulred(nf,x,y)=idealmul(nf,x,y,1);
-idealnorm
-idealpow
-idealpowred(nf,x,y)=idealpow(nf,x,y,1);
-idealtwoelt
-idealtwoelt2(nf,x,a)=idealtwoelt(nf,x,a);
-idealval
-idmat(n)=matid(n);
-if
-imag
-image(x)=matimage(x);
-image2(x)=matimage(x,1);
-imagecompl(x)=matimagecompl(x);
-incgam
-incgam1(s,x)=;
-incgam2(s,x)=;
-incgam3(s,x)=;
-incgam4(s,x,y)=incgam(s,x,y);
-indexrank(x)=matindexrank(x);
-indsort(x)=vecsort(x,,1);
-initalg(pol)=nfinit(pol);
-initalgred(x)=nfinit(x,2);
-initalgred2(x)=nfinit(x,3);
-initell(x)=ellinit(x);
-initrect(w,x,y)=plotinit(w,x,y);
-initzeta(x)=zetakinit(x);
-integ(x,y)=intformal(x,y);
-intersect(x,y)=matintersect(x,y);
-intgen(x=a,b,s)=intnum(x=a,b,s,1);
-intinf(x=a,b,s)=intnum(x=a,b,s,2);
-intnum
-intopen(x=a,b,s)=intnum(x=a,b,s,3);
-inverseimage(x,y)=matinverseimage(x,y);
-isdiagonal(x)=matisdiagonal(x);
-isfund(x)=isfundamental(x);
-isideal(nf,x)=nfisideal(nf,x);
-isincl(x,y)=nfisincl(x,y);
-isinclfast(nf1,nf2)=nfisincl(nf1,nf2,1);
-isirreducible(x)=polisirreducible(x);
-isisom(x,y)=nfisisom(x,y);
-isisomfast(x,y)=nfisisom(x,y);
-isoncurve(e,x)=ellisoncurve(e,x);
-isprime
-isprincipal(bnf,x)=bnfisprincipal(bnf,x,0);
-isprincipalforce(bnf,x)=bnfisprincipal(bnf,x,2);
-isprincipalgen(bnf,x)=bnfisprincipal(bnf,x);
-isprincipalgenforce(bnf,x)=bnfisprincipal(bnf,x,3);
-isprincipalray(bnf,x)=bnrisprincipal(bnf,x);
-isprincipalraygen
-ispsp(x)=ispseudoprime(x);
-isqrt(x)=sqrtint(x);
-isset(x)=setisset(x);
-issqfree(x)=issquarefree(x);
-issquare
-isunit(bnf,x)=bnfisunit(bnf,x);
-jacobi(x)=qfjacobi(x);
-jbesselh(n,x)=besseljh(n,x);
-jell(x)=ellj(x);
-karamul(x,y,k)=;
-kbessel(nu,x)=besselk(nu,x);
-kbessel2(nu,x)=besselk(nu,x);
-ker(x)=matker(x);
-keri(x)=matker(x,1);
-kerint(x)=matkerint(x);
-kerint1(x)=matkerint(x,1);
-kerint2(x)=;
-kill
-killrect(w)=plotkill(w);
-kro(x,y)=kronecker(x,y);
-label=;
-lambdak(nfz,s)=zetak(nfz,s,1);
-laplace(x)=serlaplace(x);
-lcm
-legendre(n)=pollegendre(n);
-length
-lex
-lexsort(x)=vecsort(x,,2);
-lift
-lindep
-lindep2(x)=lindep(x,1);
-line(w,x2,y2)=plotlines(w,x2,y2);
-lines(w,x2,y2)=plotlines(w,x2,y2);
-lll(x)=qflll(x);
-lll1(x)=;
-lllgen(x)=qflll(x,8);
-lllgram(x)=qflllgram(x);
-lllgram1(x)=;
-lllgramgen(x)=qflllgram(x,8);
-lllgramint(x)=qflllgram(x,1);
-lllgramkerim(x)=qflllgram(x,4);
-lllgramkerimgen(x)=qflllgram(x,5);
-lllint(x)=qflll(x,1);
-lllintpartial(x)=qflll(x,2);
-lllkerim(x)=qflll(x,4);
-lllkerimgen(x)=qflll(x,5);
-lllrat(x)=;
-ln(x)=log(x);
-lngamma
-localred(e)=elllocalred(e);
-log
-logagm(x)=log(x,1);
-lseriesell(e,s,N,A)=elllseries(e,s,A);
-makebigbnf(sbnf)=bnfinit(sbnf);
-mat(x)=Mat(x);
-matextract(x,y,z)=vecextract(x,y,z);
-mathell(e,x)=ellheightmatrix(e,x);
-matrix
-matrixqz
-matrixqz2(x,p)=matrixqz(x,-1);
-matrixqz3(x,p)=matrixqz(x,-2);
-matsize
-max
-min
-minideal(nf,ix,vdir)=idealmin(nf,ix,vdir);
-minim(x,bound,maxnum)=qfminim(x,bound,maxnum);
-minim2(x,bound)=qfminim(x,bound,,1);
-mod(x,y)=Mod(x,y);
-modp(x,y,p)=Mod(x,y);
-modreverse
-modulargcd(x,y)=gcd(x,y,1);
-move(w,x,y)=plotmove(w,x,y);
-mu(n)=moebius(n);
-newtonpoly
-nextprime
-nfdetint
-nfdiv(nf,a,b)=nfeltdiv(nf,a,b);
-nfdiveuc(nf,a,b)=nfeltdiveuc(nf,a,b);
-nfdivres(nf,a,b)=nfeltdivrem(nf,a,b);
-nfhermite(nf,x)=nfhnf(nf,x);
-nfhermitemod(nf,x,detx)=nfhnfmod(nf,x,detx);
-nfmod(nf,a,b)=nfeltmod(nf,a,b);
-nfmul(nf,a,b)=nfeltmul(nf,a,b);
-nfpow(nf,a,k)=nfeltpow(nf,a,k);
-nfreduce(nf,a,id)=nfeltreduce(nf,a,id);
-nfsmith(nf,x)=nfsnf(nf,x);
-nfval(nf,a,pr)=nfeltval(nf,a,pr);
-norm
-norml2
-nucomp(x,y,l)=qfbnucomp(x,y,l);
-numdiv
-numer(x)=numerator(x);
-nupow(x,n)=qfbnupow(x,n);
-o(x)=O(x);
-omega
-ordell(e,x)=ellordinate(e,x);
-order(x)=znorder(x);
-orderell(e,x)=ellorder(e,x);
-ordred(x)=polredord(x);
-padicprec
-pascal(n)=matpascal(n);
-perf(a)=qfperfection(a);
-permutation(n,k)=numtoperm(n,k);
-permutation2num(vect)=permtonum(vect);
-pf(x,p)=qfbprimeform(x,p);
-phi(x)=eulerphi(x);
-pi=Pi;
-plot
-ploth
-ploth2(X=a,b,expr)=ploth(X=a,b,expr,1);
-plothmult(X=a,b,expr)=ploth(X=a,b,expr);
-plothraw
-pnqn(x)=contfracpnqn(x);
-point(w,x,y)=plotpoints(w,x,y);
-pointell(e,z)=ellztopoint(e,z);
-points(w,x,y)=plotpoints(w,x,y);
-polint(xa,ya,x)=polinterpolate(xa,ya,p);
-polred
-polred2(x)=polred(x,2);
-polredabs
-polredabs2(x)=polredabs(x,1);
-polredabsall(x)=polredabs(x,4);
-polredabsfast(x)=polredabs(x,8);
-polredabsnored(x)=polredabs(x,2);
-polsym
-polvar(x)=variable(x);
-poly(x,v)=Pol(x,v);
-polylog
-polylogd(m,x)=polylog(m,x,1);
-polylogdold(m,x)=polylog(m,x,2);
-polylogp(m,x)=polylog(m,x,3);
-polyrev(x,v)=Polrev(x,v);
-polzag(n,m)=polzagier(n,m);
-postdraw(list)=psdraw(list);
-postploth(X=a,b,expr)=psploth(X=a,b,expr);
-postploth2(X=a,b,expr)=psploth(X=a,b,expr,1);
-postplothraw(listx,listy)=psplothraw(listx,listy);
-powell(e,x,n)=ellmul(e,x,n);
-powrealraw(x,n)=qfbpowraw(x,n);
-pprint(x)=;
-pprint1(x)=;
-prec(x,n)=precision(x,n);
-precision
-prime
-primedec(nf,p)=idealprimedec(nf,p);
-primes
-primroot(n)=znprimroot(n);
-principalideal(nf,x)=;
-principalidele(nf,x)=;
-print
-print1
-prod(x,X=a,b,expr)=prod(X=a,b,expr,x);
-prodeuler
-prodinf
-prodinf1(X=a,expr)=prodinf(X=a,expr,1);
-psi
-qfi(a,b,c)=Qfb(a,b,c);
-qfr(a,b,c,d)=Qfb(a,b,c,d);
-quaddisc
-quadgen
-quadpoly
-random
-rank(x)=matrank(x);
-rayclassno(bnf,x)=bnrclassno(bnf,x);
-rayclassnolist(bnf,liste)=bnrclassnolist(bnf,liste);
-rbox(w,dx,dy)=plotrbox(w,dx,dy);
-read(x)=input(x);
-real
-recip(x)=polrecip(x);
-redimag(x)=qfbred(x);
-redreal(x)=qfbred(x);
-redrealnod(x,d)=qfbred(x,2,,d);
-reduceddisc(f)=poldiscreduced(f);
-regula(x)=quadregulator(x);
-reorder=;
-resultant(x,y)=polresultant(x,y);
-resultant2(x,y)=polresultant(x,y,1);
-reverse(x)=serreverse(x);
-rhoreal(x)=qfbred(x,1);
-rhorealnod(x,d)=qfbred(x,3,,d);
-rline(w,dx,dy)=plotrline(w,dx,dy);
-rlines(w,dx,dy)=plotrlines(w,dx,dy,1);
-rmove(w,dx,dy)=plotrmove(w,dx,dy);
-rndtoi(x)=round(x,&e);
-rnfbasis
-rnfdiscf(nf,pol)=rnfdisc(nf,pol);
-rnfequation
-rnfequation2(nf,pol)=rnfequation(nf,pol,1);
-rnfhermitebasis(bnf,order)=rnfhnfbasis(bnf,order);
-rnfisfree
-rnflllgram
-rnfpolred
-rnfpseudobasis
-rnfsteinitz
-rootmod(x,p)=polrootsmod(x,p);
-rootmod2(x,p)=polrootsmod(x,p,1);
-rootpadic(x,p,r)=polrootspadic(x,p,r);
-roots(x)=polroots(x);
-rootsof1(nf)=nfrootsof1(nf);
-rootsold(x)=;
-round
-rounderror(x)=round(x,&e);
-rpoint(w,dx,dy)=plotrpoint(w,dx,dy);
-rpoints(w,dx,dy)=plotrpoints(w,dx,dy);
-scale(w,x1,x2,y1,y2)=plotscale(w,x1,x2,y1,y2);
-series(x,v)=Ser(x,v);
-set(x)=Set(x);
-setintersect
-setminus
-setprecision(n)=default(realprecision,n);
-setrand
-setsearch
-setserieslength(n)=default(seriesprecision,n);
-settype(x,t)=type(x,t);
-setunion
-shift
-shiftmul
-sigma
-sigmak(k,x)=sigma(x,k);
-sign
-signat(x)=qfsign(x);
-signunit(bnf)=bnfsignunit(bnf);
-simplefactmod(x,p)=factormod(x,p,1);
-simplify
-sin
-sinh
-size(x)=sizedigit(x);
-smallbasis(x)=nfbasis(x,1);
-smallbuchinit(x)=bnfcompress(x);
-smalldiscf(x)=nfdisc(x,1);
-smallfact(x)=factor(x,0);
-smallinitell(x)=ellinit(x,1);
-smallpolred(x)=polred(x,1);
-smallpolred2(x)=polred(x,3);
-smith(x)=matsnf(x);
-smith2(x)=matsnf(x,1);
-smithclean(x)=matsnf(x,4);
-smithpol(x)=matsnf(x,2);
-solve
-sort(x)=vecsort(x);
-sqr
-sqred(x)=qfgaussred(x);
-sqrt
-srgcd(x,y)=gcd(x,y,2);
-string(w,x)=plotstring(w,x);
-sturm(x)=polsturm(x);
-sturmpart(x,a,b)=polsturm(x,a,b);
-subcyclo(p,d)=polsubcyclo(p,d);
-subell(e,a,b)=ellsub(e,a,b);
-subst
-sum(x,X=a,b,expr)=sum(X=a,b,expr,x);
-sumalt
-sumalt2(X=a,expr)=sumalt(X=a,expr,1);
-suminf
-sumpos
-sumpos2(X=a,expr)=sumpos(X=a,expr,1);
-supplement(x)=matsupplement(x);
-sylvestermatrix(x,y)=polsylvestermatrix(x,y);
-system
-tan
-tanh
-taniyama(e)=elltaniyama(e);
-taylor
-tchebi(n)=polchebyshev(n);
-teich(x)=teichmuller(x);
-texprint(x)=printtex(x);
-theta
-thetanullk
-threetotwo2=;
-threetotwo=;
-torsell(e)=elltors(e);
-trace
-trans(x)=mattranspose(x);
-trunc(x)=truncate(x);
-tschirnhaus(x)=poltschirnhaus(x);
-twototwo(nf,a,b)=;
-type
-unit(x)=quadunit(x);
-until
-valuation
-vec(x)=Vec(x);
-vecindexsort(x)=vecsort(x,,1);
-veclexsort(x)=vecsort(x,,2);
-vecmax
-vecmin
-vecsort
-vector
-vvector(n,X,expr)=vectorv(n,X,expr);
-weipell(e)=ellwp(e);
-wf(x)=weber(x);
-wf2(x)=weber(x,2);
-while
-zell(e,P)=ellpointtoz(e,P);
-zeta
-zetak
-zideallog(nf,x,bid)=ideallog(nf,x,bid);
-zidealstar(nf,I)=idealstar(nf,I);
-zidealstarinit(nf,id)=idealstar(nf,id,1);
-zidealstarinitgen(nf,id)=idealstar(nf,id,2);
-znstar

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/pari-sage.git



More information about the debian-science-commits mailing list